不推荐使用DataInputStream readLine()

时间:2014-02-13 12:19:15

标签: java io deprecated readline datainputstream

我需要使用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 {
    // ???
  }
}

并使用可在DataInputStream类中找到的readLine()方法内容(这类似于引用问题中的已接受答案)。但是,我不完全理解为什么该方法已被弃用,并且更愿意知道它是否与我的代码相关。

javadoc说:此方法无法正确将字节转换为字符。

但这意味着什么?我应该担心这种情况以及在最坏的情况下会发生什么?是否有可能编写我自己的方法来解决问题(效率并不是真正的问题)?

提示:新的BufferedReader(new InputStreamReader(..));不是正确答案......

2 个答案:

答案 0 :(得分:4)

当他们说readLine()因为没有正确转换字符而被弃用时,他们的意思是它不允许您指定字符编码,例如UTF-8与CP1252。这意味着如果读取一个默认为不同字符编码的系统,使用一种字符编码写入的数据很可能会失败。

那么,你需要担心吗?当然。不推荐使用方法向开发人员发出警告,告知他们将来可能会消失。也就是说,根据JavaDoc,{JD} 1.1中已经弃用了readLine(),这是一个LOOONG时间。

至于你因为缓冲而不想要BufferedReader的观点,我会说不要使用它。使用扩展Reader的其他类之一,或者,如果你想成为那么极端,可以使用自己的类。没有什么能阻止您创建自己的类DataInputReader,强调读取基元的方法,并提供适当的readLine()实现以满足您的需求。

但是,如果您正在阅读二进制编码数据,我建议您根本不使用Reader,并坚持使用InputStream,这样您就可以阅读原始byte并自行处理转换。 Reader的设计考虑了字符编码的处理,因此在尝试将二进制数据转换为字符串的前提下,倾向于修改您正在阅读的内容。

答案 1 :(得分:3)

我不是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根本不会处理多字节字符,因为它基本上是char next =(char)in.read();为每个角色。

基本上,我认为您需要至少一个非常小的缓冲区才能正确读取多字节字符。也就是说,您可以直接在InputStreamReader之上构建自定义方法而不是BufferedReader,因为这样可以正确处理多字节字符。或者,如果您知道您总是要处理ascii,那么使用已弃用的方法可能是安全的。

编辑:还值得注意的是,即使DataInputStream在内部缓冲也是为了正确处理\ r \ n行结尾。至少在jdk7中,对\ r的处理是:

          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;

因此,如果我们遇到像\ ra这样的东西,a会被读回到推回输入流上,后者维护一个未读字节的内部缓冲区。