点击 跳转到我的笔记:Java笔记-I/O字节流
1.OutputStreamWriter
输出流
2.InputStreamReader
输入流
把字节流+编码表,转换成,字符流。
在《Java网络编程》中,有这样一段话:
“Reader和Writer最重要的子类是InputStreamReader
和OutputStreamWriter
类。
InputStreamReader
类包含了一个底层输入流,可以从中读取原始字节。它根据指定的编码方式,将这些字节转换为Unicode字符。
OutputStreamWriter
从运行的程序中接收Unicode字符,然后使用指定的编码方式将这些字符转换为字节,再将这些字节写入底层输出流中。”
其是字符流和字节流之间的桥梁
可对读取到的字节数据经过指定编码转换成字符
可对读取到的字符数据经过指定编码转换成字节
简单使用举例:
public static void main(String[] args) {
try {
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("D:\\a.txt"));
osw.write(97);
osw.write('小');
osw.write("龙的传人");
osw.write("精灵宝可梦".toCharArray());
osw.write("桃花潭水深千尺", 2, 2);
osw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//运行结果:
//a小龙的传人精灵宝可梦潭水
//如果想每次在文件末尾写入数据的话
//OutputStreamWriter没提供构造方法
//我们使用FileOutputStream为我们提供的构造方法即可
//new FileOutputStream("a.txt", true) 即可
简单使用举例:
public static void main(String[] args) {
try {
// 1.一次读一个字符
InputStreamReader isr1 = new InputStreamReader(
new FileInputStream("D:\\Demo.java"));
int ch = -1;
while ((ch = isr1.read()) != -1) {
System.out.print((char) ch);
}
isr1.close();
// 2.一次读一个字符数组
InputStreamReader isr2 = new InputStreamReader(
new FileInputStream("D:\\Demo.java"));
char[] cs = new char[100];
int total = -1;
while ((total = isr2.read(cs)) != -1) {
System.out.print(new String(cs, 0, total));
}
isr2.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//提示:转换流可以读字符,也就是可以处理中文,不会乱码。
1.先向系统中写入UTF-8编码的文件
代码演示:
public static void main(String[] args) {
try {
//按UTF-8编码
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("D:\\a.txt"), "UTF-8");
String str = "一失足成千古风流人物";
osw.write(str);
osw.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//new OutputStreamWriter(new FileOutputStream("xx"), "UTF-8");
//也就是OutputStreamWriter的构造方法可以控制编码格式
2.用Java读取文件的内容输出到控制台
代码演示:
public static void main(String[] args) {
try {
//按UTF-8解码
InputStreamReader isr = new InputStreamReader(
new FileInputStream("D:\\a.txt"), "UTF-8");
int total = -1;
char[] cs = new char[100];
while ((total = isr.read(cs)) != -1) {
System.out.print(new String(cs, 0, total));
}
isr.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//同OutputStreamWriter
//new InputStreamReader(new FileInputStream("xx"), "UTF-8");
//也就是InputStreamReader的构造方法可以控制解码格式
问题1:混着用会有什么问题?为什么?
答:字节流去复制文本文件没问题,复制字节码文件也没问题。
字符流复制文本文件没问题,复制字节码文件比原来大,而且文件损坏。
原因:因为字符流每次拿取一个字符,而我们字节码文件里面没有字符,所以导致把字节当做字符处理,莫名其妙多了很多字符,而这些字符导致了字节码文件的字节混乱,无法使用
问题2:什么时候用字节流?什么时候用字符流?
答:用windows本地记事本打开文件
如果看得懂就用字符流
如果看不懂就用字节流
如果不知道 就用字节流(万能流)
方法都是从转换流继承过来,自己没有新方法
FileReader 类是读取字符流的抽象类,常用方法如下:
方法名称 | 说明 |
---|---|
int read() |
从输入流中读取单个字符 |
int read(byte[] c) |
从输入流中读取 c.length 长度的字符,保存到字符数组 c 中,返回实际读取的字符数 |
int read(char[] c, int off, int len) |
从输入流中读取最多 len 长度的字符,保存到字符数组 c 中,保存的位置从 off 位置开始,返回实际读取的字符长度 |
void close() |
关闭流 |
FileReader 类,字符输入流,代码演示:
public static void main(String[] args) {
try {
// InputStreamReader isr = new InputStreamReader(new BufferedInputStream(new FileInputStream("D:\\a.txt")));
// 下面一行代码是上面的代码的简化写法
// 使用默认的缓冲区大小 和 默认的编码表
FileReader fr = new FileReader("D:\\a.txt");
int total = -1;
char[] cs = new char[100];
while ((total = fr.read(cs)) != -1) {
System.out.println(new String(cs, 0, total));
}
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
FileWriter类是向文件写入数据的字符流,常用方法如下:
方法名称 | 说明 |
---|---|
write(String str) |
将 str 字符串里包含的字符输出到指定的输出流中 |
write(String str, int off, int len) |
将 str 字符串里从 off 位置开始长度为 len 的字符输出到输出流中 |
void close() |
关闭输出流 |
void flush() |
刷新输出流 |
FileWriter 类,字符输出流,代码演示:
public static void main(String[] args) {
try {
// OutputStreamWriter isr = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("D:\\a.txt")));
// 下面一行代码是上面的代码的简化写法
// 使用默认的缓冲区大小 和 默认的编码表
FileWriter fw = new FileWriter("D:\\a.txt", true);
fw.write("xxxxx");
fw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//如果像我一样FileWriter fw = new FileWriter("D:\\a.txt", true);
//写true 则写在文章末尾; 不写的话,覆盖文章,从头开始写
//1.缓冲字符流为我们提供的方法
bw.newLine();
//2.动态获取换行符并输出
bw.write(System.getProperty("line.separator"));
//3.直接输出操作系统的换行符(我这里输出的Windows的)
bw.write("\r\n");
代码如下:
public static void main(String[] args) {
try {
// 3中换行方法演示
BufferedWriter bw = new BufferedWriter(
new FileWriter("D:\\a.txt"));
bw.write("xxx");
// 1 跨平台可用,写起来麻烦
bw.write(System.getProperty("line.separator"));
bw.write("yyy");
// 2 推荐
bw.newLine();
bw.write("zzz");
// 3 跨平台不可用
bw.write("\r\n");
bw.write("结束");
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
有一个新的方法可用:
方法名称 | 说明 |
---|---|
String readLine() |
读取一个文本行。通过下列字符之一即可认为某行已终止:\r 、\n 、\r\n ,或回车后直接跟着换行。返回:包含该行内容的字符串,不包含任何终止符,所以每读取到一行,自己手动添加换行符;如果已到达流末尾,返回 null |
代码演示:
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(
new FileReader("D:\\a.txt"));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//注意:
//line = br.readLine() != null
//是 != null ; 不是 != -1 了
//切记切记!