InputStream && OutputStream

Posted nicewuranran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了InputStream && OutputStream相关的知识,希望对你有一定的参考价值。

InputStream && OutputStream


介绍

IO流操作中非常重要的一组接口(其实是抽象类)是InputStream和OutputStream。

InputStream字节输入流其最核心的一个方法是read()方法
OutputStream字节输出流其最核心的一个方法是write()方法

所有字节输入输都要实现read方法,所有字节输出流都要实现write()方法。
字节流可以操作任意类型的文件(二进制或文本文件)

首先了解几个概念:

01机器码:只有机器才能识别0101串
字节:拿英文来说明就是英文字符所对应的ASCII码(a==>97)
字符:就是我们人类能识别的字符文字
备注:每种语言有自己对应的字节码比如英文一个字符只占一个字节(ASCII编
码),但是中文可能就会占两个字节(gbk/gb2312)或三个字节(utf-8)取决于使用何种编码格式。

InputStream抽象类研究

InputStream核心Code

    /**
     * This abstract class is the superclass of all classes representing
     * an input stream of bytes.
     *
     * Applications that need to define a subclass of InputStream
     * must always provide a method that returns the next byte of input.
     */
    public abstract class InputStream implements Closeable {

        /**
         * Reads the next byte of data from the input stream. The value byte is
         * returned as an int in the range 0 to
         * 255. If no byte is available because the end of the stream
         * has been reached, the value -1 is returned. This method
         * blocks until input data is available, the end of the stream is detected,
         * or an exception is thrown.
         *
         * A subclass must provide an implementation of this method.
         */
        public abstract int read() throws IOException;//核心方法

        /**
         * Reads some number of bytes from the input stream and stores them into
         * the buffer array b. The number of bytes actually read is
         * returned as an integer.  This method blocks until input data is
         * available, end of file is detected, or an exception is thrown.
         *
         * If the length of b is zero, then no bytes are read and
         * 0 is returned; otherwise, there is an attempt to read at
         * least one byte. If no byte is available because the stream is at the
         * end of the file, the value -1 is returned; otherwise, at
         * least one byte is read and stored into b.
         *
         * The first byte read is stored into element b[0], the
         * next one into b[1], and so on. The number of bytes read is,
         * at most, equal to the length of b. Let k be the
         * number of bytes actually read; these bytes will be stored in elements
         * b[0] through b[k-1],
         * leaving elements b[k] through
         * b[b.length-1] unaffected.
         */
        public int read(byte b[]) throws IOException {
            return read(b, 0, b.length);
        }

        //理解下面代码块
        public int read(byte b[], int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if (off < 0 || len < 0 || len > b.length - off) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }

            int c = read();
            if (c == -1) {
                return -1;
            }
            b[off] = (byte)c;

            int i = 1;
            try {
                for (; i < len ; i++) {
                    c = read();
                    if (c == -1) {
                        break;
                    }
                    b[off + i] = (byte)c;
                }
            } catch (IOException ee) {
            }
            return i;
        }

        /**
         * Closes this input stream and releases any system resources associated
         * with the stream.
         */
        public void close() throws IOException {}

    //备注:最重要的是理解read()方法和read(byte[] bytes)方法

}

典型模板代码

@Test
public void testReadFile() throws Exception {

    String SEPARATOR = File.separator;
    File file = new File("E:" + SEPARATOR + "io" + SEPARATOR + "test.txt");
    // 获得输入流
    FileInputStream inputStream = new FileInputStream(file);

    // 定义缓存字节数组
    byte[] buffer = new byte[1024];
    int length = 0;// 表示实际读取字节数组缓冲的字节数目
    while ((length = inputStream.read(buffer)) != -1) {
        System.out.print(new String(buffer, 0, length, "utf-8"));
        // 输出文件到控制台时最好不要使用ln换行打印,否则如果数组长度定义不恰当是可能出现问题的.
    }
    // 流资源关闭
    inputStream.close();

}

OutputStream抽象类研究

OutputStream核心Code

/**
 * This abstract class is the superclass of all classes representing
 * an output stream of bytes. An output stream accepts output bytes
 * and sends them to some sink.
 * 
 * Applications that need to define a subclass of
 * OutputStream must always provide at least a method
 * that writes one byte of output.
 */
public abstract class OutputStream implements Closeable, Flushable {
        /**
         * Writes the specified byte to this output stream. The general
         * contract for write is that one byte is written
         * to the output stream. The byte to be written is the eight
         * low-order bits of the argument b. The 24
         * high-order bits of b are ignored.
         * 
         * Subclasses of OutputStream must provide an
         * implementation for this method.
         *
         */
        public abstract void write(int b) throws IOException;

