流与文件

Java中,一个可以读取字节序列的对象被称为输入流,一个可以写入字节序列的对象被称为输出流。在抽象类InputStreamOutputStream中对它们进行了说明。

读写字节

InputStream类有一个抽象的方法:

abstract int read()

该方法将读取一个字节,并将其返回。如果已经读到了输入源的末尾,将返回-1。具体的输入流类的设计者覆盖这个方法以提供具体的功能实现。例如,System.in是一个预定义的InputStream的子类的对象,使用它可以从键盘读取信息。

同样地,OutputStream类定义了这个抽象方法:

abstract void write(int b)

将一个字节写到指定的输出位置。

这里的read方法和write方法都是阻塞I/O

available方法可以检查目前可以读取的字节数。也就是说,下面这样的代码不可能永远被阻塞:

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

当完对一个流的读取或者写入后,就应该调用close方法将它关闭,这样可以释放流所占用的操作系统资源。关闭一个输出流也可以冲洗(flush)输出流占用的缓存区,即临时存储在缓冲区中等待形成较大的数据包后再发送的那些字符,此时将他们发送出去。

 

流过滤器的分层

FileInputStream和FileOutputStream能够把输入和输出流与磁盘文件关联起来。例如:

FileInputStream fin = new FileInputStream("employee.data");

也可以使用一个File对象

File f = new File("employee.dat");

FileInputStream fin = new FileInputStream(f);

因为所有在java.io中的类都是将相对路径名解释为起始于用户的当前工作目录,所以应该清楚当前的目录。可以通过调用System.getProperty("user.dir")来获得。

与抽象类的InputStream和OutputStream类似,这些类只在字节层次上支持读写。这意味着,只能从fin对象中读取字节和字节数组。

byte b = (byte)fin.read();

一些流(例如FileInputStream以及URL类中利用openStream方法来返回的输入流)可以从文件以及其他地方接收字节。另一些流(例如DataInputStream和PrintWiter)可以将字节组合成更加有用的数据类型。Java程序员采用将一个已经存在的流传递给另一个流的构造器方法,将这两种流结合起来,结合后的流被称为过滤流。例如:

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

DataInputStream din = new DataInputStream(fin);

double s = din.readDouble();

非常重要的一点是:利用上面的代码建立的数据输入流并没有与一个新的磁盘文件对应。新创建的流依然通过访问与文件输入流相联系的文件获取数据。但是,现在可以使用一种功能更多的接口了。

 

java.io.BufferedInputStream 1.0

BufferedInputStream(InputStream in)

新建一个默认大小的缓冲流。缓冲的输入流从一个流中读取字节,而不会每次都引起对设备的访问。当缓冲区空时,一个新的数据块会被读入缓冲区。

BufferedInputStream(InputStream in, int n)

根据用户自定义缓冲区大小,新建一个缓冲流。

 

java.io.BufferedOutputStream 1.0

BufferedOutputStream(OutputStream out)

新建一个默认缓冲大小的缓冲流。缓冲输出流收集写入的字符以免每次都引起对设备的访问。当缓存区满或者流被冲洗时,数据被写入设备。

BufferedOutputStream(OutputStream out, int n)

根据用户自定义的缓冲区大小,新建一个缓冲流。

 

java.io.PushbackInputStream 1.0

PushbackInputStream (InputStream in)

构造一个预查看一个字节的流。

PushbackInputStream (InputStream in, int size)

使用指定大小的pushback缓冲区构造一个流。

void unread(int b)

返回一个字节,下次调用读取时仍会再次得到该字节。一次只能返回一个字节。参数b:再次被读取的字节。

 

随机存取文件流

RandomAccessFile流类能够在文件的任何位置查找或者写入数据。他同时实现了DataInput和DataOutPut接口。磁盘文件可以随机存取,但是来自网络的数据流就不行了。随机存取文件提供了一个文件指针。文件指针总是指向下一条要进行读写操作记录的位置。Seek方法指定文件指针的位置,getFilePointer方法返回文件指针的当前位置。

java.io.RandomAccessFile 1.0

RandomAccessFile(String file, String mode)

RandomAccessFile(File file, String mode)

参数:file         将被打开的文件

        mode     "r":只读,"rw":读/写, "rws":同步读写, "rwd":同步读写

long getFilePointer()

返回文件指针的当前位置。

void seek(long pos)

将文件指针的位置设定为从文件开始的pos字节处。

long length()

返回文件的长度(以字节记)

 

java.io.DataInput 1.0 //DataInput是一个接口哪个类实现了这个接口,就是定义了接口中的方法。

boolean readBoolean()

byte readByte()

char readChar()

double readDouble()

float readFloat()

void readFully(byte[] b)//将所有字节读入字节数组b中,阻塞直到全部字节被读取为止。

void readFully(byte[] b, int off, int len)// off:数据开始位置的偏移量,len:读取字节的最大数

int readInt()

String readLine()//读取一行,直到 , , 或者EOF。返回字符串

long readLong()

short readShort()

String readUTF()//使用"modified-UTF-8"格式读取一个字符组成的字符串

int skipBytes(int n)//跳过n个字节

 

java.io.DataOutput 1.0

与DataInput接口对应。例如,有boolean readBoolean(),就有void writeBoolean(boolean b)。

注意,与readFully相对应的是void writeChars(String s),将字符串s写入。

 

这里插一条接口的笔记:接口类型可以作为形参类型,而所有实现了该接口的类都可以作为实参类型。例如:

class Employee

{

    read(DataInput in){...}

    write(DataOutput out){...}

}

RandomAccessFile类实现了DataInput 和DataOutput 接口,因此read方法和write方法的实参可以是RandomAccessFile类的对象。 

原文地址:https://www.cnblogs.com/johnsblog/p/4143861.html