Loading

Java IO整理总结之字节流

原文链接https://www.codeliu.com/java/261.html
写文章之前先上一张图吧,应该是迄今为止最全的IO流图,图太大了,可能看着有点费劲,里面有很多类我从来没用过,以后可能也不会用上。本人有些许强迫症,为了知识的全面性,就全部画上去了。
这里写图片描述

摘要:

Java流分为字节流和字符流,字符流处理的是2个字节的单元比如字符串、字符数组;而字节流处理的是一个字节的单元比如字节和字节数组。字符流一次可以处理一个缓冲区,而字节流一次只能处理一个字节,所以字符流的效率更高。

InputStream是所有表示字节输入流的类的超类,OutputStream是所有表示字节输出流的类的超类,Reader是所有读取字符流的类的超类,Writer是所有写入字符流的类的超类,以上四个类都是抽象类。

任何自InputStream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或字节数组,同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写单个字节或字节数组。

**

字节流

**
一.InputStream
这里写图片描述

1.InputStream

构造方法

InputStream()

其他方法

int available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

void close() 关闭此输入流并释放与该流关联的所有系统资源。

void mark(int readlimit) 在此输入流中标记当前的位置。readlimit 参数告知此输入流在标记位置失效之前允许读取的字节数。

boolean markSupported() 测试此输入流是否支持 mark 和 reset 方法。

abstract int read() 从输入流中读取数据的下一个字节。

int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。

void reset() 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。

long skip(long n) 跳过和丢弃此输入流中数据的 n 个字节。

2.AudioInputStream

音频输入流是具有指定音频格式和长度的输入流。长度用示例帧表示,不用字节表示。提供几种方法,用于从流读取一定数量的字节,或未指定数量的字节。音频输入流跟踪所读取的最后一个字节。可以跳过任意数量的字节以到达稍后的读取位置。音频输入流可支持标记。设置标记时,会记住当前位置,以便可以稍后返回到该位置。

构造方法

AudioInputStream(InputStream stream, AudioFormat format, long length) 使用指定输入流中的音频数据构造具有请求的格式和长度(以示例帧为单位)的音频输入流。

AudioInputStream(TargetDataLine line) 构造从指示的目标数据行读取数据的音频输入流。

其他方法

int available() 返回可不受阻塞地从此音频输入流中读取(或跳过)的最大字节数。

void close() 关闭此音频输入流并释放与该流关联的所有系统资源。

void mark(int readlimit) 标记此音频输入流中的当前位置。

boolean markSupported() 测试此音频输入流是否支持 mark 和 reset 方法。

int read() 从音频输入流中读取数据的下一个字节。

int read(byte[] b) 从音频输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

int read(byte[] b, int off, int len) 将音频输入流中最多 len 个数据字节读入 byte 数组。

void reset() 将此音频流重新定位到最后一次对此输入流调用 mark 方法时的位置。

long skip(long n) 跳过和丢弃此音频输入流中数据的 n 个字节。

AudioFormat getFormat() 获得此音频输入流中声音数据的音频格式。

long getFrameLength() 获得流的长度,以示例帧表示,而不是以字节表示。

3.ByteArrayInputStream

ByteArrayInputStream 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。 关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。

构造方法

ByteArrayInputStream(byte[] buf) 创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。

ByteArrayInputStream(byte[] buf, int offset, int length) 创建 ByteArrayInputStream,使用 buf 作为其缓冲区数组。

4.FileInputStream

FileInputStream 从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。
FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

构造方法

FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。

FileInputStream(FileDescriptor fdObj) 通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。

FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

5.FilterInputStream

FilterInputStream 包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。FilterInputStream 类本身只是简单地重写那些将所有请求传递给所包含输入流的 InputStream 的所有方法。FilterInputStream 的子类可进一步重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

构造方法

FilterInputStream(InputStream in) 将参数 in 分配给字段 this.in,以便记住它供以后使用,通过这种方式创建一个 FilterInputStream。

FilterInputStream有很多的子类,有几个是比较常用的,比如BufferedInputStream

6.ObjectInputStream

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

要实现序列化,必须实现Serializable 接口

构造方法

ObjectInputStream() 为完全重新实现 ObjectInputStream 的子类提供一种方式,让它不必分配仅由 ObjectInputStream 的实现使用的私有数据。

ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。

其他方法

void defaultReadObject() 从此流读取当前类的非静态和非瞬态字段。

protected boolean enableResolveObject() 使流允许从该流读取的对象被替代。

boolean readBoolean() 读取一个boolean值

byte readByte() 读取一个8位的字节

