Чтобы понять это полностью, вам нужно понять, что такое поток символов и байтов, поэтому давайте быстро рассмотрим это:
Потоки байтов
Поток байтов обращается к файлу побайтно. Программы Java используют потоки байтов для ввода и вывода 8-битных байтов. Он подходит для любого типа файлов, однако не совсем подходит для текстовых файлов. Например, если файл использует кодировку Unicode и символ представлен двумя байтами, поток байтов будет обрабатывать их отдельно, и вам нужно будет выполнить преобразование самостоятельно. Потоки, ориентированные на байты, не используют какую-либо схему кодирования, в то время как потоки, ориентированные на символы, используют схему кодирования символов (UNICODE). Все классы потока байтов происходят от InputStream и OutputStream.
Поток персонажей
Поток символов будет читать файл символ за символом. Поток символов — это концепция более высокого уровня, чем поток байтов. Поток символов — это, по сути, поток байтов, который был обернут логикой, позволяющей ему выводить символы из определенной кодировки. Это означает, что для правильной работы потоку символов необходимо указать кодировку файла. Поток символов может поддерживать все типы наборов символов ASCII, Unicode, UTF-8, UTF-16 и т. д. Все классы потоков символов происходят от Reader и Writer.
Если вы попытаетесь прочитать из файла .txt
, который был написан с кодировкой Uni-8, которая по умолчанию используется в java, то чтение файла с классами 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");
}
}
output.txt
Hello World
Это 3 способа чтения из файла: сначала с помощью FileReader по умолчанию, затем с помощью FileInputStream, а затем с использованием InputStreamReader с кодировкой Unicode-16 (кодировка). Комментарии к методам говорят сами за себя, прочтите их, чтобы получить четкое представление о том, как это работает.
Программа чтения файлов
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) : þ
FileInputStream
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 : þ
InputStreamReader
/*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
person
Arpan Banerjee
schedule
19.04.2020