Java核心技术:输入与输出——输入输出流

抽象类InputStreamOutputStream构成了输出/输出(I/O)类层次结构的基础。

读写字节

InputStream类有一个抽象方法:

abstract int read()

这个方法将读入一个字节,并返回读入的字节,或者在遇到输入源结尾时返回-1。
在设计具体的输入流类时,必须覆盖这个方法以提供适用的功能。


InputStream类还有若干非抽象的方法,可以读入一个字节数组,或者跳过大量的字节。这些方法都要调用抽象的read方法,因此,各个子类都只需覆盖这个方法。

public abstract class InputStream implements Closeable {
	public abstract int read() throws IOException;
	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;
    }
	
	public long skip(long n) throws IOException {

        long remaining = n;
        int nr;

        if (n <= 0) {
            return 0;
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }
}

与此类似,OutputStream类定义了下面的抽象方法:

abstract void write(int b);

它可以向某个输出位置写入一个字节。


readwrite方法在执行时都将阻塞,知道字节确实被读入或写出。
```available`方法检查当前可读入的字节数量,下面的代码不可能被阻塞:

int bytesAvaliable = in.available();
if (bytesAvailable >0)
{
	byte[] data = new byte[bytesAvailable];
	in.read(data);
}

当完成对输入/输出流的读写时,应该通过调用close方法来关闭它。

  • 这个调用会释放操作系统资源
  • 还会冲刷用于该输出流的缓冲区
    如果不关闭文件,写出字节的最后一个包可能得不到传递。可以使用flush方法来认为地冲刷这些输出。
    InputStream
    OutputStream

完整的流家族

InputStream
OutputStream
流家族按照使用方法划分,分为处理字节和字符的两个单独层次结构。

  • InputStreamOutputStream可以读写单个字节或字节数组,构成层级结构的基础。
  • DataInputStreamDataOutputStream可以以二进制格式读写所有基本Java类型,提供读写字符串和数字更强大的功能。
  • ZipInputStreamZipOutputStream等包含了很多有用的功能。

对于Unicode文本,可以使用抽象类ReaderWriter的子类。
Readerread方法将返回一个Unicode码元(一个在0~65535之间的整数),或者在碰到文件结尾时返回-1。
Writerwrite方法写入一个Unicode码元。
Reader

Writer

还有4各附加接口:Closeable,Flushable,Readable,Appenable
Interface

  • Closeable接口:
void close() throw IOException
  • Flushable接口:
void flush()
  • Readable接口:
int read(CharBuffer cb)
  • Appendable接口
Appendable append(Char c)
Appendable append(CharSequence s)

CharBuffer表示一个内存中的缓冲区或者一个内存映像的文件。
CharSequence接口描述了一个char值序列的基本属性
CharSequence

组合输入/输出过滤器

FileInputStreamFileOutputStream可以提供附着在一个磁盘文件上的输入流和输出流。

FileInputStream fin = new FileInputStream("employee.dat")

所有在java.io中的类都将相对路基那个解释为以用户工作目录开始,可以调用System.getProperty("user.dir")类获取
DataInputStream可以读入数值类型,但没有任何从文件中获取数据的方法。

DataInputStream din = ...;
double x = din.readDouble();

Java使用组合的方式分类这种指责:

  • 某些输入流(例如FileInputStream和由URL类的openStream方法返回的输入流)可以从文件和其他更外部的位置上获取字节
  • 其他的输入流(例如DataInputStream)可以将字节组装到更有用的数据类型中

必须对二者进行组合。例如:

FileInputStream fin = new FileInputStream("employee.dat");
DataInputStream din = new DataInputStream(fin);
double x = din.readDouble();

FilterInputStreamFilterOutputStream的子类用于向处理字节的输入/输出流添加额外的功能。

输入流在默认下是不被缓冲区缓存的,每个对read的调用都会请求操作系统再分发一个字节。相比下,请求一个数据块并将其置于缓冲区中会更加高效。
要使用缓冲机制,以及用于文件的数据输入方法,就使用下面的构造器序列:

DataInputStream din = new DataInputStream(
	new BufferedInputStream(
		new FileInputStream("employee.dat");

DataInputStream置于构造器的最后,是希望使用DataInputStream的方法,并希望能使用带缓冲机制的read方法。

当读入输入时,经常需要预览下一个字节,以了解它是否是想要的值。

PushbackInputStream pbin = new PushbackInputStream(
	new BufferedInputStream(
		new FileInputStream("employee.dat");

可以预读下一个字节:

int b = pbin.read();

并且在它并发是所期望的值时将其推回流中:

if (b != '<') pbin.unread(b);

如果希望能预先浏览并且还可以读入数字,那么需要一个既是可回退输入流又是一个数据输入流的引用:

DataInputStream din = new DataInputStream(
	pbin = new PushbackInputStream(
		new BufferedInputStream(
			new FileInputStream("employee.dat");

组合流

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值