java I/O系统

来源:互联网 发布:淘宝号被冻结 编辑:程序博客网 时间:2024/05/22 02:03

输入和输出

JavaI/O类分为输入和输出。Inputstream抽象类是表示字节输入流的所有类的超类,用于读取单个字节。Reader抽象类是表示字符输入流的所有类的超类,用于读取单个字符。Outputstream用于写单个字节,Write用于写单个字符。它们都有read()和write()基本方法。下图为I/O所有类树图。

这里写图片描述

Inputstream类型

Inputstream从不同数据源产生的输入类,这些数据源包括:

  • 字节数组。
  • String对象
  • 文件
  • “管道”
  • 其他

下表1-1为Inputstream的直接子类,通过继承它满足不同需求,具体自己查看Java api。

类 功能 ByteArrayInputstream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。作为一种数据源:将其与FilterInputStreamd对象相连以提供有用的接口。 FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。作为一种数据源:将其与FilterInputStreamd对象相连以提供有用的接口。 PipedInputStream 通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。 如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。作为多线程中数据源:将其与FilterInputStreamd对象相连以提供有用的接口。 SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。 FilterInputStream FilterInputStream抽象类作为“装饰器”的接口,包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。FilterInputStream 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

Outputstream类型

Outputstream数据输出类,输出目标包括:

  • 字节数组。
  • String对象
  • 文件
  • “管道”
  • 其他

下表1-2为Outputstream的直接子类,通过继承它满足不同需求,具体自己查看Java api。

类 功能 BteArrayOutputstream 此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。作为一种数据源:将其与FilterOutputStreamd对象相连以提供有用的接口。 FileInputStream 文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。FilterOutputStream 的子类可进一步地重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。 PipedOutputStream 通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。作为多线程中数据源:将其与FilterOutputStreamd对象相连以提供有用的接口。 FilterOutputStream FilterOutputStream抽象类作为“装饰器”的接口,此类是过滤输出流的所有类的超类。这些流位于已存在的输出流(基础 输出流)之上,它们将已存在的输出流作为其基本数据接收器,但可能直接传输数据或提供一些额外的功能。FilterOutputStream 类本身只是简单地重写那些将所有请求传递给所包含输出流的 OutputStream 的所有方法。FilterOutputStream 的子类可进一步地重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

装饰器

由于I/O需要不同功能的组合,装饰器模式可以满足这个需求。FilterInputStream和FilterOutputStream是用来提供装饰接口以控制特定输入流和输出流的两个基类。

FilterInputStream

下表1-3为FilterInputStream的直接子类,通过继承它满足不同需求,具体自己查看Java api。

类 功能 DataInputStream 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型(int,long,char等)。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。DataInputStream 对于多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。 BufferedInputStream BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。 PushbackInputStream PushbackInputStream 为另一个输入流添加性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。在代码片段可以很方便地读取由特定字节值分隔的不定数量的数据字节时,这很有用;在读取终止字节后,代码片段可以“取消读取”该字节,这样,输入流上的下一个读取操作将会重新读取被推回的字节。例如,表示构成标识符字符的字节可能由表示操作符字符的字节终止;用于读取一个标识符的方法可以读取到遇到操作符为止,然后将该操作符推回以进行重读。

FilterOutputStream

下表1-4为FilterOutputStream的直接子类,通过继承它满足不同需求,具体自己查看Java api。

类 功能 DataOutputStream 数据据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。 printStream PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。它还提供其他两项功能。与其他输出流不同,PrintStream 永远不会抛出 IOException;而是,异常情况仅设置可通过 checkError 方法测试的内部标志。另外,为了自动刷新,可以创建一个 PrintStream;这意味着可在写入 byte 数组之后自动调用 flush 方法,可调用其中一个 println 方法,或写入一个换行符或字节 (‘\n’)。PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。 BufferedOutputStream 该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。

Reader和Writer

Reader和Writer与Inputstream和Outputstream的区别是Reader和Writer是面向字符的并且提供兼容Unicode。InputstreamReader可以把Inputstream转换成Reader,OutputstreamReader可以把Outputstream转换成Reader。下图为它们及其子类之间对应关系:

字节 字符 InputStream Reader 适配器:InputstreamReader OutputStream Writer 适配器:OutputstreamReader FileInputStream FileReader FileOutputStream FileWriter ByteArrayInputStream CharArrayReader ByteArrayInputStream CharArrayWrite PipedInputStream PipedReader PipedOutputStream PipedWriter

RandomAcessFile

此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。

通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException。

| 字节| 字符|
| InputStream | Reader 适配器:InputstreamReader|

