2016-05-25 2 views
0

На сайте есть похожие вопросы, но все они использовались в разных сценариях. Итак, я спрашиваю его здесь:Почему метод FileInputStream read() ошибочно читает знак вопроса (ascii: 63) при вводе в бесконечный цикл?

package Assign6B; 

import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 

public class FileOpsDemo { 
    public static void main(String[] args) throws IOException 
    { 

     FileInputStream inputFile = null; 
     FileOutputStream outputFile = null; 

     try 
     { 
      inputFile = new FileInputStream("s:/inputFile.txt"); 
      outputFile = new FileOutputStream("s:/outputFile.txt"); 
      char c; 
      while((c = (char) inputFile.read()) != -1) 
      { 
       System.out.println((char)c); 
       outputFile.write(c); 
      } 

      System.out.println("File transfer complete!"); 
     } 

     finally 
     { 
      if (inputFile != null) 
       inputFile.close(); 

      if (outputFile != null) 
       outputFile.close(); 
     } 
    } 
} 

Это мой код. В условии while while я сначала установил его для вывода вывода int через read() в char. В результате он перешел в бесконечный цикл со всеми символами, которые были преобразованы в '?' (ascii: 63). Затем я осознал свою ошибку преобразования символов и изменил ее.

Но когда я изменил условие while на «= -2» (без преобразования символов) (это условие никогда не произойдет и, следовательно, поместит его в бесконечный цикл). Здесь, даже если нет преобразования символов, первые (скажем, 10) действительные символы файла все еще преобразуются в '?'. (После того, как он достигнет EOF, все недопустимые символы становятся «?» - я предполагаю, что это дано).

Почему это происходит? По крайней мере, допустимые символы файла должны быть правильно прочитаны, пока не встретится с EOF и не начнет подавать недопустимые символы!

ответ

0

Просто измените этот раздел кода - как только вы конвертируете в char, вы не можете сравнить его с целым числом успешно, поэтому ваше условие выхода не выполняется.

int c; 
while ((c = inputFile.read()) != -1) { 
    System.out.println((char) c); 
    outputFile.write(c); 
} 

Также с помощью Java 8 java.nio и java.io пакеты гораздо проще

public static void main(String[] args) throws IOException { 
    List<String> lines = Files.readAllLines(Paths.get("s:/inputFile.txt")); 
    Files.write(Paths.get("s:/outputFile.txt"), lines); 
} 
0

типажей результат in.read() обугливаться плохой стиль. Символы должны читать только из Reader - в вашем случае вы можете использовать InputStreamReader:

inputFile = new FileInputStream("s:/inputFile.txt"); 
    outputFile = new FileOutputStream("s:/outputFile.txt"); 
    Reader inputReader = InputStreamReader(inputFile, StandardCharsets.UTF_8); 
    Writer outputWriter = OutputStreamWriter(outputFile, StandardCharsets.UTF_8); 
    char[] cbuf = new char[4096]; 
    int read; 
    while((read = inputReader.read(cbuf)) >= 0) 
    { 
     System.out.println(new String(cbuf, 0, read)); 
     outputWriter.write(cbuf, 0, read); 
    } 

В этом примере, кроме того, не копирует байт за байтом (массовое улучшение скорости) и применяется UTF-8 в качестве кодировки.

+0

* "типажей а результат in.read() на char - это плохой стиль. "* - Не только плохой стиль. В зависимости от фактической кодировки файла это может быть просто неверно. –

+0

Кроме того, трудно написать UTF-8, вероятно, плохая идея. Более безопасным предположением было бы использовать кодировку по умолчанию для чтения и записи. –

1

Почему это происходит?

Проблема заключается в этой строке:

while((c = (char) inputFile.read()) != -1) 

Вы делаете следующее:

  1. Чтение байта из файла. Это дает вам int, который является либо байтом в диапазоне от 0 до 255, либо -1.

  2. Вы вводите это значение в char. Для байта, который дает значение char в диапазоне от 0 до 255. Для -1 литой вы получите '\uffff'.

  3. Вы назначаете это значение c.

  4. Затем вы проверяете значение на -1. Здесь все идет не так. В случае, когда read вернулся -1, вы сейчас будете оценивать это '\uffff' == -1. LHS преобразуется в значение int ... 0x0000ffff ... и это сравнивается с 0xffffffff.Они разные.

Тогда вы печатаете 'uffff' ... который преобразуется в '?' при выводе в качестве символа в вашей кодировке по умолчанию.


В коде есть две основные ошибки. Во-первых, конверсия int ->char ->int не собирается работать; см. выше.

Во-вторых, что более важно:

  • вы не должны пытаться использовать InputStream (который ориентирован байт) для чтения данных в виде символов, а

  • вы должны пытаться написать символьные данные в OutputStream.

В зависимости от того, что вы на самом деле пытаетесь достичь здесь, вы должны либо:

  • чтения и записи байтов ... без паразитных «преобразования» в char в середине, ИЛИ

  • используйте FileReader и FileWriter, чтобы сделать преобразования правильно для набора символов по умолчанию платформы.

(Есть и другие моменты, которые могут быть сделаны о буферизации, выбрав другой набор символов, и т.д., но это ответ уже становится слишком долго.)

+0

Эта логика работает, когда FIS читает «-1» EOF. Но я получаю все символы, выводимые на -1 (и, следовательно,?), Даже допустимые символы файла ... почему он читает EOF для допустимых символов файла .. или я что-то упустил здесь? –

+0

Я думаю, что вы неверно истолковываете вещи. 1) Невозможно, чтобы 'char' был' -1', потому что 'char' является типом >> unsigned <<. 2) Когда символ 'char' преобразуется в'? 'На выходе, это означает, что значение символа (независимо от того, что оно есть) не имеет действительной кодировки в используемой схеме кодирования символов. Вы не можете сделать вывод, какова была его фактическая ценность. –