字节流的内部工作 write65和write'A'之间的区别?

问题描述

这两个行都会在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)-将指定的字节写入此文件输出流。

那它告诉我们什么?

  1. 很显然,当我们调用fileOutputStream.write(65)fileOutputStream.write('A')时,我们没有调用write方法的第一个或第二个重载。我们实际上是在叫第三个。

  2. 因此,当我们调用fileOutputStream.write('A')时,char'A'将转换为int值。此转换是从charint原始扩展转换。这等效于进行显式类型转换;即(int) 'A'

  3. 将原始类型从整数类型(例如char)强制转换为较大的整数类型(例如int)仅是使其变大。在这种情况下,我们只需在前面添加16个零位。 (因为char是未签名的,而int是已签名的。)

  4. 当我们查看ASCII和Unicode代码表时,我们发现它们都使用相同的字母大写A值。十进制为65,十六进制为41。换句话说,(int) 'A'65是相同的值。

  5. 因此,当您进行隐式加宽转换时,fileOutputStream.write('A')fileOutputStream.write(65)实际上是使用相同的参数值调用write

  6. 最后,write(int)的javadoc引用了javadoc,它表示:

    将指定的字节写入此输出流。写入的一般约定是将一个字节写入输出流。 要写入的字节是参数b的八个低位。 b的24个高位被忽略。

    这说明了int如何神奇地变成byte


请注意,这仅打印出有意义的内容,因为我们在ASCII字符集中选择了一个字符。碰巧Unicode选择将ASCII字符集镜像为前128个Unicode代码点。

如果用ASCII字符集之外的某个字符替换了A,则很有可能OutputStream::write(int)会显示乱码。

输出文本时,最好使用FileWriter而不是FileOutputStream