首页 > 代码库 > IO(字节流)

IO(字节流)

1. 字节流类以InputStream 和 OutputStream为顶层类,他们都是抽象类(abstract)

 

2. 最重要的两种方法是read()和write(),它们分别对数据的字节进行读写。两种方法都在InputStream 和OutputStream中被定义为抽象方法。它们被派生的流类重写。


3. 过滤流的主要特点是在输入输出数据的同时能对所传输的数据做指定类型或格式的转换,即可实现对二进制字节数据的理解和编码转换。


4. 过滤流在读/写数据的同时可以对数据进行处理,它提供了同步机制,使得某一时刻只有一个线程可以访问一个I/O流,以防止多个线程同时对一个I/O流进行操作所带来的意想不到的结果


5. 类FilterInputStream和FilterOutputStream分别作为所有过滤输入流和输出流的父类。


6. Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。这种机制实际上是一种被称为Decorator(装饰)设计模式的应用。


7. System.out是标准的输出流。默认情况下,它是一个控制台。System.in是标准输入,默认情况下,它指的是键盘。System.err指的是标准错误流,它默认是控制台。然而,这些流可以

    重定向到任何兼容的输入/输出设备


8. System.in 是InputStream的对象;System.out和System.err是PrintStream的对象。它们都是字节流,尽管它们用来读写外设的字符。如果愿意,你可以用基于字符的流来包装它们


9. 当你对文件的操作结束后,需要调用close( )来关闭文件

 


InputStream:


1. InputStream 三个基本的读方法:

    abstract int read() :读取一个字节数据,并返回读到的数据,如果返回-1,表示读到了输入流的末尾。

    int read(byte[] b) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。

    int read(byte[] b, int off, int len) :将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。

    off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。


2. 为什么只有第一个read方法是抽象的,而其余两个read方法都是具体的?

    因为第二个read方法依靠第三个read方法来实现,而第三个read方法又依靠第一个read方法来实现,所以说只有第一个read方法是与具体的I/O设备相关的,

    它需要InputStream的子类来实现。


3. InputStream常用方法:

    long skip(long n) :在输入流中跳过n个字节,并返回实际跳过的字节数。

    int available() :返回在不发生阻塞的情况下,可读取的字节数。

    void close() :关闭输入流,释放和这个流相关的系统资源。

    void mark(int readlimit) :在输入流的当前位置放置一个标记,如果读取的字节数多于readlimit设置的值,则流忽略这个标记。

    void reset() :返回到上一个标记。

    boolean markSupported() :测试当前流是否支持mark和reset方法。如果支持,返回true,否则返回false。

 


OutputStream:


1. 三个基本的写方法:

    abstract void write(int b) :往输出流中写入一个字节。

    void write(byte[] b) :往输出流中写入数组b中的所有字节。

    void write(byte[] b, int off,int len) :往输出流中写入数组b中从偏移量off开始的len个字节的数据

 

2. 常用方法:

    void flush() :刷新输出流,强制缓冲区中的输出字节被写出。

    void close() :关闭输出流,释放和这个流相关的系统资源。


FileInputStream和FileOutputStream


1. FileInputStream 类创建一个能从文件读取字节的InputStream 类,它的两个常用的构造方法如下:

    FileInputStream(String filepath)

    FileInputStream(File fileObj)


2. FileOutputStream 创建了一个可以向文件写入字节的类OutputStream,它常用的构造方法如下:

    FileOutputStream(String filePath)

    FileOutputStream(File fileObj)

    FileOutputStream(String filePath, boolean append)


3. FileOutputStream的创建不依赖于文件是否存在。在创建对象时FileOutputStream在打开输出文件之前创建它。这种情况下你试图打开一个只读文件,会引发一个IOException异常

 

4. 当read( )返回-1时,它仅表示一点:遇到了文件的结尾

 

 

ByteArrayInputStream和ByteArrayOutputStream


1. ByteArrayInputStream是把字节数组当成源的输入流。该类有两个构造方法,每个构造方法需要一个字节数组提供数据源:

    ByteArrayInputStream(byte array[ ])

    ByteArrayInputStream(byte array[ ], int start, int numBytes)

    这里,array是输入源。第二个构造方法创建了一个InputStream类,该类从字节数组的子集生成,以start指定索引的字符为起点,长度由numBytes决定


2. ByteArrayInputStream实现mark()和reset()方法。然而,如果mark()不被调用,reset()在流的开始设置流指针——该指针是传递给构造方法的字节数组的首地址


3. ByteArrayOutputStream是一个把字节数组当作输出流的实现。ByteArrayOutputStream 有两个构造方法:

    ByteArrayOutputStream( )

    ByteArrayOutputStream(int numBytes)

    在第一种形式里,一个32位字节的缓冲区被生成。第二个构造方法生成一个numBytes大小的缓冲区。缓冲区保存在ByteArrayOutputStream的受保护的buf 成员里。缓冲区的大小

    在需要的情况下会自动增加。缓冲区保存的字节数是由ByteArrayOutputStream的受保护的count域保存的。


