字节流的内部工作。 write(65) 和 write('A') 的区别?

Internal working of byte streams. Difference between write(65) and write('A')?

这两行都会在file中给我写字母A。谁能告诉我他们在内部工作上有何不同?

FileOutputStream fileOutputStream = new FileOutputStream("test.txt");
fileOutputStream.write(65);
fileOutputStream.write('A');

[编辑]:我对这两种情况下的转换方式更感兴趣。据我所知,什么是 ASCII 和 UNICODE 表。

让我们从 FileOutputStreamjavadoc 开始。如果您查看它,您会发现共有三种 write 方法:

  • void write​(byte[] b) - Writes b.length bytes from the specified byte array to this file output stream.
  • void write​(byte[] b, int off, int len) - Writes len bytes from the specified byte array starting at offset off to this file output stream.
  • void write​(int b) - Writes the specified byte to this file output stream.

那么它告诉我们什么?

  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 指的是 this javadoc,它说:

    Writes the specified byte to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.

    这解释了 int 如何神奇地变成 byte


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

如果您将 A 替换为 ASCII 字符集之外的某些字符,则 OutputStream::write(int) 很可能会出现乱码。

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