【问题标题】:What is actually difference between InputStream and Reader in javajava中InputStream和Reader之间的实际区别是什么
【发布时间】:2016-03-30 15:48:45
【问题描述】:

当我搜索 InputStreamReader 之间的区别时。我得到了答复。

InputStream: Byte-Base(逐字节读取)

阅读器: Character-Base(逐字符读取)

我将á 字符粘贴到我的操作系统中的ASCII(或可能是其他字符集)为225 的文件中,而字节的max_value 为127。我使用FileInputStream 来读取(),那么为什么它返回225?它如何能够读取多个字节?因为read() 方法一次只读取一个字节或字符。

或者InputStreamReader 之间的实际区别是什么?

【问题讨论】:

    标签: java


    【解决方案1】:

    á 确实有一个 unicode 值 225(这是它的代码点,与它的编码无关)。当您将其转换为一个字节时,您将得到-31。但是,如果您仔细查看 InputStream.read 的文档,您会看到:

    从输入流中读取数据的下一个字节。 值字节以 int 形式返回,范围为 0 到 255。

    (强调)read 方法返回一个 int,而不是一个字节,但该 int 本质上表示一个无符号字节。如果您将该 int 转换为 char,您将返回到 á。如果你将该 int 转换为一个字节,它会返回到 -31。

    更多细节:

    • á 的 unicode 值为 225。
    • Java 中的字符表示为 UTF-16,对于 225,其二进制表示为 00000000 11100001
    • 如果你把它转换成一个字节,它会丢弃高字节,留下11100001。如果将其视为有符号字节,则其值为 -31,但如果视为无符号字节,则值为 225。
    • InputStream.read 返回一个 int 以便它可以将流的结尾表示为 -1。但如果 int 为非负数,则仅设置其低 8 位(十进制值 0-255)
    • 当您将该 int 转换为一个字节时,Java 将丢弃除最低 8 位之外的所有位 - 再次为您留下 11100001

    【讨论】:

    • 你能给我举个例子,让InputStream逐字节读取和Reader逐字符读取完全不同吗?正如我所尝试的那样。
    • 你的意思是读取00000000 11100001,因为字节可以占用8位,所以它将它存储为11100001,即-31,然后再将字节存储为int。 00000000 00000000 00000000 11100001 是 255 吗?
    • 主要是。如果你把那个字节 -31 转换为 int,你实际上仍然会得到 -31——转换使用“符号扩展”,这基本上意味着由于字节的高位(符号位)是 1,左侧的额外位将为 1(不是 0)。但是您可以只应用一个掩码 (i &= 0xff) 来清除这些位。
    • 我试图逐步理解,正如我在倒数第二条评论中试图解释的那样。意思是读取字符然后转换为字节然后转换为整数。你能这样解释吗?
    • 如果您使用的是 InputStream,那么您永远不会读取字符 - 您正在读取字节。但是,如果您编写的字符是á,并且您使用 UTF-8(或 Latin-1)编写了该字符,那么恰好该字符在该编码中的表示是一个字节——并且一切都“正常工作” 。”如果您尝试将'☃' 之类的内容写入文件,您会发现您读取的字节本质上是随机的;雪人字符在 UTF-8 中是 3 个字节,所以你只是在读它的三分之一。我强烈推荐这本入门书:joelonsoftware.com/articles/Unicode.html
    【解决方案2】:

    不同之处在于InputStream 将按原样读取文件的内容,不进行解释:原始字节。

    另一方面,Reader 将使用CharsetDecoder 处理字节输入并将其转换为chars 序列。它处理字节输入的方式将取决于使用的Charset

    这不是1 1的关系!

    另外,忘记“ASCII 值”; Java 不使用 ASCII,它使用 Unicode,char 实际上是一个 UTF-16 代码单元。在 Java 开始时它是一个完整的代码点,但后来 Unicode 定义的 BMP 之外的代码点和 Java 必须适应:U+FFFF 上的代码点现在使用代理对表示,即两个字符。

    请参阅here 以获得更详细的说明。

    【讨论】:

      【解决方案3】:
      • InputStream.read() 返回一个 int。 That is a value between 0 and 255.

      • Byte.MAX_VALUE127Byte.MIN_VALUE-128 这是二进制 10000000。但是 java 不支持无符号原语,因此最高有效字节始终是符号位。

      【讨论】:

      • unsigned primitives 是什么意思?那为什么-127
      • java 不支持无符号原语意味着 java 中的每个原语(字节、整数、长整数等)都保留一个位来定义它是正数还是负数。
      • 127-128 范围的原因是负数不必定义负零,因此它有一个额外的可能值。
      • 抱歉再次混淆。你能给我链接,可以帮助我理解吗?
      • 维基百科有一个很好的解释。 en.wikipedia.org/wiki/Signed_number_representations
      猜你喜欢
      • 2011-05-21
      • 2023-03-08
      • 2021-06-12
      • 1970-01-01
      • 2010-10-22
      • 1970-01-01
      • 2015-03-12
      • 2012-05-08
      • 2011-03-06
      相关资源
      最近更新 更多