。。。还有readInt()之类的就不写了,自己可以查阅手册

Object readObject() 从 ObjectInputStream 读取对象。

7.PipedInputStream

管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。

构造方法

PipedInputStream() 创建尚未连接的 PipedInputStream。

PipedInputStream(int pipeSize) 创建一个尚未连接的 PipedInputStream,并对管道缓冲区使用指定的管道大小。

PipedInputStream(PipedOutputStream src) 创建 PipedInputStream,使其连接到管道输出流 src。

PipedInputStream(PipedOutputStream src, int pipeSize) 创建一个 PipedInputStream,使其连接到管道输出流 src,并对管道缓冲区使用指定的管道大小。

8.SequenceInputStream

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

构造方法
系统有毒,我一加它的构造方法,下面的内容就无法显示了==,所以我就删了

9.StringBufferInputStream

过时

二.OutputStream
这里写图片描述

1.ByteArrayOutputStream

此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。

构造方法

ByteArrayOutputStream() 创建一个新的 byte 数组输出流。

ByteArrayOutputStream(int size) 创建一个新的 byte 数组输出流,它具有指定大小的缓冲区容量(以字节为单位)。

其他方法

void reset() 将此 byte 数组输出流的 count 字段重置为零,从而丢弃输出流中目前已累积的所有输出。

int size() 返回缓冲区的当前大小

byte[] toByteArray() 创建一个新分配的 byte 数组。

String toString() 使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。

String toString(String charsetName) 使用指定的 charsetName,通过解码字节将缓冲区内容转换为字符串。

void write(byte[] b, int off, int length) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此 byte 数组输出流。

void write(int b) 将指定的字节写入此 byte 数组输出流。

void write(OutputStream out) 将此 byte 数组输出流的全部内容写入到指定的输出流参数中,这与使用 out.write(buf, 0, count) 调用该输出流的 write 方法效果一样。

2.FileOutputStream

文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。

构造方法

FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(FileDescriptor fdObj) 创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。

FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。

其他方法

void write(byte[] b, int off, int length) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此 byte 数组输出流。

void write(int b) 将指定的字节写入此 byte 数组输出流。

void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。

3.FilterOutputStream

此类是过滤输出流的所有类的超类。这些流位于已存在的输出流(基础 输出流)之上,它们将已存在的输出流作为其基本数据接收器,但可能直接传输数据或提供一些额外的功能。

FilterOutputStream 类本身只是简单地重写那些将所有请求传递给所包含输出流的 OutputStream 的所有方法。FilterOutputStream 的子类可进一步地重写这些方法中的一些方法,并且还可以提供一些额外的方法和字段。

构造方法

FilterOutputStream(OutputStream out) 创建一个构建在指定基础输出流之上的输出流过滤器。

其他方法

void close() 关闭此输出流并释放与此流有关的所有系统资源。

void flush() 刷新此输出流,并强制将所有已缓冲的输出字节写入该流中。

void write(byte[] b, int off, int length) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此 byte 数组输出流。

void write(int b) 将指定的字节写入此 byte 数组输出流。

void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。

4.ObjectOutputStream

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

构造方法

ObjectOutputStream() 为完全重新实现 ObjectOutputStream 的子类提供一种方法,让它不必分配仅由 ObjectOutputStream 的实现使用的私有数据。

ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream

5.PipedOutputStream

可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。

构造函数

PipedOutputStream()创建尚未连接到管道输入流的管道输出流。

PipedOutputStream(PipedInputStream snk) 创建连接到指定管道输入流的管道输出流。

介绍完了上面的类,下面咱就用代码来理解一下

public class FileOutDemo1 {
    public static void main(String[] args) throws IOException { 
        // 如果该文件不存在,则直接创建,如果存在,则删除后创建 
        FileOutputStream out = new FileOutputStream("demo\\test.txt");
        // 在文件后面追加内容 
        //FileOutputStream out = new FileOutputStream("demo\\test.txt", true); 
        // 写入A的第八位 
        out.write('A'); 
        out.write('B'); 
        int a = 10; 
        // 每次只能写入8字节,所以要写4次
        out.write(a >>> 24);  // 写入高8位
        out.write(a >>> 16); 
        out.write(a >>> 8); 
        out.write(a);   
        byte[] buf = "中国".getBytes(); 
        out.write(buf); 
        out.close(); 
        IOUtils.printHex("demo\\test.txt"); 
    }
}
/**
 * @author liu
 * @version 创建时间:2018年3月2日 下午5:36:27
 * InputStream,OutputStream
 */
