在Java中:为什么有些Stream方法采用int而不是byte或甚至是char?

时间:2010-06-30 19:33:40

标签: java character-encoding streaming iostream

为什么将bytes/chars写入流的某些方法需要int而不是byte/char ??

有人在in t而不是char时告诉我: 因为java中的char只有2个字节的长度,对于已经使用的大多数字符符号都可以,但是对于某些字符符号(中文或其他),字符用超过2个字节表示,因此我们改为使用int。

这个解释与真相有多接近?

编辑: 我使用stream字来表示二进制和字符流(不仅仅是二进制流)

感谢。

6 个答案:

答案 0 :(得分:5)

  

有人告诉我int而不是char:因为java中的char只有2个字节长度,大多数字符符号已经在使用,但是对于某些字符符号(中文或其他),该字符正在表示超过2个字节,因此我们使用int。

假设此时您正在专门讨论Reader.read()方法,那么您所叙述的“某人”的陈述其实不正确

确实,某些Unicode代码点的值大于65535,因此无法表示为单个Java char。但是,Reader API实际上会生成一系列Java char值(或-1),而不是一系列Unicode代码点。这在javadoc中明确说明。

如果您的输入包含(适当编码的)Unicode代码点大于65535,那么您实际上需要两次调用read()方法才能看到它。你会得到一个UTF-16代理对;即,在一起的两个Java char值代表代码点。实际上,这符合Java String,StringBuilder和StringBuffer类的工作方式;它们都使用基于UTF-16的表示......带有嵌入的代理对。

Reader.read()返回int而不是char的真正原因是允许它返回-1以表示没有更多字符需要读取。同样的逻辑解释了为什么InputStream.read()会返回int而不是byte

假设,我认为Java设计者可以指定read()方法抛出异常来表示“流结束”条件。但是,这只会将一个潜在的错误源(无法测试结果)替换为另一个(未能处理异常)。此外,异常相对昂贵,并且流的结束并非真正意外/异常事件。简而言之,目前的方法更好,IMO。

Reader API的16位性质的另一个线索是read(char[], ...)方法的签名。如果未使用代理对,如何处理大于65535的代码点?)< / p>

修改

DataOutputStream.writeChar(int)的情况确实有点奇怪。但是,javadoc明确指出该参数被写为2字节值。实际上,实现清楚地只将底部的两个字节写入底层流。

我认为没有充分理由这样做。无论如何,有一个bug数据库条目(4957024),标记为“11-Closed,Not a Defect”,并带有以下注释:

  

“这不是一个很好的设计或借口,但它太过于让我们改变了。”

...这是一种承认 是一种缺陷,至少从设计的角度来看。

但这不值得大惊小怪,IMO。

答案 1 :(得分:3)

我不确定你指的是什么,但也许你在考虑InputStream.read()?它返回一个整数而不是一个字节,因为返回值被重载也表示流的结尾,表示为-1。由于有257个不同的可能返回值,因此一个字节不足。

否则,或许您可以提供一些更具体的例子。

答案 2 :(得分:2)

有一些可能的解释。

首先,正如一些人已经注意到的那样,可能是因为read()必然会返回一个int,因此可以认为write()接受一个int来避免强制转换是优雅的:

int read = in.read();
if ( read != -1 )
   out.write(read);
//vs
   out.write((byte)read);

其次,避免其他的转换案例可能会很好:

//write a char (big-endian)
char c;
out.write(c >> 8);
out.write(c);

//vs
out.write( (byte)(c >> 8) );
out.write( (byte)c );

答案 3 :(得分:0)

最大可能的代码点是0x10FFFF是正确的,它不适合char。但是,流方法是面向字节的,而writer方法是16位。 OutputStream.write(int)写入一个字节,而Writer.write(int)只查看低16位。

答案 4 :(得分:0)

在Java中,Streams用于原始字节。要编写字符,可以在Writer中包装Stream。

虽然Writer确实有write(int)(写入16个低位;它是一个int因为字节太小而短,因为它被签名而太小),你应该使用而是write(char[])write(String)

答案 5 :(得分:0)

可能与read()方法对称,返回一个int。没什么大不了的。