转换流
在学习字符流(FileReader、FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputStreamWriter,这又是什么意思呢?
OutputStreamWriter类
OutputStreamWriter
是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节
将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class Test {
public static void main(String[] args) throws IOException {
writeGBK();
writeUTF();
}
/*
* 转化流对象 OutoutStreamWriter写文本
* 文本采用GBK的形式写入
*/
public static void writeGBK() throws IOException{
// 创建字节流输出流 绑定数据文件
FileOutputStream fos = new FileOutputStream("c:\\test.txt");
// 创建转换流对象 构造方法 绑定字节输出流 默认使用系统GBK编码
OutputStreamWriter osw = new OutputStreamWriter(fos);
// 转换流写入数据
osw.write("你好");
osw.flush();
osw.close();
}
/*
* 转化流对象 OutoutStreamWriter写文本
* 文本采用UTF-8的形式写入
*/
public static void writeUTF() throws IOException{
// 创建字节流输出流 绑定数据文件
FileOutputStream fos = new FileOutputStream("c:\\test1.txt");
// 创建转换流对象 构造方法 绑定字节输出流 指定UTF-8的编码
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
// 转换流写入数据
osw.write("你好");
osw.flush();
osw.close();
}
}
InputSteamReader类
查阅InputStreamReader的API介绍,InputStreamReader
是字节流通向字符流的桥梁:它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test2 {
public static void main(String[] args) throws IOException {
readGBK();
readUTF();
}
/*
* 转换流,InputSteamReader读取文本
* 采用系统默认编码表,读取GBK文件
*/
public static void readGBK()throws IOException{
//创建自己输入流,传递文本文件
FileInputStream fis = new FileInputStream("c:\\test.txt");
//创建转换流对象,构造方法,包装字节输入流
InputStreamReader isr = new InputStreamReader(fis);
char[] ch = new char[1024];
int len = 0;
while ((len = isr.read(ch)) != -1){
System.out.println(new String(ch,0,len));
}
isr.close();
}
/*
* 转换流,InputSteamReader读取文本
* 采用UTF-8编码表,读取文件
*/
public static void readUTF()throws IOException{
//创建自己输入流,传递文本文件
FileInputStream fis = new FileInputStream("c:\\test1.txt");
//创建转换流对象,构造方法中,包装字节输入流,同时写编码表名
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
char[] ch = new char[1024];
int len = 0;
while ((len = isr.read(ch)) != -1){
System.out.println(new String(ch, 0, len));
}
isr.close();
}
}
转换流子类父类的区别
OutputStreamWriter
和InputStreamReader
是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。
FileWriter
和FileReader
:作为子类,仅作为操作字符文件的便捷类存在,当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"))
默认字符集
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK")
指定GBK字符集。
FileReader fr = new FileReader("a.txt")
这三句代码的功能是一样的,其中第三句最为便捷
注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?
条件:
1、操作的是文件。2、使用默认编码。
总结:
字节--->字符 : 看不懂的--->看的懂的。 需要读。输入流。 InputStreamReader
字符--->字节 : 看的懂的--->看不懂的。 需要写。输出流。 OutputStreamWriter
缓冲流
在我们学习字节流与字符流的时候,大家都进行过读取文件中数据的操作,读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么,我想提高速度,怎么办?
Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度
缓冲流,根据流的分类分类字节缓冲流与字符缓冲流
字节缓冲流
字节缓冲流根据流的方向,共有2个
- 写入数据到流中,字节缓冲输出流
BufferedOutputStream
- 读取流中的数据,字节缓冲输入流
BufferedInputStream
它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test3 {
public static void main(String[] args) throws IOException {
bufferedWrite();
bufferedRead();
}
public static void bufferedWrite() throws IOException{
// 创建字节流
FileOutputStream fos = new FileOutputStream("c:\\test.txt");
// 创建字节流输出缓冲流对象 构造方法中传递字节流
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write(100); // d
byte[] bytes = "HelloWorld".getBytes();
bos.write(bytes); // HelloWorld
bos.write(bytes, 5, 5); // World
bos.close();
}
public static void bufferedRead() throws IOException{
// 创建字节流
FileInputStream fis = new FileInputStream("c:\\test.txt");
// 创建字节流输出缓冲流对象 构造方法中传递字节流
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = bis.read(bytes)) != -1){
System.out.print(new String(bytes, 0, len));
} // dHelloWorldWorld
bis.close();
}
}
字符缓冲流
- 字符缓冲输入流
BufferedReader
- 字符缓冲输出流
BufferedWriter
完成文本数据的高效的写入与读取的操作
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test4 {
public static void main(String[] args) throws IOException {
bufferedWrite();
bufferedRead();
}
/* 字符输出流缓冲区流
* java.io.BufferedWriter 继承 Writer
* 写入方法 write () 单个字符,字符数组,字符串
* BufferedWriter(Writer w)传递任意字符输出流
*/
public static void bufferedWrite() throws IOException{
// 创建字符输出流
FileWriter fw = new FileWriter("c:\\test.txt");
// 创建字符流缓冲对象 构造方法中传递字符流
BufferedWriter bw = new BufferedWriter(fw);
bw.write(100); // d
bw.flush();
// newLine() 写换行 方法具有平台无关性
bw.newLine();
bw.write("你好".toCharArray());
bw.flush(); // 你好
bw.close();
}
/*
* 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
* public String readLine() 读取一个文本行,包含该行内容的字符串,
* 不包含任何行终止符,如果已到达流末尾,则返回 null
*/
public static void bufferedRead() throws IOException{
// 创建字符输出流
FileReader fr = new FileReader("c:\\test.txt");
// 创建字符流缓冲对象 构造方法中传递字符流
BufferedReader br = new BufferedReader(fr);
// 调用缓冲流的方法 readLine()读取文本行
// 循环读取文本 结束条件 readLine()返回null
String line = null;
int lineNumber = 0;
while((line = br.readLine()) != null){
lineNumber ++;
System.out.println(lineNumber + " " + line); // 1 d
} // 2 你好
br.close();
}
}
流的操作规律
IO流中对象很多,解决问题(处理设备上的数据时)到底该用哪个对象呢?
把IO流进行了规律的总结(四个明确):
-
明确一:要操作的数据是数据源还是数据目的。
- 源:
InputStream
Reader
- 目的:
OutputStream
Writer
先根据需求明确要读,还是要写。
- 源:
-
明确二:要操作的数据是字节还是文本呢?
- 源:
字节:InputStream
文本:Reader
- 目的:
字节:OutputStream
文本:Writer
已经明确到了具体的体系上。
- 源:
-
明确三:明确数据所在的具体设备。
- 源设备:
硬盘:文件 File开头。
内存:数组,字符串。
键盘:System.in;
网络:Socket - 目的设备:
硬盘:文件 File开头。
内存:数组,字符串。
屏幕:System.out
网络:Socket
完全可以明确具体要使用哪个流对象。
- 源设备:
-
明确四:是否需要额外功能呢?
- 额外功能:
转换吗?转换流。InputStreamReader
OutputStreamWriter
高效吗?缓冲区对象。BufferedXXX
- 额外功能: