Java IO 之字节流

来源:互联网 发布:informix数据库特点 编辑:程序博客网 时间:2024/05/01 01:10

流(stream):流是一组有序的数据序列,根据操作的类型,分为输入流和输出流两种。
输入流:输入流的指向称为源,程序从指向源的输入流中读取源中的数据。
输出流:输出流的指向是字节要去的目的地,程序通过向输出流中写入数据把信息传递到目的地。

流一般分为字节流字符流两种。


1. InputStream & OutputStream

1.1 InputStream

InputStream类是字节输入流的抽象类,是所有字节输入流的父类。InputStream有多个子类,继承关系如下图所示,可以实现不同的数据输入流。
InputStream子类继承关系图

InputStream类常用方法如下表所示。

方法名称 功能描述 int read() 从输入流中读取单个字节,返回读取的字节数据(字节数据可直接转换为int类型) int read(byte[] b) 从输入流中最多读取b.length个字节的数据,并存于字节数组b中,返回实际读取的字节数 int read(byte[] b, int off, int len) 从输入流中最多读取len个字节的数据,并存于字节数组b中,放入数组b中时,从off位置开始存放,返回实际读取的字节数 close() 关闭当前输入流,并释放任何与之关联的系统资源

1.2 OutputStream

OutputStream类是字节输出流的抽象类,是所有字节输出流的父类。OutputStream有多个子类,继承关系如下图所示,可以实现不同的数据输出流。
OutputStream子类继承关系图

OutputStream类常用方法如下表所示。

方法名称 功能描述 void write(int c) 将指定的字节输出到输出流中,其中c代表字节 void write(byte[] b) 将字节数组b中的数据输出到指定输出流 void write(byte[] b, int off, int len) 将字节数组中从off位置开始,长度为len的数据输出到指定输出流 flush() 刷新当前输出流,并强制写入所有缓冲的字节数据 close() 关闭当前输出流,并释放任何与之关联的系统资源

2 FileInputStream & FileOutputStream

2.1 FileInputStream(访问文件)

FileInputStream是InputStream类的子类,实现了文件的读取,是文件字节输入流。常用构造方法有如下两种。

(1) FileInputStream(String filePath);

