首页 > 解决方案 > 文件到字节数组的转换实际上是如何工作的?

问题描述

我有一个代码来打印文件的所有字节:

String txtDocumentName = "data.txt";
File file = new File(txtDocumentName);

byte[] bytes = Files.readAllBytes(file.toPath());

System.out.println("bytes.length: " +  bytes.length);

System.out.println("bytes:");

for (byte currentByte: bytes) {
    System.out.println(currentByte);
}

如果我有data.txt文档内容:

abc

,然后它会打印:

bytes.length: 3
bytes:
97
98
99

其中字节长度为 3,因为我有 3 个字符。97 表示 'a' 字符的 ASCII 码,98 表示 'b' 字符的 ASCII 码,以此类推。

另外,如果我有data.txt一份包含俄语内容的文件:

собака

,然后它会打印:

bytes.length: 12
bytes:
-47
-127
-48
-66
-48
-79
-48
-80
-48
-70
-48
-80

现在我没有得到它的实际作用)

你能解释一下吗?

PS: собака在英语中是狗的意思

如果您还可以解释此技巧如何处理图像文件和视频文件,我会很高兴

标签: javabyte

解决方案


文本字节很特殊,因为缺少一个信息:字节使用什么编码/字符集?在第一种情况下,ASCII 的一些超集。在俄语的第二种情况下,它不是单字节编码(否则长度将是 6)。

因此,这两个文本都可以是 UTF-8,对于每个西里尔字母,它都使用两个设置了高位的字节(因此是“负数”)。当从或转换为 java 的字符串时,必须提供这个缺失和相关的字符集。

byte[] bytes = ...;
String s = new String(bytes, StandardCharsets.UTF_8);
bytes = s.getBytes(StandardCharsets.UTF_8);

对于俄语,您可以在 Windows-1251 中编写文本:

Path cyrPath = file.toPath().resolveSibling("cp1251.txt");
Files.write(cyrPath, s, Charset.from("Windows-1251"));

6 字节,在俄语 Windows 上可读。

如果您有纯二进制、非文本数据,请不要使用 String。由于 String 总是需要在 , 之间进行转换byte[],这可能会出错(并非所有字节数组都是有效的 UTF-8)。

对于真正的二进制数据,只有字节。


推荐阅读