问题描述
这两个行都会在file
中写给我字母A 。有人可以告诉我他们在内部工作上有何不同吗?
FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
fileOutputStream.write(65);
fileOutputStream.write('A');
[EDIT]:我对这两种情况下的转换工作更感兴趣。据我所知,ASCII和UNICODE表是什么。
解决方法
让我们从FileOutputStream
的{{3}}开始。如果您看一下,您会发现有三种write
方法:
void write(byte[] b)
-将指定字节数组中的b.length
个字节写入此文件输出流。void write(byte[] b,int off,int len)
-将指定字节数组中的len
个字节从偏移量off
开始写入此文件输出 流。void write(int b)
-将指定的字节写入此文件输出流。
那它告诉我们什么?
-
很显然,当我们调用
fileOutputStream.write(65)
或fileOutputStream.write('A')
时,我们没有调用write
方法的第一个或第二个重载。我们实际上是在叫第三个。 -
因此,当我们调用
fileOutputStream.write('A')
时,char
值'A'
将转换为int
值。此转换是从char
到int
的原始扩展转换。这等效于进行显式类型转换;即(int) 'A'
。 -
将原始类型从整数类型(例如
char
)强制转换为较大的整数类型(例如int
)仅是使其变大。在这种情况下,我们只需在前面添加16个零位。 (因为char
是未签名的,而int
是已签名的。) -
当我们查看ASCII和Unicode代码表时,我们发现它们都使用相同的字母大写A值。十进制为65,十六进制为41。换句话说,
(int) 'A'
和65
是相同的值。 -
因此,当您进行隐式加宽转换时,
fileOutputStream.write('A')
和fileOutputStream.write(65)
实际上是使用相同的参数值调用write
。 -
最后,
write(int)
的javadoc引用了javadoc,它表示:将指定的字节写入此输出流。写入的一般约定是将一个字节写入输出流。 要写入的字节是参数b的八个低位。 b的24个高位被忽略。
这说明了
int
如何神奇地变成byte
。
请注意,这仅打印出有意义的内容,因为我们在ASCII字符集中选择了一个字符。碰巧Unicode选择将ASCII字符集镜像为前128个Unicode代码点。
如果用ASCII字符集之外的某个字符替换了A
,则很有可能OutputStream::write(int)
会显示乱码。
输出文本时,最好使用FileWriter
而不是FileOutputStream
。