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 предназначены только для чтения и записи текста?


person saravanan    schedule 01.03.2011    source источник


Ответы (6)


Да, ваш вывод правильный, подклассы Reader и Writer предназначены для чтения/записи текстового контента. InputStream / OutputStream предназначены для двоичного содержимого. Если вы посмотрите на документацию:

Reader — абстрактный класс для чтения потоков символов

InputStream — Абстрактный класс является надклассом всех классов, представляющих входной поток байтов.

person Bozho    schedule 01.03.2011
comment
поэтому я могу читать только файл .txt ..потому что pdf, файл word также содержит файлы изображений ..не так ли - person saravanan; 01.03.2011
comment
@saravanan да, только текстовые файлы. pdf и doc — это сложные форматы, для полноценного анализа которых нужны специальные библиотеки. - person Bozho; 01.03.2011
comment
@Bozho: где я могу найти эти библиотеки для использования в моем pgm, и взяли ли создатели Java материал для создания потоков символов только для чтения файлов .txt - person saravanan; 01.03.2011
comment
@saravanan это зависит от ваших конкретных требований. Вы можете задать другой вопрос, спрашивая, что именно вы хотите получить из PDF и/или Doc. Но сначала поищите - уже есть сопутствующие вопросы - person Bozho; 01.03.2011
comment
я отредактировал свой предыдущий комментарий .. вы можете ответить на второй вопрос - person saravanan; 01.03.2011
comment
@saravanan это другой вопрос. - person Bozho; 01.03.2011

FileReader (и действительно все, расширяющие Reader) действительно для текста. Из документации Reader:

Абстрактный класс для чтения символьных потоков.

(Выделение мое.) Посмотрите на API, и вы увидите, что все это связано с текстом — char вместо byte повсюду.

InputStream и OutputStream предназначены для двоичных данных, таких как файлы mp4.

Лично я бы вообще избегал FileReader, так как он всегда использует системную кодировку символов по умолчанию - по крайней мере, до Java 11. Вместо этого используйте InputStreamReader вокруг FileInputStream... но только тогда, когда вы хотите иметь дело с текстом. (В качестве альтернативы используйте Files.newBufferedReader.)

Кроме того, это очень неэффективный способ копирования из ввода в вывод... используйте перегрузки read и write, которые считывают или записывают из буфера - либо byte[], либо char[]. В противном случае вы вызываете чтение и запись для каждого байта/символа в файле.

Вы должны также закрывать потоки ввода-вывода в finally блоках, чтобы они были закрыты, даже если во время их обработки возникает исключение.

person Jon Skeet    schedule 01.03.2011
comment
Герберт Шильдт в своей книге рекомендует использовать потоки символов, чтобы код можно было интернационализировать. Вы имеете в виду, что использование потоков байтов также не повлияет на интернационализацию? - person Amal K; 21.02.2020
comment
@AmalK: Если вы читаете двоичные по своей природе данные, такие как видео, тогда контекст интернационализации отсутствует. Любая рекомендация зависит от контекста, и контекст должен учитываться при рассмотрении рекомендации. - person Jon Skeet; 21.02.2020
comment
@John Skeet Я конкретно имею в виду текстовые данные, как и рекомендация. Влияет ли запись файла с использованием потока байтов на интернационализацию, поскольку там нет контекста кодировки символов? Как насчет упомянуть об этом в своем ответе? Обратите внимание, что начиная с Java 11 FileReader позволяет указывать кодировку. Кроме того, было бы очень важно, если бы вы могли ответить на мой последний вопрос :) - person Amal K; 21.02.2020
comment
@AmalK: Этот вопрос не о текстовых данных. Речь идет о файлах mp4. Я специально вызываю Вместо этого используйте InputStreamReader вокруг FileInputStream... но только тогда, когда вы уже хотите иметь дело с текстом. - person Jon Skeet; 21.02.2020

FileInputStream используется для чтения потоков необработанных байтов данных, таких как необработанные изображения. FileReaders, с другой стороны, используются для чтения потоков символов

Разница между FileInputStream и FileReader заключается в том, что FileInputStream считывает файл побайтно, а FileReader читает файл посимвольно.

Поэтому, когда вы пытаетесь прочитать файл, содержащий символ "Č", в FileInputStream вы получите результат как 196 140, потому что ASCII значение Č равно 268.

В FileReader будет получен результат как 268, который является значением ASCII символа Č.

person satender    schedule 29.04.2014

Чтобы понять это полностью, вам нужно понять, что такое поток символов и байтов, поэтому давайте быстро рассмотрим это:

Потоки байтов

Поток байтов обращается к файлу побайтно. Программы 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

«FileWriter предназначен для записи потоков символов. Для записи потоков необработанных байтов рассмотрите возможность использования FileOutputStream».

http://download.oracle.com/javase/1.4.2/docs/api/java/io/FileWriter.html

FileWriter и FileReader предназначены для потоков символов...

с уважением.

Фуркан

person Furkan    schedule 01.03.2011

Текстовый файл можно прочитать как с помощью fileReader, так и с помощью fileInputStream, но mp3 и png можно прочитать только с помощью fileInputStream

  1. fileReader читает символ за символом

  2. fileInputStream читает байт за байтом

person IshanGarg    schedule 10.07.2016