FileInputStream против FileReader
FileReader rd=new FileReader("new.mp4");
FileWriter wr=new FileWriter("output.mp4");
int ch;
while((ch=rd.read())!=-1)
wr.write(ch);
wr.flush();
wr.close();
Когда я использую FileReader
а также FileWriter
читать и писать файл mp4, output.mp4
файл не может быть отображен хорошо. Но когда я использую FileInputStream
а также FileOutputStream
вместо этого это работало хорошо.
Итак, я могу заключить FileReader
а также FileWriter
только для чтения и написания текста?
5 ответов
Да, ваш вывод верен подклассам Reader
а также Writer
предназначены для чтения / записи текстового контента. InputStream
/ OutputStream
для бинарного контента. Если вы посмотрите на документацию:
Reader
- Абстрактный класс для чтения потоков символов
InputStream
- Абстрактный класс - это суперкласс всех классов, представляющих входной поток байтов.
FileReader
(и действительно все, что расширяет Reader) действительно для текста. Из документацииReader
:
Абстрактный класс для чтения символьных потоков.
(Акцент мой.) Посмотрите на API, и вы увидите, что все это связано с текстом - char
вместо byte
повсюду.
InputStream
а также OutputStream
предназначены для двоичных данных, таких как файлы mp4.
Лично я бы избегал FileReader
в целом, хотя он всегда использует системную кодировку символов по умолчанию. Вместо этого используйте InputStreamReader
вокруг FileInputStream
... но только когда вы хотите иметь дело с текстом.
Кроме того, это очень неэффективный способ копирования с входа на выход... используйте перегрузки read
а также write
который читает или пишет из буфера - либо byte[]
или char[]
, В противном случае вы вызываете чтение и запись для каждого байта / символа в файле.
Вы также должны закрыть потоки ввода-вывода в finally
блоки закрываются, даже если во время их обработки выдается исключение.
FileInputStream
используется для чтения потоков необработанных байтов данных, таких как необработанные изображения. FileReaders
, с другой стороны, используются для чтения потоков символов
Разница между FileInputStream
а также FileReader
является, FileInputStream
читает файл побайтно и FileReader
читает файл символ за символом.
Поэтому, когда вы пытаетесь прочитать файл, который содержит символ "Č"
, в FileInputStream
даст результат как 196 140
, поскольку ASCII
ценность Č
является 268
,
В FileReader
даст результат как 268
какой ASCII
стоимость символа Č
,
Чтобы понять это полностью, вам нужно понять, что такое поток символов и байтов, поэтому давайте быстро взглянем на это -
Байтовые потоки
Байтовый поток обращается к файлу побайтно. Программы 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.Комментарии в методах говорят сами за себя, пожалуйста, прочтите их, чтобы получить четкое представление о том, как они работают.
FileReader
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
"FileWriter предназначен для записи потоков символов. Для записи потоков необработанных байтов рассмотрите возможность использования FileOutputStream".
http://download.oracle.com/javase/1.4.2/docs/api/java/io/FileWriter.html
FileWriter и FileReader предназначены для потоков символов...
с уважением.
Furkan
Текстовый файл может быть прочитан с использованием обоих fileReader
а также fileInputStream
но mp3 и png можно читать только используя fileInputStream
fileReader
читает символ за символомfileInputStream
читает побайтно