【问题标题】:Java char contains value > 255?Java char 包含的值 > 255?
【发布时间】:2010-09-22 00:08:41
【问题描述】:

我从套接字得到一个字符数组:

char[] cbuf = new char[3];
inputStream.read(cbuf, 0, 3); // read 3 chars in buffer "cbuf", offset = 0

然后当我打印时:

System.out.println("r:"+(int)cbuf[0]+" g:"+(int)cbuf[1]+" b:"+(int)cbuf[2]);

我明白了:

...
r:82 g:232 b:250
r:82 g:232 b:250
r:66 g:233 b:8224

8224的值远大于255,char怎么能包含这个值???

谢谢

【问题讨论】:

  • 问题是您通过“Reader”而不是“InputStream”读取数据。阅读器使用编码将字节转换为字符,在您的情况下可能是 windows-1252。请参阅下面的答案。
  • 我假设您来自 C 背景,其中 sizeof(char) == sizeof(byte),但是即使在 C 中,我也建议您使用无符号字节,因为 r/g/b 的值不是字符。

标签: java char


【解决方案1】:

Java 中的 char 原语为 16 位宽,用于容纳标准 ASCII 范围之外的字符,使用 Unicode

您似乎正在尝试将 RGB 值存储在 char[3] 中。我可以推荐一个byte[3],还是java.awt.Color

Color c = new Color(255, 255, 240);

【讨论】:

  • @sje397:不,我的意思是Modified UTF-8 and CESU-8
  • @Michael Petrotta:不,你的意思是 UTF-16。确实,Java 也使用修改后的 UTF-8,但不是用于 char 类型:它根本不能,因为对于任何 >= U+0800 的字符都需要超过 16 位。 Java 1.4 及更早版本使用 UCS-2,Java 1.5 切换到 UTF-16。
  • @Stephen, @Michael:你当然是对的——从逻辑上讲,它必须如此。我已经编辑了我的答案。
  • 使用字符而不是字节的提示是正确的,但是我不明白 java.awt.Color 应该如何帮助他完成从流中实际读取 rgb 值的任务。
  • @Grodriguez:我想 OP 打印颜色通道值只是为了查看它们是什么,或者作为调试步骤。他可能想稍后对通道做一些事情,如果他使用惯用的 Java 处理值,这可能会更容易。
【解决方案2】:

InputStream 上没有 read(char[], int, int) 方法。您必须在 Reader 子类(例如 InputStreamReader)上调用它。 InputStreamReader 使用平台默认字符编码自动将字节转换为字符,在您的情况下,它看起来像 windows-1252

您收到的字符,8224 是 Unicode 字符U+2020 Dagger '†'。这可能是使用 windows-1252 字符编码从字节 0x86 (134) 转换而来的。

如果您正在阅读包含非文本内容的文件,则需要确保您没有使用 Reader 的子类来阅读它,而是使用 InputStream 的子类。或者,您可以使用 InputStreamReader 并指定像 ISO-8859-1 这样的字符编码,它将每个字节映射到具有相同数值的字符。

【讨论】:

  • 澄清:查找变量“inputStream”[原文如此]的创建位置;很可能它是使用 socket.getInputStream() 创建的。删除包装的 InputStreamReader 并确保使用原始 InputStream。改为读入 byte[]。确保协议实际上按照您认为的顺序发送了 3 个字节;最后,考虑使用 Color。
  • 谢谢+1。 (我不知道 char 是 16 位,所以我接受了另一个答案)
【解决方案3】:

char type in Java 是 16 位的。

如果您正在寻找 8 位数据类型,请考虑使用 byte

【讨论】:

  • 如果您使用 BMP 之外的字符,则不会。 char 包含的是 UTF-16 代码单元。
【解决方案4】:

正如人们已经指出的那样,您要读取字节而不是字符(字符在 Java 中是 16 位),并确保您实际使用的是 InputStream 而不是 Reader

我还想指出与您的问题没有直接关系的内容:调用InputStream.read(byte[])InputStream.read(byte[], int, int) 读取多个字节时,不要假设所有请求的字节在返回时都已读取。只要 一些 字节可用,对read 的调用可能会返回。您应该始终检查返回值以了解实际读取了多少字节。

这同样适用于Reader 中的read 方法。

【讨论】:

    【解决方案5】:

    Java 使用 UTF(不是 ASCII)来存储字符,UTF 是 16 位长,因此它可以包含高达 65.535 的值。

    【讨论】:

    • 不完全正确。 UTF-16 是 16 位“长”。 UTF-8 是 8 位“长”。虽然这是对“long”这个词的灵活使用,因为对于某些代码点,每个都可以有更长的序列。
    • JLS 3.1:“...Java 编程语言使用 UTF-16 编码以 16 位代码单元序列表示文本。...”java.sun.com/docs/books/jls/third_edition/html/…
    【解决方案6】:

    字符是 Java 中的无符号 16 位整数。虽然从技术上讲,如果您从不受信任的字节码接收值,则必须准备好处理任意 32 位值,因为 JVM 不会对整数参数范围进行任何验证。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-09
      • 2022-01-04
      • 1970-01-01
      • 2015-11-26
      • 2011-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多