2014-02-13 7 views
1

Мне нужно использовать DataInputStream, так как мне нужна устаревшая функция readLine(), и я не знаю точного формата файла входного файла (то есть, какой конец строки используется), но также необходимо для чтения двоичных закодированных примитивов.DataInputStream readLine() устарел

Это похоже на этот вопрос:

Is there a class that exposes an unbuffered readLine method in Java?

Мое предложение использовать что-то вроде этого

public class SaveDataInputStream extends DataInputStream { 
    public SaveDataInputStream(InputStream in) {super(in);} 
    public String readLineSave() throws IOException { 
    // ??? 
    } 
} 

и использовать() содержание метода ReadLine, который можно найти в Класс DataInputStream (это похоже на принятый ответ в указанном вопросе). Однако я не совсем понимаю, почему метод был устаревшим и предпочел бы знать, подходит ли он для моего кода.

Javadoc говорит: Этот метод неправильно преобразовывает байты в символы.

Но что это значит? Должен ли я беспокоиться об этом и что может произойти в худшем случае? Можно ли написать собственный метод, который исправляет проблему (эффективность на самом деле не вызывает беспокойства)?

Подсказка: новый BufferedReader (новый InputStreamReader (..)); это неправильный ответ ...

+1

Было бы легче узнать, как читать файл, если вы указали код, используемый для его записи. –

ответ

2

Я не уверен на 100%, но я нашел пример неправильной работы метода по сравнению с BufferedReader.readLine(). Вот код:

import java.io.*; 

public class HelloWorld { 
    public static void main(String[] args) throws Exception { 
    String s = "喜\n"; 
    InputStream in = new ByteArrayInputStream(s.getBytes()); 
    DataInputStream d = new DataInputStream(in); 
    System.out.println(d.readLine()); // prints å 

    in = new ByteArrayInputStream(s.getBytes()); 
    BufferedReader br = new BufferedReader(new InputStreamReader(in)); 
    System.out.println(br.readLine()); // prints 喜 
    } 
} 

В принципе, это не кажется, что DataInputStream обрабатывает многобайтовые символы вообще, так как он в основном делает обугленный следующий = (полукокс) in.read(); для каждого персонажа.

По существу, я считаю, что вам нужно хотя бы очень маленький буфер, чтобы правильно читать многобайтовые символы. Тем не менее, вы, вероятно, можете создать свой собственный метод поверх InputStreamReader напрямую, а не BufferedReader, так как это будет правильно обрабатывать многобайтовые символы. Альтернативно, если вы знаете, что всегда будете иметь дело с ascii, тогда вы, вероятно, будете безопасно использовать устаревший метод.

EDIT: также стоит отметить, что даже DataInputStream буферизует внутренне, чтобы правильно обрабатывать окончание строк. В jdk7, по крайней мере, обращение к \ г является:

  case '\r': 
      int c2 = in.read(); 
      if ((c2 != '\n') && (c2 != -1)) { 
       if (!(in instanceof PushbackInputStream)) { 
        in = new PushbackInputStream(in); 
       } 
       ((PushbackInputStream)in).unread(c2); 
      } 
      break loop; 

Таким образом, если мы сталкиваемся с чем-то вроде \ га, а-непрочитанное обратно на входной теряемом поток, который поддерживает внутренний буфер непрочитанных байт.

+0

Принимает этот ответ, потому что он дает пример метода readLine(). Я не уверен, как бы я решил исправить проблему конверсии, но так как мой ввод - это только ASCII, это меня не беспокоит. – vincent

4

Что они имеют в виду, когда говорят, что readLine() устарел, поскольку он неправильно преобразовывает символы, так это то, что он не позволяет указать кодировку символов, например, UTF-8 и CP1252. Это означает, что данные, написанные с использованием одного символьного кодирования, скорее всего, потерпят неудачу, если вы прочитаете одну систему, которая по умолчанию использовала другую кодировку символов.

Итак, вам нужно беспокоиться об этом? Конечно. Методы устарели, чтобы предоставить разработчикам предупреждение о том, что в будущем они могут исчезнуть. Тем не менее, согласно JavaDoc, readLine() устарел в JDK 1.1, который был LOOONG.

Что касается вашей точки не желая BufferedReader из-за буферизации, я бы сказал, не используйте его. Используйте один из других классов, которые расширяют Reader, или, если вы хотите быть такими экстремальными, сверните свои собственные. Ничто не мешает вам создать свой собственный класс под названием DataInputReader, используя методы для чтения ваших примитивов и обеспечивая правильную реализацию readLine() в соответствии с вашими потребностями.

Однако, если вы читаете двоичные закодированные данные, я бы рекомендовал НЕ использовать Reader вообще и придерживаться InputStream, чтобы вы могли читать необработанные byte и обрабатывать сами конверсии. Reader s были разработаны с учетом кодирования символов и, как таковые, имеют тенденцию изменять то, что вы читаете, в предположении, что он пытается преобразовать двоичные данные в строки символов.

Смежные вопросы