java - 文件到字节数组的转换实际上是如何工作的?

标签 java byte

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

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:собака在英语中的意思是

如果您也能解释一下这个技巧如何处理图像文件和视频文件,我会很高兴

最佳答案

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

因此,两个文本都可以采用 UTF-8 格式,对于每个西里尔字母,都使用两个具有高位设置的字节(因此为“负”)。当从 java 的字符串转换或转换为 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)。

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

关于java - 文件到字节数组的转换实际上是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59935273/

相关文章:

java - Espresso : Interact with Play Store Popup

c - 这不是逐字节比较 : WHY

java - 将 byte[] 转换为 Java 字符串。添加一个?在每次转换中

c# - 将 "1.5TB", "500MB"转换成单个文件大小单位

C - 如何在内存级别进行算术转换?

java - Hibernate 5 无法比较字符串和 int

java - 将 PHP 输出流传递给 Java

java - 如何从 akka 流源获取迭代器?

java - 通过java程序读取另一个软件文件

java - 将方法应用于流