字节流

概述

在 Java API 中,可以从其中读入一个字节序列的对象称做输入流InputStream,而可以向其中写入一个字节序列的对象称做输出流OutputStream

输入流 InputStream

package java.io;

public abstract class InputStream implements Closeable {

    // MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to use when skipping.
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;

    /**
     * 从数据中读入一个字节,并返回该字节,或者在遇到输入流结尾时返回-1。
     */
    public abstract int read() throws IOException;

    /**
     * 读入一个字节数组,并返回实际读入的字节数,或者在遇到输入流结尾时返回-1。
     * 最多读入b.length个字节
     */
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }

    /**
     * 读入一个字节数组,并返回实际读入的字节数,或者在遇到输入流结尾时返回-1。
     * off: 第一个读入字节应该被放置的位置在b中的偏移量。
     * len: 读入字节的最大数量。
     */
    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;
    }

    /**
     * 返回在不阻塞的情况下可获取的字节数(阻塞意味着当前线程将失去它对资源的占用)。
     */
    public int available() throws IOException {
        return 0;
    }

    /**
     * 关闭这个输入流
     */
    public void close() throws IOException {}

    /**
     * 在输入流的当前位置打一个标记(并非所有的流都支持这个特性)。
     * 如果从输入流中已经读入的字节多于readlimit个,则这个流允许忽略这个标记。
     */
    public synchronized void mark(int readlimit) {}

    /**
     * 返回到最后一个标记,随后对read的调用将重新读入这些字节。
     * 如果当前没有任何标记,则这个流不被重置。
     */
    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

    /**
     * 如果这个流支持打标记,返回true。
     */
    public boolean markSupported() {
        return false;
    }
}

输出流 OutputStream

package java.io;

public abstract class OutputStream implements Closeable, Flushable {

    /**
     * 写出一个字节的数据。
     */
    public abstract void write(int b) throws IOException;

    /**
     * 写出所有字节到数组b中。
     */
    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }

    /**
     * 写出某个范围的字节到数组b中。
     * off: 第一个写出字节在b中的偏移量。
     * len: 写换粗字节的最大数量。
     */
    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]);
        }
    }

    /**
     * 冲刷输出流,将所有缓冲区中的数据发送到目的地。
     */
    public void flush() throws IOException {}

    /**
     * 冲刷并关闭输出流。
     */
    public void close() throws IOException {}
}

注意

read和write方法在执行时都将阻塞,直至字节确实被读入或写出。这就意味着如果流不能被立即访问(通常是因为网络忙),那么当前的线程将被阻塞。这使得在这两个方法等待指定的流变为可用的这段时间里,其他的线程就有机会去执行有用的工作。

当你完成输入/输出流的读写时,应该通过调用close方法关闭它,这个调用会释放掉十分有限的操作系统资源。 如果一个应用程序打开了过多的输入/输出流而没有关闭,那么系统资源将被耗尽。关闭一个输出流的同时还会冲刷用于该输出流的缓冲区:所有被临时置于缓冲区中,以便用更大的包的形式传递的字节在关闭输出流时都将被送出。特别是,如果不关闭文件,那么写出字节的最后一个包可能将永远也得不到传递。当然,我们可以使用flush方法来人为地冲刷这些输出。

参考资料

  • Java 核心技术 卷II 第2章 输入与输出
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值