Java IO 之字节流

流(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()方法实际上不执行任何操作
    }
}

运行结果:

15
67
255
247

解析:
以上字节数组输入流从字节数组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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值