方法 摘要 void close() 关闭此随机访问文件流并释放与该流关联的所有系统资源。 FileChannel getChannel() 返回与此文件关联的唯一 FileChannel 对象。 FileDescriptor getFD() 返回与此流关联的不透明文件描述符对象。 boolean readBoolean() 从此文件读取一个 boolean。 long getFilePointer() 返回此文件中的当前偏移量。 long length() 返回此文件的长度。 int read() 从此文件中读取一个数据字节。 int read(byte[] b) 将最多 b.length 个数据字节从此文件读入 byte 数组。 int read(byte[] b, int off, int len) 将最多 len 个数据字节从此文件读入 byte 数组。 byte readByte() 从此文件读取一个有符号的八位值。 char readChar() 从此文件读取一个字符。 double readDouble() 从此文件读取一个 double。 float readFloat() 从此文件读取一个 float。 void readFully(byte[] b) 将 b.length 个字节从此文件读入 byte 数组,并从当前文件指针开始。 void readFully(byte[] b, int off, int len) 将正好 len 个字节从此文件读入 byte 数组,并从当前文件指针开始。 int readInt() 从此文件读取一个有符号的 32 位整数。 String readLine() 从此文件读取文本的下一行。 long readLong() 从此文件读取一个有符号的 64 位整数。 short readShort() 从此文件读取一个有符号的 16 位数。 int readUnsignedByte() 从此文件读取一个无符号的八位数。 int readUnsignedShort() 从此文件读取一个无符号的 16 位数。 String readUTF() 从此文件读取一个字符串。 void seek(long pos) 设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。 void setLength(long newLength) 设置此文件的长度。 int skipBytes(int n) 尝试跳过输入的 n 个字节以丢弃跳过的字节。 void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。 void write(byte[] b, int off, int len) 将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。 void write(int b) 向此文件写入指定的字节。 void writeBoolean(boolean v) 按单字节值将 boolean 写入该文件。 void writeByte(int v) 按单字节值将 byte 写入该文件。 void writeBytes(String s) 按字节序列将该字符串写入该文件。 void writeChar(int v) 按双字节值将 char 写入该文件,先写高字节。 void writeChars(String s) 按字符序列将一个字符串写入该文件。 void writeDouble(double v) 使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,然后按八字节数量将该 long 值写入该文件,先定高字节。 void writeFloat(float v) 使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个 int,然后按四字节数量将该 int 值写入该文件,先写高字节。 void writeInt(int v) 按四个字节将 int 写入该文件,先写高字节。 void writeLong(long v) 按八个字节将 long 写入该文件,先写高字节。 void writeShort(int v) 按两个字节将 short 写入该文件,先写高字节。 void writeUTF(String str) 使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。

经典使用方式

缓冲输入文件

如果想要打开一个文件用于字符输入,为了提高速度,我们希望对那个文件进行缓冲,那么可以使用BufferedReader。

package S;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.util.Iterator;import java.util.LinkedList;public class BufferedReaderTest {    public static LinkedList<String> read(String filepath) {        LinkedList<String> lls = new LinkedList<String>();        try {            BufferedReader in = new BufferedReader(new FileReader(filepath));            String s;            while ((s = in.readLine()) != null) {                lls.add(s + "\n");            }            in.close();        } catch (IOException e) {            e.printStackTrace();        }        return lls;    }    public static void main(String[] args) {        LinkedList<String> lls = read("E:\\infile.txt");        Iterator llsi = lls.descendingIterator();        while (llsi.hasNext()) {            System.out.print(llsi.next());        }    }}

基本文件输出

package S;import java.io.*;public class PrintWriterTest {    public static void Writer() {        try {            BufferedReader in = new BufferedReader(new FileReader("E:\\infile.txt"));            PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("E:\\outfile.txt")));            String s;            while ((s = in.readLine()) != null) {                out.println(s);            }            in.close();            out.close();        } catch (IOException e) {            e.printStackTrace();        }    }    public static void mian(String[] args) {        Writer();    }}

存储和恢复数据

DataOutputStream可以保证准确的读取数据-无论读和写平台是否相同。

package S;import java.io.*;public class StoringAndRecoveringData {    public static void main(String[] args) {        try {            DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("E:\\outfile.txt")));            out.writeDouble(3.124355);            out.writeUTF("ni hao a linlin");            out.writeInt(1);            out.writeUTF("ni hao a world");            out.close();            DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("E:\\outfile.txt")));            System.out.println(in.readDouble());            System.out.println(in.readUTF());            System.out.println(in.readInt());            System.out.println(in.readUTF());            in.close();        } catch (IOException e) {            e.printStackTrace();        }    }}

随机读取

RandomAccessFile该类继承了DataInput, DataOutput也能保证准确的读取,除此之外还能指定位置读取,前提是读、取内容你已知。

package S;import java.io.IOException;import java.io.RandomAccessFile;public class RandomAccessFileTest{    public static void main(String[] args){        try {            RandomAccessFile out=new RandomAccessFile("E:\\outfile.txt","rw");            out.writeDouble(3.124355);            out.writeUTF("ni hao a linlin");            out.writeInt(1);            out.writeUTF("ni hao a world");            out.close();            RandomAccessFile in=new RandomAccessFile("E:\\outfile.txt","r");            System.out.println(in.length());            in.seek(8);            System.out.println(in.readUTF());        } catch (IOException e) {            e.printStackTrace();        }    }}
原创粉丝点击