java中字节流,字符流

在 Java 中,字节流是以字节(8 位二进制数)为单位来处理数据的流。字节是计算机存储和处理数据的基本单位,所有的数据在计算机底层最终都是以字节形式存在的,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据,因为这些文件本质上就是字节序列,字节流可以直接读取和写入这些字节,而不需要进行额外的转换

字符流是以字符为单位来处理数据的流。字符是人类可识别的文本符号,如字母、数字、标点符号等。但是,字符在计算机中存储和传输时需要通过字符编码转换为字节序列。字符流的抽象基类是Reader(输入字符流)和Writer(输出字符流)

java中字节流,字符流_第1张图片

1. InputStream

(1)FileInputStream是字节输入流,可以读取文件,并且是abstract,被子类继承,无法直接使用

InputStream提供了read()方法来逐个字节地读取数据。这个方法返回一个int值,范围是 0 - 255,表示读取到的字节数据(该方法一次读取一个字符并以整数格式返回其ASCII值),需要转为char类型,当返回 - 1 时,表示已经到达流的末尾。

如果读取的文件中含有汉字,会产生乱码。utf8汉字有3个字节,但是read()方法一次只能读取一个字节,无法正常读取

在这里会产生异常,可以使用throws IOException 或者try catch finally抛出,最好使用后者

因为最后需要关闭文件流释放资源,

fileInputStream是inputStream的子类,也拥有read()方法,在这里使用fileInputStream来读取文件
@Test
public void readFile01() {
    String filePath = "D:\\hello.txt";
    int readData = 0;
    FileInputStream fileInputStream = null;
    try {
        // 创建FileInputStream对象 用于读取文件
        fileInputStream = new FileInputStream(filePath);
        // 从输入流读取一个字节的数据,如果没有输入可用,返回-1,结束
        // 需要抛出异常 IOException
        while ((readData = fileInputStream.read()) != -1) {

            // utf-8 汉字是3个字节,输入汉字会乱码
            System.out.println((char)readData);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // 关闭文件流,释放资源
        try {
            fileInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(2)一次读取一个字节太消耗IO资源,我们在这里使用字节数组来提高效率

  // 使用 read(byte[] b) 读取文件,提高效率
    // 读取次数减少,但是汉字还是会乱码
    @Test
    public void readFile02() {
        String filePath = "d:\\hello.txt";
//        int readData = 0;
        // 字节数组
        byte[] buf = new byte[8]; // 一次读取八个字节,读取字节数可以改变
        int readLen = 0;
        FileInputStream fileInputStream = null;
        try {
            // 创建FileInputStream对象 用于读取文件
            fileInputStream = new FileInputStream(filePath);
        
            // 需要抛出异常 IOException   // 关闭文件流,释放资源
            //            try {
            //                fileInputStream.close();
            //            } catch (IOException e) {
            //                e.printStackTrace();
            //            }
            while ((readLen = fileInputStream.read(buf)) != -1) {

// 从输入流中每次读取8或数据到buf中,8个数据是因为byte[8]
// readLen是 返回每次读取数据的个数,只能<=8

                System.out.println(new String(buf, 0, readLen));

// length的长度不能大于数组的
// 从每次读取到的数据中取出length长度的数据
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }

2.OutputStream

(1)FIleOutputStream是字节输入流,可以写入文件,并且是abstract,被子类继承,无法直接使用

OutputStream提供了write(int b)方法用于逐个字节地输出数据。这个方法接收一个int类型的参数,但是实际上只使用了这个int值的最低一个字节(因为字节是 8 位,int是 32 位)来写入目标。

更高效的方式是使用write(byte[] b)方法,它可以将一个字节数组中的数据一次性输出到目标。还有一个重载的方法write(byte[] b, int off, int len),可以指定字节数组中的起始位置off和要输出的长度len

 @Test
    public void writeFile(){
        String filePath = "d:\\a.txt";
        FileOutputStream fileOutputStream = null;
        try {
            // 1. new FileOutputStream(filePath); 写入内容覆盖原来
            // 2. new FileOutputStream(filePath, true); 写入内容包含原来
             fileOutputStream = new FileOutputStream(filePath,true);
             // 写入一个字节
//            fileOutputStream.write('H');
            // 写入字符串
            String str = "aaaaadddd";
            // str.getBytes() 可以把字符串转为字节数组
//            fileOutputStream.write(str.getBytes());
            // 写入指定范围的字符
            fileOutputStream.write(str.getBytes(),0,4);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

3.Reader

(1)FileReader是 Java 中用于读取字符文件的类,它属于字符流范畴

字符编码转换:在底层,计算机存储文件是以字节为单位的。而FileReader会根据指定的字符编码将字节转换为字符。如果没有指定编码,它会使用系统默认的字符编码(例如在大多数中文系统中可能是 GBK 或者 UTF - 8)。这个转换过程是在读取数据时自动完成的。

与底层字节流的关系:实际上,FileReader在内部会创建一个FileInputStream(字节流)来读取文件中的字节,然后通过InputStreamReader将字节流转换为字符流。所以,FileReader是在字节流的基础上构建的,是对字节流读取和字符转换操作的一种封装,使得开发者可以更方便地专注于字符级别的文本处理

读取方法:逐个字符读取:FileReader提供了read()方法来逐个字符地读取文件内容。这个方法返回一个int值,范围是 0 - 65535(该方法一次读取一个字符并以整数格式返回其ASCII值),表示读取到的字符的 Unicode 编码值,当返回 - 1 时,表示已经到达文件末尾。

FileReader fileReader = new FileReader("example.txt");

int data;

while ((data = fileReader.read())!= -1) {

// 处理读取到的字符,例如打印出来

System.out.print((char) data);

}

fileReader.close();

读取到字符数组:除了逐个字符读取,还可以使用read(char[] cbuf)方法将文件内容读取到一个字符数组中。这个方法会尝试读取最多cbuf.length个字符到字符数组cbuf中,并返回实际读取的字符数。如果返回 - 1,则表示已经到达文件末尾。

FileReader fileReader = new FileReader("example.txt");

char[] buffer = new char[1024];

int charsRead;

while ((charsRead = fileReader.read(buffer))!= -1) {

// 处理读取到的字符数组,例如打印出来

System.out.print(new String(buffer, 0, charsRead)); }

fileReader.close();

4.Writer

Writer是抽象类,它有许多子类,如FileWriter、BufferedWriter、CharArrayWriter、StringWriter、PipedWriter等。这些子类实现了不同的功能,以适应各种具体的写入场景。

(1)FIleWriter

 try {
               FileWriter writer = new FileWriter("example.txt");
               String text = "Hello, World!";
               writer.write(text);
               writer.close();
           } catch (IOException e) {
               e.printStackTrace();
           }

 首先创建了一个FileWriter对象,指定要写入的文件名为example.txt。然后使用write方法将字符串"Hello, World!"写入文件。最后,通过close方法关闭FileWriter,释放相关资源。

(2) 字符数组和字符串写入(CharArrayWriter 和 StringWriter)

CharArrayWriter用于将字符写入字符数组,它可以将写入的字符数据存储在一个内部的字符数组中。例如,可以用于在内存中构建字符数据,然后获取这个字符数组进行后续操作。

StringWriter类似,不过它是用于构建字符串。它会将写入的字符数据转换为一个字符串,可以通过toString方法获取构建的字符串。

你可能感兴趣的:(java,开发语言)