要彻底理解这一点,您需要了解什么是字符流和字节流,所以让我们快速看一下——
字节流
字节流逐字节访问文件。Java 程序使用字节流来执行 8 位字节的输入和输出。它适用于任何类型的文件,但不太适合文本文件。例如,如果文件使用 unicode 编码并且一个字符用两个字节表示,则字节流将分别处理这些,您需要自己进行转换。面向字节的流不使用任何编码方案,而面向字符的流使用字符编码方案(UNICODE)。所有字节流类都来自 InputStream 和 OutputStream 。
字符流
字符流将逐个字符地读取文件。Character Stream 是比 Byte Stream 更高层次的概念。字符流实际上是一个字节流,它已被逻辑包装,允许它从特定编码输出字符。这意味着,需要为字符流提供文件的编码才能正常工作。字符流可以支持所有类型的字符集 ASCII、Unicode、UTF-8、UTF-16 等。所有字符流类都是从 Reader 和 Writer 继承而来的。
如果您尝试从.txt
使用 Java 默认使用的 Uni-8 编码编写的文件中读取,则使用 Reader 和 InputStream 类读取文件将给出相同的输出。因为这里每个字节代表一个字符。
我创建了一些方法来帮助您理解这两个术语之间的区别 -FileInputStream reads byte by byte
和FileReader reads char by char
. 请耐心等待并进一步阅读以了解这一点。
现在您已经对这两个流有所了解,让我们看一下示例以了解它在内部是如何工作的——
使用 Unicode 16 编码在文件中写入一些数据的方法
public void unicode16Writer() throws Exception {
try (OutputStream outputStream = new FileOutputStream("output.txt")) {
Writer writer = new OutputStreamWriter(outputStream, Charset.forName("UTF-16"));
writer.write("Hello World");
}
}
输出.txt
Hello World
这是从文件中读取的 3 种方式,首先使用 FileReader 默认方式,然后使用 FileInputStream,然后使用带有 Unicode-16 字符集(编码)的 InputStreamReader。
方法中的注释是不言自明的,请阅读它们以清楚地了解它是如何工作的。
文件阅读器
public void fileReaderUnicode8() throws IOException {
FileReader fr = new FileReader("output.txt");
int i;
int j = fr.read();
/*
* here it is not able to convert the
* int(a byte/8 bits read from the file) to a
* char as we had used UTF-16 to encode the file so 16 bits
* represented one character, but we can use its super class
* InputStreamReader to provide the charset(what we used for encoding)
* which for our case is UTF-16 , then we can
* easily convert that into char.
*/
System.out.println("Output of FileReader using default cons(default charset) : " + (char) j);
// while ((i=fr.read()) != -1)
// System.out.print((char) i);
}
输出
Output of FileReader using default cons(default charset) : þ
文件输入流
public void readBytebyByte() throws IOException {
try (FileInputStream fis = new FileInputStream("output.txt")) {
int i;
int j = fis.read();
/*
* here it is not able to convert the
* int(a byte/8 bits read from the file) to a
* char as we had used UTF-16 to encode the
* file so 16 bits represented one
* character.
*/
System.out.println("Output of FileInputStream reading byte by byte : " + (char) j);
// while ((i=fis.read()) != -1)
// System.out.print((char) i);
}
}
输出
Output of FileInputStream reading byte by byte : þ
输入流读取器
/*Here we are using the parent class of FileReader so that
*we can set the charset(type of encoding)
*in its constructor.
*/
public void unicode16Reader() throws IOException {
try (InputStream inputStream = new FileInputStream("output.txt")) {
Reader reader = new InputStreamReader(inputStream, Charset.forName("UTF-16"));
int data = reader.read();
System.out.println("uni-16 ISR: " + (char) data);
// while(data != -1){
// char theChar = (char) data;
// data = reader.read();
// }
}
}
输出
uni-16 ISR: H