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

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

  2. fileInputStream читает побайтно

Другие вопросы по тегам