DataInputStream vs InputStreamReader,试图在概念上理解这两者

ros*_*man 6 java inputstreamreader datainputstream

正如我暂时理解它:

DataInputStream是一个InputStream子类,因此它读取和写入字节.如果您正在读取字节,并且您知道它们将是ints或其他一些原始数据类型,那么您可以byte使用它直接读取它们DataInputStream.

  • 问题:在读取内容之前,您是否需要知道正在读取的内容的类型(int,string等)?并且整个文件是否需要由一个原始类型组成?

我遇到的问题是:为什么不使用InputStreamReader缠绕InputStream的字节数据?使用这种方法,您仍然在读取字节,然后将它们转换为表示字符的整数.哪个整数表示哪些字符取决于指定的字符集,例如"UTF-8".

  • 问题:在什么情况下,如果InputStreamReader工作无效DataInputStream

我的猜测答案:如果速度真的很重要,你可以做到,那么将InputStream字节数据直接转换为原始数据DataInputStream将是要走的路?这避免了Reader必须将字节数据"转换"为int第一个; 并且它不依赖于提供一个字符集来解释返回的整数表示哪个字符.我想这就是人们的意思,DataInputStream允许机器独立读取底层数据.

  • 简化:DataInputStream可以将字节直接转换为基元.

引发整个事情的问题:我正在阅读以下教程代码:

    FileInputStream fis = openFileInput("myFileText");

    BufferedReader reader = new BufferedReader( new InputStreamReader( new DataInputStream(fis)));

    EditText editText = (EditText)findViewById(R.id.edit_text);

    String line;

    while(  (line = reader.readline()) != null){

        editText.append(line);
        editText.append("\n");
    }
Run Code Online (Sandbox Code Playgroud)

...我不明白教师为什么选择使用new DataInputStream(fis)它,因为它看起来不像直接从字节转换为基元的任何能力正在被利用?

  • 我错过了什么吗?

感谢您的见解.

J4v*_*4v4 6

InputStreamReader和DataInputStream是完全不同的.

DataInputStream是一个InputStream子类,因此它读取和写入字节.

这是不正确的,InputStream只读取字节,DataInputStream扩展它,因此您也可以读取Java原语.它们都不能写任何数据.

问题:在读取内容之前,您是否需要知道正在读取的内容的类型(int,string等)?并且整个文件是否需要由一个原始类型组成?

DataInputStream只应用于读取以前由DataOutputStream写入的数据.如果不是这种情况,您的DataInputStream不太可能"理解"您正在读取的数据,并将返回随机数据.因此,您应该确切地知道相应的DataOutputStream以哪种顺序写入了哪种类型的数据.

例如,如果要保存应用程序的状态(假设它包含几个数字):

public void exit() {
    //...
    DataOutputStream dout = new DataOutputStream(new FileOutputStream(STATE_FILE));
    dout.write(somefloat);
    dout.write(someInt);
    dout.write(someDouble);
}

public void startup() {
    DataInputStream dout = new DataInputStream(new FileInputStream(STATE_FILE));
    //exactly the same order, otherwise it's going to return weird data
    dout.read(somefloat);
    dout.read(someInt);
    dout.read(someDouble);
}
Run Code Online (Sandbox Code Playgroud)

这基本上就是DataInputStream和DataOutputStream的整个故事:将原始变量写入流并读取它们.

现在,InputStreamReader是完全不同的东西.InputStreamReader将编码文本"转换"为Java字符.您基本上可以使用任何文本流(知道其编码)并使用InputStreamReader从该源读取Java字符.

使用这种方法,您仍然在读取字节,然后将它们转换为表示字符的整数.哪个整数表示哪些字符取决于指定的字符集,例如"UTF-8".

字符编码不仅仅是代码点和字符之间的简单映射.除此之外,它还指定了代码点在内存中的表示方式.例如,UTF-8和UTF-16共享相同的字符映射,但如果您尝试将UTF-8流读取为UTF-16,则InputStreamReader将显着失败.字符串aabb由四个字节UTF-8('a','a','b','b')表示,将转换为两个字符.两个a和b的值将被视为一个字符.我懒得查看那些角色,但它们会非常奇怪.

如果您知道编码,则InputStreamReader处理所有内容,因此能够从任何源(与DataInputStream不同)读取文本.

问题:在什么情况下,InputStreamReader无法在DataInputStream工作的地方工作?

这一点现在应该很清楚了.由于两个类的目的完全不同,所以不应该问这个问题.一个InputStreamReader并没有字节转换像一个DataInputStream整数,而不是为此目的设计的.

在教程代码中,我很确定您可以省略DataInputStream:

BufferedReader reader = new BufferedReader( new InputStreamReader(fis));
Run Code Online (Sandbox Code Playgroud)

但是,DataInputStream提供了与InputStream相同的方法,这就是为什么将FileInputStream包装在其中并没有错(尽管它是不必要的).