字符流=字节流+字符集
特点:输入流:一次读一个字节,遇到中文时,一次读多个字节。
输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中。
使用场景:对纯文本文件进行读写操作,Reader是字符的输入流,writer是字符的输出流,负责写出数据FileReader操作本地文件的字符输入流,FileWriter操作本地文件的字符输出流。
FileReader:1.创建字符输入流对象。
2.读取数据。
第二步有两个小细节:细节1:按字节进行读取,遇到中文,一次读取多个字节,读取后解码,返回一个整数。
细节2:读到文本末尾了,read方法返回-1.
3.释放资源。
read方法的细节:方法的底层会解码并转成十进制,最终把十进制作为返回值。
如果想在控制台看到中文,需要进行强转。也就是用(char)。我写了一段代码,拱大家理解,如下:
FileReader fr=new FileReader("C:\\Users\\86188\\IdeaProjects\\java\\Game\\a.txt");
int ch;
while ((ch=fr.read())!=-1){
System.out.println((char) ch);
}
fr.close();
}
}
最终,在控制台上打印的就是我在a文件里写出的纯文本文件。
接下来说说空参的read方法和实参的区别,首先,空参的read方法一个字节一个字节的读,遇到中文会一次读取多个字节,返回的是一个十进制,也就是一个数值,在控制台如果想看见中文,那就必须强转。而实参不一样,它是把读取数据,解码,强转放在一块儿了,然后把强转之后的字符放在数组当中。
FileWriter字符输出流
1.创建字符输出流的对象:
细节1:参数是字符串表示的路径,或者new一个File对象都是可以的
细节2:如果文件不存在,那么会创建一个新的文件,但是要保证父级文件是存在的。
细节3:如果文件存在,再接着调用write方法时,会清空文件,如果想要续写,那么需要传参数ture。
2.写数据
细节:如果write方法的参数是整数,但实际上写到本地文件中的是整数在字符集上对应的字符。
3.释放资源。
字符输出流在调用write方法时,会有几种选项,第一种write(int c)这种是写出字符集编码到固定文件夹中去的方法,第二种write(String str)这种是写出一个字符串到文件夹中去的方法。
第三种是write(String str,int off,int len)这种是写出字符串的一部分,也就是从off到len这一段的字符串,还有一种是write(char[]ch,int off,int len),是写出数组的一部分。
其中第二种和第三种方法是我用的比较多的方法,我写了一串代码,请看:
FileReader fr=new FileReader("C:\\Users\\86188\\IdeaProjects\\java\\Game\\a.txt");
FileWriter fw=new FileWriter("C:\\Users\\86188\\IdeaProjects\\java\\Game\\b.tet",true);
int b;
char[]c=new char[10];
while ((b=fr.read(c))!=-1){
fw.write(c,0,b);
}
fw.write("这是续写的部分");
fw.close();
fw.close();
}
}
在字符输入流中,首先,肯定会有一个数据源的,我们创建了对象以后,数据源就会与内存之间创建一个通道,此时,在底层,还创建了一个长度为8192的字节数组,也叫缓冲区。在调用read方法时,首先会去判断缓冲区中是否有数据可以被读取,如果没有,就会从文件中去读取,尽可能的装满缓冲区,每次读取,会从缓冲区中去读取,减少频繁的到硬盘中读取数据的过程,缓冲区是为了提高效率的,如果缓冲区中有数据,就会从缓冲区中找数据。如果文件中没有数据,并且缓冲区中的数据也被读完后,就会返回-1.
当然,这些是我在csdn查找的,到底有没有缓冲区,我创建了一个代码来验证。如下:
FileReader fr=new FileReader("C:\\Users\\86188\\IdeaProjects\\java\\Game\\a.txt");
int b1=fr.read();
System.out.println(b1);
int b2=fr.read();
System.out.println(b2);
int b3=fr.read();
System.out.println(b3);
fr.close();
}
}
然后,我将 FileReader fr=new FileReader(“C:\Users\86188\IdeaProjects\java\Game\a.txt”);打了断点,查看了它的bb这个数据,发现,还真有8192这个字节数组,也就是缓冲区。然后,将我在a文件夹中所写的数据储存到了这个字节中。
我截图了,请看:
我们再来学习一下字符输出流的底层原理,它同样的也会创建一个缓冲区,会将数据源中的数据传输到长度为8192的字节数组中,然后,将缓冲区中的数据传输到目的地当中。当然了,出现以下三种情况时,缓冲区中的数据会直接到目的文件夹中:
情况1:缓冲区装满了
情况2:手动的进行刷新,将缓冲区中的数据都传输到目的地中去。
情况3:关流的时候。
这里还要介绍两个方法,一个是public void flush()它的作用是将缓冲区中的数据刷新到本地文件中,还有一个就是老方法public void close()关流时也可以清空缓冲区。