【学习笔记】IO 流 (二)
字符编码
-
ISO-8859-1 收录了除ASCII 外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。采用一个字节来表示,最多只能表示256个字符
-
UTF-8 针对Unicode码表的可变长度字符编码,采用一个两个或三个字节来表示
-
GB2312 简体中文 采用一个或两个字节来表示,在1995年之前使用
-
GBK 简体中文,是GB2312的升级版,在1995年后使用
-
BIG5 台湾,繁体中文
写文件和读文件时,一定要采取相同的编码,当编码方式和解码方式不一致时,会出现乱码
在介绍字符流之前,我们先看一个案例
package com.iosteam;
import java.io.FileInputStream;
public class Demo08 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("f:\\test\\hello.txt");
int data = 0;
while ((data = fis.read()) != -1){
System.out.print((char) data);
}
}
}
我们读取一个txt文件,文件中写的是helloworld
如果我们把helloworld 换成中文 “好好学习”,会出现乱码
我们可以看到,这个文件的编码方式是UTF-8
UTF-8 对于中文的编码是一个汉字三个字节,所以 “好好学习” 是12个字节
如果我们用字节流读的话,是一个字节一个字节地读,所以把每个汉字拆成三个字节,然后逐个读取输出,所以才造成了乱码
所以我们要使用字符流来读
字符流的父类
字符流的父类(抽象类)
-
Reader: 字符输入流
-
public int read() {}
-
public int read(char[] c) {}
-
public int read(char[] b,int off,int len) {}
-
-
Wirter: 字符输出流
-
public void write(int n){}
-
public void write(String str){}
-
public void write(char[] c){}
-
文件字符流
-
FileReader :
-
public int read(char[] c) //从流中读取多个字符,将读到的内容存到c 数组,返回实际读到的字符数,如果达到文件的尾部,则返回-1
-
public int read() //从流中读取单个字符,并返回
-
package com.iosteam;
import java.io.FileReader;
public class Demo08 {
public static void main(String[] args) throws Exception{
//创建FileReader
FileReader fr = new FileReader("f:\\test\\hello.txt");
//单个读取
// int data = 0;
// while((data = fr.read()) != -1){
// System.out.print((char) data);
// }
//多个读取,采用缓冲数组
char[] buf = new char[1024];
int count = 0;
while((count = fr.read(buf)) != -1){
System.out.println(new String(buf,0,count));
}
//关闭
fr.close();
}
}
-
FileWriter
-
public void write(String str) //一次写多个字符
-
package com.iosteam;
import java.io.FileWriter;
public class Demo09 {
public static void main(String[] args) throws Exception{
//创建FileWriter
FileWriter fw = new FileWriter("f:\\test\\write.txt");
//读取
for (int i = 0; i < 10; i++) {
fw.write("java是最好的语言\r\n");
fw.flush();
}
//关闭
fw.close();
}
}
-
用文件字符流复制文件
package com.iosteam.file;
import java.io.FileReader;
import java.io.FileWriter;
public class Deme10 {
public static void main(String[] args) throws Exception{
//创建flieReader
FileReader fr = new FileReader("f:\\test\\write.txt");
//创建FileWrite
FileWriter fw = new FileWriter("f:\\test\\write1.txt");
//读取文件,并且写入文件
char[] buf = new char[1024];
int count = 0;
while((count = fr.read(buf)) != -1){
fw.write(buf);
fw.flush();
}
fr.close();
fw.close();
System.out.println("复制完成");
}
}
只能复制文本文件,不能复制图片或二进制文件
原因是图片文件没有字符编码,所以图片中的二进制转成字符就会成为乱码,写回去的也是乱码,所以复制以后的图片就会出错
所以以后我们复制文件时,可以使用字节流来复制,字节流可以复制任意文件,因为文件在计算机中都是二进制来存储。
字符缓冲流
字符缓冲流是字符流的增强,提高字符流读取和写入的功能
-
高效读写
-
支持输入换行符
-
可一次写一行、读一行
BufferedReader:
方法:
1.构造方法:BufferReader(Reader in) //需要传入字符流
2.readLine() //读取一行文本
package com.iosteam.file;
import java.io.BufferedReader;
import java.io.FileReader;
public class Demo11 {
public static void main(String[] args) throws Exception{
//创建BufferReader
FileReader fr = new FileReader("F:\\test\\write.txt");
BufferedReader br = new BufferedReader(fr); //需要传入字符流
//读取
//第一种方式:通过创建缓冲数组
// char[] buf = new char[1024];
// int count = 0;
// while((count = br.read(buf)) != -1){
// System.out.println(new String(buf,0,count));
// }
//第二种方式:一行一行的读取
String str = null;
while((str = br.readLine()) != null){
System.out.println(str);
}
//关闭
br.close();
}
}
BufferedWriter:
方法:
1.构造方法:BufferedWriter(Writer out); //需要传入字符流
2.newLine() //写一个分隔符
package com.iosteam.file;
import java.io.BufferedWriter;
import java.io.FileWriter;
public class Demo12 {
public static void main(String[] args) throws Exception{
//创建BufferedWriter
FileWriter fw = new FileWriter("f:\\test\\buffer.txt");
BufferedWriter bw = new BufferedWriter(fw);
//写入
for (int i = 0; i < 10; i++) {
bw.write("好好学习,天天向上");
bw.newLine(); //写入一个换行符 windows:\r\n Linux:\n
bw.flush(); //刷新缓冲
}
//关闭
bw.close();
}
}
打印流
-
PrintWriter: 继承了Writer类
-
封装了 print() / println() 方法,支持写入后换行
-
支持数据原样打印
-
与PrintStream 中的方法相同,唯一区别的地方是,PrintWriter 不包含用于写入原始字节的方法
package com.iosteam.file; import java.io.PrintWriter; public class Demo13 { public static void main(String[] args) throws Exception{ //创建PrintWriter PrintWriter pw = new PrintWriter("f:\\test\\print.txt"); //打印 pw.println(100); pw.println('w'); pw.println(true); pw.println(3.14); //关闭 pw.close(); } }
-
转换流
-
桥转换流:把硬盘上的字节流转成内存中的字符流,反之把字符流转换成字节流
-
InputStreamReader : 是字节流通向字符流的桥梁
-
构造方法:InputStreamReader(InputSream in) //需要传递一个字节流
InputStreamReader(InputSream in,String charsetName) //指定编码方式
-
String getEncoding() //得到编码方式
-
package com.iosteam.file;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class Demo14 {
public static void main(String[] args) throws Exception{
//创建InputStreamReader
FileInputStream fis = new FileInputStream("f:\\test\\write.txt");
InputStreamReader isr = new InputStreamReader(fis,"utf-8"); //传入字节流和编码方式
//读取文件
int data = 0;
while((data = isr.read()) != -1){
System.out.print((char) data);
}
//关闭
isr.close();
}
}
在这里要注意:我们传入的编码方式一定要与被读文件的编码方式相同,否则就会乱码
-
OutputStreamWriter:字符流通向字节流的桥梁
-
构造方法:OutputStreamWriter(OutputStream out) //需要传入字节流
OutputStreamWriter(OutputStream out,String charsetName) //指定编码方式
-
getEncoding() //得到编码方式
package com.iosteam.file; import java.io.FileOutputStream; import java.io.OutputStreamWriter; public class Demo15 { public static void main(String[] args) throws Exception{ //创建OutputStreamWriter FileOutputStream fos = new FileOutputStream("f:\\test\\info.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8"); //写入文件 for (int i = 0; i < 10; i++) { osw.write("怎么了怎么了\r\n"); osw.flush(); } //关闭 osw.close(); } }
-