        /**
         * Writes b.length bytes from the specified byte array
         * to this output stream. The general contract for write(b)
         * is that it should have exactly the same effect as the call
         * write(b, 0, b.length).
         */
        public void write(byte b[]) throws IOException {
            write(b, 0, b.length);
        }

        /**
         * Writes len bytes from the specified byte array
         * starting at offset off to this output stream.
         * The general contract for write(b, off, len) is that
         * some of the bytes in the array b are written to the
         * output stream in order; element b[off] is the first
         * byte written and b[off+len-1] is the last byte written
         * by this operation.
         * <p>
         * The write method of OutputStream calls
         * the write method of one argument on each of the bytes to be
         * written out. Subclasses are encouraged to override this method and
         * provide a more efficient implementation.
         */
        public void write(byte b[], int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if ((off < 0) || (off > b.length) || (len < 0) ||
                       ((off + len) > b.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return;
            }
            for (int i = 0 ; i < len ; i++) {
                write(b[off + i]);
            }
        }

        /**
         * Flushes this output stream and forces any buffered output bytes
         * to be written out. The general contract of flush is
         * that calling it is an indication that, if any bytes previously
         * written have been buffered by the implementation of the output
         * stream, such bytes should immediately be written to their
         * intended destination.
         * 
         * If the intended destination of this stream is an abstraction provided by
         * the underlying operating system, for example a file, then flushing the
         * stream guarantees only that bytes previously written to the stream are
         * passed to the operating system for writing; it does not guarantee that
         * they are actually written to a physical device such as a disk drive.
         *
         * The flush method of OutputStream does nothing..
         */
        public void flush() throws IOException {
        }

        /**
         * Closes this output stream and releases any system resources
         * associated with this stream. The general contract of close
         * is that it closes the output stream. A closed stream cannot perform
         * output operations and cannot be reopened.
         */
        public void close() throws IOException {
        }

}
//有一位计算机科学家说缓存思想是20世纪计算机发展最重要的思想

典型模板代码

@Test
public void testFileOutputStream() throws Exception {

        String SEPARATOR = File.separator;
        File file = new File("E:" + SEPARATOR + "io" + SEPARATOR + "out.txt");
        // 定义输出流
        FileOutputStream out = new FileOutputStream(file);
        // 向输出流中写入数据
        out.write("helloworld 你好世界".getBytes("utf-8"));
        out.close();

        // 备注使用OutputStream由于没有缓存,所以不需要调用flush方法就直接写入到文件中。
}

文件考本

说明:文件考本这里涉及到源和目标其实这样就可以推广到网络上文件传输
也是一样的,都是有输入流和输出流,IO流操作弄清楚源和目标以及输入输
出流和方向时那么问题就简单了模型就清楚了。

Code

@Test
public void testCopyFile() throws Exception {

    String SEPARATOR = File.separator;
    // 源文件
    File source = new File("E:" + SEPARATOR + "io" + SEPARATOR + "1.png");
    // 获得输入流
    FileInputStream inputStream = new FileInputStream(source);

    // 输出(目标)文件
    File copyFile = new File("E:" + SEPARATOR + "io" + SEPARATOR + "copy.png");
    // 定义输出流
    FileOutputStream outputStream = new FileOutputStream(copyFile);

    // 定义缓冲字节数组
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = inputStream.read(buffer)) != -1) {// 只要输入流还有字节那么输出流就一直写入数据
        outputStream.write(buffer, 0, length);
    }
    outputStream.close();
    inputStream.close();

    // 备注:解释缓冲字节数组,通常缓冲字节数组都是对于输入流而言的,可以那么理解,
    // 当输入流读一个文件的时候,原先是读一个字节就往输出流写一个字节,这样相对比较浪费时间,
    // 所以就可以读一定量的字节存放到一个数组中,当数组满了之后然后将这个数组中所有字节输入到输出流中,然后清空数组继续读取字节。以此循环

}

以上是关于InputStream && OutputStream的主要内容,如果未能解决你的问题,请参考以下文章

ava.io.InputStream & java.io.FileInputStream

InputStream & OutputStream 使用方法以及注意事项

Java IO流--InputStream(字节输入流) & OutputStream(字节输出流)

InputStream 的自定义实现

有没有办法使用 Guava 获取 InputStream 的哈希码?

导入导出