4. writeTo(OutputStream out) :将此字节数组输出流的全部内容写入到指定的输出流参数中

    reset():将此字节数组输出流的count字段重置为零,从而丢弃输出流中目前已累积的所有输出。通过重新使用已分配的缓冲区空间,可以再次使用该输出流

 

 


BufferedInputStream 和BufferedOutputStream


1. 对于字节流,缓冲流(buffered stream),通过把内存缓冲区连到输入/输出流扩展一个过滤流类。该缓冲区允许Java对多个字节同时进行输入/输出操作,提高了程序性能。因为缓冲区

    可用,所以可以跳过、标记和重新设置流。


2. 若处理的数据量较多,为避免每个字节的读写都对流进行,可以使用过滤流类的子类缓冲流。缓冲流建立一个内部缓冲区,输入输出数据先读写到缓冲区中进行操作,这样可以提高文件流的操作效率

 

3. 缓冲输入/输出是一个非常普通的性能优化。Java的BufferedInputStream 类允许把任何InputStream类“包装”成缓冲流并使它的性能提高


4. BufferedInputStream 有两个构造方法

    BufferedInputStream(InputStream inputStream)

    BufferedInputStream(InputStream inputStream, int bufSize)

    第一种形式 创建 BufferedInputStream 流对象并为以后的使用保存 InputStream 参数 in ,并创建一个内部缓冲区数组来保存输入数据。

    第二种形式 用指定的缓冲区大小 size 创建BufferedInputStream 流对象


5. 当创建缓冲输入流BufferedInputStream时,一个输入缓冲区数组被创建,来自流的数据填入缓冲区,一次可填入许多字节

 

6. 缓冲一个输入流同样提供了在可用缓冲区的流内支持向后移动的必备基础。除了在任何InputStream类中执行的read( )和skip( )方法外,

    BufferedInputStream 同样支持mark( ) 和 reset( )方法。BufferedInputStream.markSupported( )返回true是这一支持的体现。


7. 缓冲输出流BufferedOutputStream类提供和FileOutputStream类同样的写操作方法,但所有输出全部写入缓冲区中。当写满缓冲区或关闭输出流时,它再一次性输出到流,

    或者用flush()方法主动将缓冲区输出到流。


8. BufferedOutputStream的两个构造方法:

    BufferedOutputStream(OutputStream outputStream)

    BufferedOutputStream(OutputStream outputStream, int bufSize)

    第一种形式创建了一个使用512字节缓冲区的缓冲流。第二种形式,缓冲区的大小由bufSize参数传入。


9. 要想在程序结束之前将缓冲区里的数据写入磁盘,除了填满缓冲区或关闭输出流外,还可以显式调用flush()方法。

 

10. 在调用完BufferedOutputStream后一定要flush或者将其close掉,否则缓冲区中的字节不会输出来

 

 

SequenceInputStream


1. SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达

    包含的最后一个输入流的文件末尾为止

 

2. SequenceInputStream的构造不同于任何其他的InputStream。SequenceInputStream构造方法要么使用一对InputStream,要么用InputStream的一个Enumeration,显示如下 :

    SequenceInputStream(InputStream first,InputStream second)

   SequenceInputStream(Enumeration streamEnum)

   操作上来说,该类满足读取完第一个InputStream后转去读取第二个流的读取要求。使用Enumeration的情况下,它将继续读取所有InputStream流直到最后一个被读完

 

 

DataInputStream和DataOutputStream

 

1. 提供了允许从流读写任意对象与基本数据类型功能的方法 。

 

2. 字节文件流FileInputStream 和FileOutputStream只能提供纯字节或字节数组的输入/输出,如果要进行基本数据类型如整数和浮点数的输入/输出。则要用到过滤流类的子类二进制数据

  文件流DataInputStream和DataOutputStream类。这两个类的对象必须和一个输入类或输出类联系起来,而不能直接用文件名或文件对象建立。

 

3. 使用数据文件流的一般步骤:

    1). 建立字节文件流对象;

    2). 基于字节文件流对象建立数据文件流对象;

    3). 用流对象的方法对基本类型的数据进行输入/输出。


4. DataInputStream类的构造方法如下:

    DataInputStream(InputStream in) :创建过滤流FilterInputStream 对象并为以后的使用保存InputStream 参数 in 。


5. DataOutputStream类的构造方法如下:
    DataOutputStream(OutputStream out):创建输出数据流对象, 写数据到指定的OutputStream


6. 注意:读取的顺序一定要与写入的顺序完全一致,否则会发生错误

 


PipedInputStream和PipedOutputStream

 

1. 管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流 。

    PipedInputStream与PipedOutputStream总是成对出现的


2. 管道流继承自InputStream与OutputStream,所以他们并不是过滤流


3. 传送输入流应该连接到传送输出流;传送输入流会提供要写入传送输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream对象读取,并由其他线程将其写入到相应的

    PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程。传送输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开


4. 传送输出流可以连接到传送输入流,以创建通信管道。传送输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream

    读取。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁该线程

 

 

IO(字节流)