public class IOUtils {
    /** 
     * 读取指定文件内容,以16进制输出到控制台,每行10个 
     * @param fileName 
     */ 
    public static void printHex(String fileName) throws IOException { 
        // 把文件作为字节流进行操作
        FileInputStream file = new FileInputStream(fileName); 
        int b; 
        int count = 0; 
        while((b = file.read()) != -1) { 
            System.out.print(Integer.toHexString(b) + "  "); 
            count++; 
            if(count % 10 == 0) { 
                System.out.println(); 
            } 
        } 
        file.close(); 
    }

    /**
     * 通过数组读取文件的内容 
     * @param fileName 
     * @throws IOException 
     */ 
    public static void printHexArr(String fileName) throws IOException { 
        FileInputStream in = new FileInputStream(fileName); 
        byte[] buf = new byte[10 * 1024]; 
        int count = 0; 
        // 从0开始,将buf.length长度的字节读入buf数组,返回读入的字节数 
        int len = in.read(buf, 0, buf.length); 
        for(int i = 0; i< len; i++) { 
            System.out.print(Integer.toHexString(buf[i] & 0xff) + "  "); 
            count++; if(count % 10 == 0) { 
                System.out.println(); 
            } 
        } 
        in.close(); 
    }

    /** 
     * 文件的复制 
     * @param objectFile 
     * @param sourceFile 
     * @throws IOException  
     */ 
    public static void copyFiles(File objectFile, File sourceFile) throws IOException { 
        if(!sourceFile.exists()) { 
            throw new IllegalArgumentException("源文件不存在"); 
        } 
        if(!objectFile.exists()) { 
            objectFile.createNewFile(); 
        } 
        FileInputStream in = new FileInputStream(sourceFile); 
        FileOutputStream out = new FileOutputStream(objectFile); 
        int buf; 
        while((buf = in.read()) != -1) { 
            out.write(buf); 
        } 
        in.close(); 
        out.close(); 
    }

    /** 
     * 拷贝文件,通过字节数组 
     * @param objectFile 
     * @param sourceFile 
     * @throws IOException 
     */ 
    public static void copyFilesByArr(File objectFile, File sourceFile) throws IOException{ 
        if(!sourceFile.exists()) { 
            throw new IllegalArgumentException("源文件不存在"); 
        } 
        if(!objectFile.exists()) { 
            objectFile.createNewFile(); 
        } 
        FileInputStream in = new FileInputStream(sourceFile);
        FileOutputStream out = new FileOutputStream(objectFile); 
        byte[] buf = new byte[8 * 1024]; 
        int b; 
        while((b = in.read(buf, 0 ,buf.length)) != -1) { 
             out.write(buf, 0, b); 
        } 
        in.close(); 
        out.close(); 
    }

    /** 
     * 文件的拷贝,通过Buffered缓冲区 
     * @param objectFile 
     * @param sourceFile 
     * @throws IOException 
     */ 
    public static void copyFileByBuff(File objectFile, File sourceFile) throws IOException { 
        if(!sourceFile.exists()) { 
            throw new IllegalArgumentException("源文件不存在"); 
        } 
        if(!objectFile.exists()) { 
            objectFile.createNewFile(); 
        } 
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(sourceFile)); 
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(objectFile));
        int b; 
        while((b = in.read()) != -1) { 
            out.write(b); 
        } 
        // 放while循环外面 
        out.flush(); 
        in.close(); 
        out.close(); 
    }

    /** 
     * 文件的拷贝,通过缓冲区的字节数组 
     * @param objectFile 
     * @param sourceFile 
     * @throws IOException 
     */ 
    public static void copyFileByBuffArr(File objectFile, File sourceFile) throws IOException {
        if(!sourceFile.exists()) { 
            throw new IllegalArgumentException("源文件不存在"); 
        } 
        if(!objectFile.exists()) { 
            objectFile.createNewFile(); 
        } 
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(sourceFile)); 
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(objectFile)); 
        byte[] buf = new byte[8 * 1024]; 
        int b; 
        while((b = in.read(buf, 0, buf.length)) != -1) { 
            out.write(buf, 0, b); 
        } 
        out.flush(); 
        in.close(); 
        out.close(); 
    }
}

测试类的话,大家可以自己去写,因为是操作文件,所有结果我就懒的截图了。写了几个小时,真累。本来想字符流和字节流一起写的,但发现写完字节流就已经这么多了,所以字符流下一篇文章再写,同时下篇文章介绍一下RandomAccessFile类,这是一个特立独行的类。

posted @ 2018-03-15 12:50  CodeTiger  阅读(31)  评论(0编辑  收藏  举报