try {    FileInputStream fis2 = new FileInputStream("H:\\testIO\\test.txt");} catch (FileNotFoundException e) {    // TODO Auto-generated catch block    e.printStackTrace();}

(2) FileInputStream(File file);

File file = new File("H:\\testIO\\test.txt");if(!file.exists()){    try {        file.createNewFile();    } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();    }       }try {    FileInputStream fis1 = new FileInputStream(file);} catch (FileNotFoundException e1) {    // TODO Auto-generated catch block    e1.printStackTrace();}}

FileInputStream测试代码:

package testIO;import java.io.FileInputStream;import java.io.IOException;import java.io.File;public class TestFileInputStream {    public static void main(String[] args){        File file = new File("H:\\testIO\\test.txt");        try {            if(!file.exists()){                         file.createNewFile();                       }                   FileInputStream fis = new FileInputStream(file);            byte[] b = new byte[512];            int rs = 0;            System.out.println("output the context of file: ");            while((rs = fis.read(b)) > 0){                String s = new String(b, 0, rs);                System.out.println(s);            }            fis.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

运行结果:

output the context of file: This is my book!

2.2 FileOutputStream(写入文件)

FileOutputStream类是OutputStream类的子类,实现文件的写入,能够以字节形式写入文件中,该类的所有方法都是从OutputStream类继承并重写的。构造方法有三种。
(1) FileOutputStream(String filePath);
(2) FileOutputStream(File file); 对原文件内容进行覆盖。
(3) FileOutputStream(File file, true); 对原文件内容进行追加。

FileOutputStream测试代码:

package testIO;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;public class TestFileOutputStream {    public static void main(String[] args) throws IOException{        File file = new File("H:\\testIO\\test1.txt");        if(!file.exists()){            file.createNewFile();        }        byte[] bytes = new byte[512];        System.out.println("please input the context: ");        int b = System.in.read(bytes);        FileOutputStream fos = new FileOutputStream(file, true);        fos.write(bytes, 0, b);        fos.close();    }}

3 ByteArrayInputStream & ByteArrayOutputStream

3.1 ByteArrayInputStream(访问字节数组)

ByteArrayInputStream类从内存中的字节数组中读取数据,因此它的数据源是一个字节数组。关闭ByteArrayInputStream输入流之后,类中的方法仍可被调用。构造方法有两种。
(1) ByteArrayInputStream(byte[] buf);
(2) ByteArrayInputStream(byte[] buf, int off, int len);

ByteArrayInputStream.read()方法读取输入流的下一个字节,read()方法不会锁住,read()方法返回值为0-255,如果流已经达到了它的结束则返回-1。

ByteArrayInputStream测试代码:

package testIO;import java.io.IOException;import java.io.ByteArrayInputStream;public class TestByteArrayInputStream {    public static void main(String[] args) throws IOException{        byte[] buf = new byte[] {2, 15, 67, -1, -9, 9};        ByteArrayInputStream bais = new ByteArrayInputStream(buf, 1, 4);        int data;        while((data = bais.read()) != -1){            System.out.println(data);        }        bais.close();//ByteArrayInputStream的close()方法实际上不执行任何操作    }}

运行结果:

1567255247

解析:
以上字节数组输入流从字节数组buf的下标为1的元素开始读,一共读取4个元素。对于读到的每一个字节类型的元素,都会转换为int类型。

例如:对于字节类型的15,二进制形式为00001111,转换为int类型的二进制形式为
00000000 00000000 00000000 00001111,因此字节类型的15 转换为int类型仍然是15;对于字节类型的-1,二进制形式为 11111111,转换为int类型的二进制形式为
00000000 00000000 00000000 11111111,因此字节类型的-1 转换为int类型是255;对于字节类型的-9,二进制形式为 11110111,转换为int类型的二进制形式为 00000000 00000000 00000000 11110111,因此字节类型的-9转换为 int类型是 247。

以上字节数组输入流在读取了4个字节后,就达到了输入流的末尾,在执行read()方法,就会返回-1。

3.2 ByteArrayOutputStream(写入字节数组)

ByteArrayOutputStream类继承了OutputStream类,实现输出流中的数据被写入一个字节数组,缓冲区会随着数据的不断写入而自动增长。关闭一个字节数组输出流之后没有影响,这个类中的方法可以在流已关闭后被调用。构造方法有两种。
(1) ByteArrayOutputStream(); 将创建一个新的字节数组输出流,默认32字节的缓冲区。
(2) ByteArrayOutputStream(int size); 将创建一个新的字节数组输出流,具有指定大小size字节的缓冲容量。

常用方法如下:

方法名称 功能描述 byte[] toByteArray() 创建一个新分配的字节数组 String toString() 将缓冲区的内容转换为使用平台默认字符集的字符串解码字节 String toString(String charsetName) 通过使用指定charsetName解码字节将缓冲区的内容转换成一个字符串 void write(byte[] b, int off, int len) 将指定的字节数组从off开始写入该字节数组输出流,写入长度为len void write(int b) 将指定字节写入该字节数组输出流 void writeTo(OutputStream out) 将该字节数组输出流的全部内容写入到指定的输出流参数 int size() 返回缓冲区的当前大小 void reset() 重置该字节数组输出流为零的计数字段,丢弃所有当前累计输出 void close() 关闭字节数组输出流,但是对方法的调用不产生影响

ByteArrayOutputStream测试代码:

package testIO;import java.io.IOException;import java.io.ByteArrayOutputStream; public class TestByteArrayOutputStream {    public static void main(String[] args) throws IOException{        byte[] buf = new byte[]{2, 15, 67, -1, -9, 9};        ByteArrayOutputStream bos1 = new ByteArrayOutputStream();        ByteArrayOutputStream bos2 = new ByteArrayOutputStream();        bos1.write(1);        bos1.write(2);        bos1.write(buf, 0, 4);        bos1.writeTo(bos2);        byte[] buf1 = bos1.toByteArray();        byte[] buf2 = bos2.toByteArray();        System.out.println("test1: ");        for(int i = 0; i < buf1.length; i++){            System.out.print(buf1[i] + " ");        }        System.out.println();           System.out.println("test2: ");        for(int i = 0; i < buf2.length; i++){            System.out.print(buf2[i] + " ");        }        System.out.println();        bos2.close();        bos1.close();           }}

运行结果:

test1: 1 2 2 15 67 -1 test2: 1 2 2 15 67 -1 
0 0