目录
2.2 int read(byte[] buffer)方式代码演示以及注释
1、什么是字符流?
就是以字符为单位传输数据的管道、分为输入字符流和输出字符流
对流的概念不了解的同学可以看我上一篇发布的文章,很详细,链接我放下面了:
IO流(四):IO流的概述,分类,输入流输出流(input、output),字节流字符流、程序怎么读取文件概述-CSDN博客
2、字符流-输入流--FileReader
FileReader读取数据有2种方式
int read() : 一个一个字符读取,通俗点讲就是我们所能看到的一个字一个字拿
int read(byte buffer) :批量读取字符,buffer相当于一个水桶的大小,去一桶一桶把水装回来
2.1 int read()方式代码演示以及注释
用的try-with-resource的方式关闭流资源,看不懂的同学看我上一篇发布的文章:
IO流的释放--try-catch-finally和try-with-resource(JDK7新),try-with-resource使用场景和代码演示、源码分析-CSDN博客
这是我建的一个文件,下面演示如何读取这个文件
2.1.1 读取一个字节
public class FileReaderTest1 {
public static void main(String[] args) {
try (
//创建文件字符输入流管道,与文件接通
Reader reader = new FileReader("src\\main\\resources\\bbb.txt");
){
try {
int read = reader.read(); //每次读取一个字符的字节返回(注意:取回来的是一个字符的字节,因为字节比int小,所以拿int来接这个字节)
System.out.println((char)read); //将读出来的字节转为字符类型
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们可以看到读取到第一个字符为柔
2.1.2 将整个文件挨个字符读取并打印演示
如果没有数据了就会返回-1,表示读取文件结束。
public class FileReaderTest1 {
public static void main(String[] args) {
try (
//创建文件字符输入流管道,与文件接通
Reader reader = new FileReader("src\\main\\resources\\bbb.txt");
){
try {
int read;
while ((read = reader.read()) != -1){ //当读取到的字符为空时,返回-1,表示读取文件结束
System.out.print((char)read); //将读出来字符的字节转为字符类型
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们可以看到,我们将整个文件都读取出来并且打印了
弊端:读取数据的性能很差,每读取一个字符就要去硬盘中拿一次。
程序在内存中执行,不能直接找硬盘文件。程序是通过调用系统里的硬件资源去读取硬盘文件里的数据的,程序调用系统里的硬件资源开销以及去硬盘中找到对应文件数据的性能开销,相对内存是很慢的
所以我们下面介绍第二种方法 int read(byte[] buffer),一次读取多个数据,减少程序调用系统硬件资源的次数。
如果是一次性全部读取数据,可以解决中文乱码的情况,但是需要注意的是,我们的内存是远远小于硬盘的,如果需要读取的文件过大,会把我们的内存撑爆。
2.2 int read(byte[] buffer)方式代码演示以及注释
buffer的大小我们可以自己定义,最好是一次性就能把文件中的数据读过来(理想情况),这样的话只需要调用硬件资源一次。
2.2 .1 一次读取3字节演示
public class FileReaderTest1 {
public static void main(String[] args) {
try (
//创建文件字符输入流管道,与文件接通
Reader reader = new FileReader("src\\main\\resources\\bbb.txt");
){
try {
char[] buffer = new char[3];//将桶的大小定义为3,一次性读取3个字符
int read = reader.read(buffer);
//现在桶里面已经有数据了,我们将桶里面的数据转为字符串,这个写法表示读出来多少倒出来多少
String result = new String(buffer,0,read);
System.out.print(result); //将读出来字符的字节转为字符类型
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
可以看到我们一次性读取了3个字节,减少了程序调用硬件资源的次数,提高性能
2.2.2 一次性读取全部数据演示
public class FileReaderTest1 {
public static void main(String[] args) {
try (
//创建文件字符输入流管道,与文件接通
Reader reader = new FileReader("src\\main\\resources\\bbb.txt");
){
try {
char[] buffer = new char[3];//将桶的大小定义为3,一次性读取3个字符
int read;
while ((read = reader.read(buffer)) != -1){ //当读取到的字符为空时,返回-1,表示读取文件结束
//现在桶里面已经有数据了,我们将桶里面的数据转为字符串,这个写法表示读出来多少倒出来多少
String result = new String(buffer,0,read);
System.out.print(result); //将读出来字符的字节转为字符类型
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
可以看到,我们一次性就把文本中的数据读取过来了
3、输出流-FileWriter
3.1 代码演示以及注释
注意创建管道时的追加参数设置,默认为false是会替换原来的文本的
public class FileWriterTest01 {
public static void main(String[] args) {
try (
//创建文件字符输出流管道,与文件接通
//该文件不需要我们手动创建
// 这个true表示追加数据,默认为false,即替换原来的数据
Writer fw = new FileWriter("src\\main\\resources\\outputTest.txt",true);
)
{
try {
//写一个字符出去
fw.write('a');
fw.write('你');
fw.write(97);
fw.write("\r\n"); //换行符
//写一个字符串出去
fw.write("柔弱女子爱java");
fw.write("\r\n");
//写字符串的一部分出去
fw.write("柔弱女子爱java",0,3);
fw.write("\r\n");
//写一个字符数组出去
char[] buffer = {'好','好','学','习'};
fw.write(buffer);
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
我们可以看到,系统自动给我们创建了一个目录并且把字节写进去
3.2 FileWriter的Flush()方法
注意:字符输出流FileWriter一定要写flush()方法,不然字符是没有办法写出去的。
原因:我们的字符流在写数据的出去的时候,会先把数据写到一个缓冲区,然后再把缓冲区的数据一次性写到我们的文件当中,这样可以减少我们调用硬件资源次数,提高性能。所以我们要是不写flush(),数据就会在缓冲区当中,写不出去。
由于我们使用完流之后都会close(),close()方法底层会帮我们刷新管道,所以一般我们只需要close()就行了。关闭流close()之后不能继续使用该流,刷新流flush()后还可以继续使用。
上述的案例中用到的是ry-with-resource(JDK7新)的方法,这个方法会自动帮我们释放资源,所以不需要手动写close()方法,不了解的同学可以看我上一篇发的文章:
4、总结
int read() 读取数据的性能很差,每次只读取一个字符,每读一个字符都需要去调用一次系统资源。int read(byte[] buffer)能批量读取字符,在我们的开发中比较常用(需要注意文件内容过大,内容溢出的情况)。
使用完流之后,记得要关闭流。流的底层是要和系统资源关联的,是要通过调用系统资源来读取文件里面的数据,所以流用完之后,应该通知系统资源关闭,不再占用系统资源,即关闭IO流,可以提高性能。
字符流在写数据的出去的时候,会先把数据写到一个缓冲区,然后再把缓冲区的数据一次性写到我们的文件当中。所以字符输出流FileWriter一定要写flush()方法,不然字符是没有办法写出去的。由于close()方法底层会帮我们刷新管道,所以一般我们只需要close()就行了。
注意:关闭流close()之后不能继续使用该流,刷新流flush()后还可以继续使用。
注意:实际应用开发中,字符流适合读取纯文本类的数据,能避免读取中文乱码的情况。但是操作图片、视频等需要用到字节流(更适用于做文件复制,文档储存等业务)。
字节流的使用文章链接:
IO流(五):字节流-输入流(Inpustream)、输出流(OutputStream)--使用场景、弊端、注意事项、代码演示。-CSDN博客
这就是我对字符流的理解,希望能帮到大家,有问题的地方欢迎大家一起讨论!
后续会不断更新作品,欢迎大家一起讨论学习。❤❤❤