部分内容已经丢失
可以看到包装FileReader
的BufferedReader
在读取文件时候如果文件的编码和项目的编码不一样的时候,会出现乱。
乱码问题
使用包装InputStreamReader
的BufferedReader
读取文件
1 2 3 4 5 6 7 8 9
| String file = "utf8.txt"; BufferedReader reader = new BufferedReader( new InputStreamReader(new FileInputStream(file), "utf-8")); char[] cbuf=new char[20]; int size; while((size=reader.read(cbuf, 0, cbuf.length))!=-1) { System.out.println(new String(cbuf,0,size)); }
|
运行结果:
这里要弄清楚的是BufferedReader只负责读到它的内部缓冲区中,而解码的工作是InputStreamReader完成的。
BufferedWriter
BufferedWriter的API:
继承关系
1 2 3
| java.lang.Object |----> java.io.Writer |----> java.io.BufferedWriter
|
构造函数:
方法 |
描述 |
BufferedWriter(Writer out) |
创建一个缓冲字符输出流,使用默认大小的输出缓冲区 |
BufferedWriter(Writer out, int sz) |
创建一个缓冲字符输出流,使用给定大小的输出缓冲区 |
成员方法
方法 |
描述 |
void write(int c) |
写入单个字符。 |
void write(char[] cbuf, int off, int len) |
写入字符数组的某一部分。 |
void write(String s, int off, int len) |
写入字符串的某一部分。 |
void newLine() |
写入一个行分隔符。 |
void close() |
关闭此流,但要先刷新它。 |
void flush() |
刷新该流的缓冲。 |
写文件实例
使用上述三个写方法写文件:一个字符一个字符的复制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static void main(String[] args) throws IOException { BufferedWriter writer=new BufferedWriter(new FileWriter("静夜思.txt")); char ch='床'; writer.write(ch); String next="前明月光,"; char[] nexts=next.toCharArray(); writer.write(nexts,0,nexts.length); writer.newLine(); String nextLine="疑是地上霜。"; writer.write(nextLine); writer.close(); }
|
运行结果,静夜思.txt:
应用:复制文本文件
逐个字符复制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| static void copyByChar(String srcFile, String destFile) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(srcFile)); BufferedWriter writer = new BufferedWriter(new FileWriter(destFile)); int ch=0; while ((ch = reader.read()) != -1) { writer.write(ch); } reader.close(); writer.close(); }
|
逐个字符数组复制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| static void copyByCharArray(String srcFile, String destFile) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(srcFile)); BufferedWriter writer = new BufferedWriter(new FileWriter(destFile)); int size=0; char[] cbuf=new char[20]; while ((size = reader.read(cbuf)) != -1) { writer.write(cbuf,0,size); } reader.close(); writer.close(); }
|
按行复制文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| static void copyByLine(String srcFile,String destFile) throws IOException { BufferedReader reader=new BufferedReader(new FileReader(srcFile)); BufferedWriter writer=new BufferedWriter(new FileWriter(destFile)); String line; while((line=reader.readLine())!=null) { writer.write(line); writer.newLine(); } reader.close(); writer.close(); }
|
需要注意的是,BufferedReader
的readLine()
读取一行的时候返回的字符串没有换行符,所以,复制的时候写文件是我们好多写入一个换行符,使用writer.newLine()
方法即可。
测试:
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws IOException { String from = "gbk.txt"; String to = "gbk_copy.txt"; String to1 = "gbk_copy1.txt"; String to2 = "gbk_copy2.txt"; copyByChar(from, to); copyByCharArray(from, to1); copyByLine(from, to2); }
|
源文件gbk.txt:
运行结果:
gbk_copy.txt
gbk_copy1.txt
gbk_copy2.txt
gbk file
这里是一句中文
bug:按行复制的时候多写换行符
细心的朋友可能发现,按行复制的时候,复制的文件会莫名其妙的在文件后面多了一个换行符。这是因为我们每次都在读到的字符串后面写一个换行符。
解决办法:在读到的字符串前面写换行符,这样出现新的问题,就是在文件开头多出了一个空行,所以加入控制语句,在第一行不写入换行符,第二行后再写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| static void copyByLine(String srcFile,String destFile) throws IOException { BufferedReader reader=new BufferedReader(new FileReader(srcFile)); BufferedWriter writer=new BufferedWriter(new FileWriter(destFile)); String line; boolean flag=false; while((line=reader.readLine())!=null) { if(!flag) { flag=true; writer.write(line); } else { writer.newLine(); writer.write(line); } } reader.close(); writer.close(); }
|
这样复制的文件就不会多谢换行符了,保证复制的文件和源文件是一模一样的。
bug:乱码问题
因为我们使用的是包装FileReader
的BufferedReader
,包装FileWriter
的BufferedWriter
。所以读字符,写字符的时候使用的是默认的字符编码读写的。所以读写文件的时候会出现乱码,可以使用包装InputStreamReader
的BufferedReader
,包装OutputStreamWriter
的BufferedWriter
来复制文件,这样就可以支持各种字符编码。
实例:gbk编码的文件复制到utf8编码的文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| static void copyByLineEncoding(String srcFile, String srcEncoding, String destFile, String destEncoding) { BufferedReader reader = null; BufferedWriter writer = null; try { reader = new BufferedReader(new InputStreamReader( new FileInputStream(srcFile), srcEncoding)); writer = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(destFile), destEncoding)); char[] charArray = new char[512]; int size; while ((size = reader.read(charArray, 0, charArray.length)) != -1) { writer.write(charArray, 0, size); }
} catch (UnsupportedEncodingException | FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
|
main方法:
1 2 3 4 5 6
| public static void main(String[] args) throws IOException { String from = "gbk.txt"; String to = "copyto_utf8.txt"; copyByLineEncoding(from,"gbk",to,"utf-8"); }
|
源文件gbk.txt(gbk编码):
目标文件copyto_utf8.txt:
乱码是正常的,因为我们的工程目录用的gbk编码,把copyto_utf8.txt编码显示就好了:
所以使用包装InputStreamReader
的BufferedReader
,包装OutputStreamWriter
的BufferedWriter
来复制文件的好处就是可以指定复制文件的时候使用的字符编码,例如上面的复制操作,从gbk编码的文件中读取,然后写入到utf8编码的文件中去。