字符流
1.概念
2.写入与读取
3.文本文件的拷贝
4.使用字符流的情况
5.使用BufferedReader和BufferedWriter
6.装饰设计模式
7.不同码表读取字符的转换
1.概念
字符流:直接读取字符的IO
字符流读取字符,先读取字节然后转换为字符,写入时将字符转化为字节后写入
2.写入与读取
- 读取(FileReader)
FileReader的用法和我们上一节内容FileInputStream相似,一下是用法案例:
try {
FileReader fileReader = new FileReader("student.txt");
int x;
while ((x = fileReader.read()) != -1) {
System.out.print((char) x);
}
fileReader.close();
} catch (Exception e) {
e.printStackTrace();
}
读出文件中的内容
如何识别字符
GBK码表中,在系统未升级之前,中文字符的码值都是以负数形式存在的,系统升级之后,中文的第一个字节的码值为负数,当读取到第一个字节为负值时,GBK读取时就读取两个字节。通过项目默认的码表依次读取一个字符。
- 写入(File Writer)
与读取的规则相同,在读取文件之前必须保证文件存在,在往文件中写数据之前只需要保证路径存在无误即刻
注意事项:
只传入一个参数时,文件中原来的内容会清空。
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter("student.txt");
fileWriter.write("热爱学习!!!");
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
3.文件的拷贝
- 1.一个一个读取
FileReader fileReader = null;
try {
fileReader = new FileReader("student.txt");
FileWriter fileWriter = new FileWriter("newstudent,txt");
int x;
while ((x = fileReader.read()) != -1) {
fileWriter.write(x);
}
fileReader.close();
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
注意事项:
输出流一定要关闭,在底层使用了缓存区,如果不关流,可能不能写入成功,内容一直在缓存区中,关闭流可以使缓存区的数据写入文件中。
- 2.自定义小数组的文件拷贝(效率更高)
public static void main(String[] args) throws IOException {
// write your code here
FileReader fileReader = new FileReader("student.txt");
FileWriter fileWriter = new FileWriter("bulala.txt");
int x;
char[] chars = new char[1024]; //读取的是字符所以用char 而不是字节!!
while ((x = fileReader.read(chars)) != -1) {
fileWriter.write(chars,0,x);
}
fileReader.close();
fileWriter.close();
}
使用字符流的情况
- 当只进行读取和写入操作时,可以使用字符流。
- 但是在拷贝文本文件时不推荐使用字符流,底层会进行字符与字节的转化,(读取时将字节转化为字符,当写入时将字符转化为字节)计算机内部都是使用字节存储,直接使用字符流更好。
- 字符流不能拷贝非纯文本文件,比如视频、照片之类的文件。
原因:当字符流拷贝非纯文本文件时,会将字节转化为字符(根据字节在对应的码表中找对应的字符,但是在字节拼接找字符的过程中可能出现错误,写出的时候会将字符转化为字节写出去,此时会将"?"也写出,写入也是乱的)
使用BufferReader和BufferWriter
在使用小数组之后我们就可以想到一个更节省空间的方法,使用缓冲区
BufferedReader bufferedReader = new BufferedReader(new FileReader("student.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("newnewstudent.txt"));
int x;
while ((x = bufferedReader.read()) != -1) {
bufferedWriter.write(x);
}
bufferedReader.close();
bufferedWriter.close();
- 一行一行读取
读取之后不会包括换行
BufferedReader bufferedReader = new BufferedReader(new FileReader("student.txt"));
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
bufferedReader.close();
- 一行一行的写入(写入换行)
BufferedReader bufferedReader = new BufferedReader(new FileReader("student.txt"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("xxx.txt"));
String line;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
- newLine()和“\r\n”的区别
newLine()可以跨平台,而“\r\n”只适应windows系统。
- 加行号读取(类LineNumberReader)
LineNumberReader lineNumberReader = new LineNumberReader(new FileReader("student.txt"));
String s;
//lineNumberReader.setLineNumber(n);行号从n+1开始,原来的第一行,现在是n+1行
while ((s = lineNumberReader.readLine()) != null) {
System.out.println(lineNumberReader.getLineNumber() + s);
}
lineNumberReader.close();
装饰设计模式
- 步骤:(1)获取装饰类的对象(2)构造函数中传入装饰类的对象(3)对原有的功能进行升级
- BufferedReader等类即采用这种设计模式
interface Style {
public abstract void code();
}
class Student implements Style{
@Override
public void code() {
System.out.println("学习挖掘机");
}
}
class GStudent implements Style {
//步骤一
private Student student;
//步骤二
public GStudent(Student student) {
this.student = student;
}
@Override
public void code() {
student.code();
System.out.println("学习java");
}
}
不同码表的读写
常使用类 InputStreamReader 和 OutputStreamWriter
- 一般直接转化会出现问题:在UTF-8码表中中文为三个字节,在JBK码表中中文是两个字节,在转化时会出现乱码问题。
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("student.txt"),"GBK");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("newstudent.txt"),"UTF-8");
int x;
while ((x = inputStreamReader.read()) != -1) {
outputStreamWriter.write(x);
}
inputStreamReader.close();
outputStreamWriter.close();
建议增加缓冲区,进行进一步优化
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("student.txt"),"GBK"));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("newstudent,txt"),"UTF-8"));
int x;
while ((x = bufferedReader.read()) != -1) {
bufferedWriter.write(x);
}
bufferedReader.close();
bufferedWriter.close();
图解理解: