Как преобразование файла в байтовый массив на самом деле работает? - PullRequest
0 голосов
/ 27 января 2020

У меня есть код для печати всех байтов файла:

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 означает ASCII-код символа «a», 98 означает ASCII-код символа «b» и т. Д. c.

также, если у меня будет data.txt документ с содержанием на русском языке:

собака

, тогда он напечатает:

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

и теперь я не понял, что он на самом деле делает)

Не могли бы вы объяснить мне?

PS: собака означает собака на английском sh

Я буду счастлив, если вы тоже могу объяснить, как этот трюк работает с файлами изображений и видеофайлами

Ответы [ 3 ]

2 голосов
/ 27 января 2020

Текстовые байты являются специальными, поскольку отсутствует одна информация: какую кодировку / кодировку используют байты? В первом случае какой-то надмножество ASCII. Во втором случае с русским языком это не однобайтовая кодировка (в противном случае длина должна быть 6).

Таким образом, оба текста могут быть в формате UTF-8, который для каждой буквы кириллицы c использует два байта с высокой бит установлен (следовательно, «отрицательный»). Этот отсутствующий и связанный набор символов должен быть предоставлен при конвертации из или в строку 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 всегда требуется преобразование между byte[], и это может go неверно (не все байтовые массивы являются допустимыми UTF-8).

Для действительно двоичных данных есть только байты.

0 голосов
/ 27 января 2020

Существует много различных систем кодирования, которые определяют, как символ (который является символом или «глифом», используемым при написании) должен быть представлен как число.

Поскольку вокруг используется так много различных символов Мир, не все из них могут быть закодированы в один байт. Для языков с относительно небольшим количеством символов может использоваться один байт, но необходимо указать «кодировку символов» - таблицу, в которой показан код для данного символа.

Другие языки, например китайский или В японском языке используется много символов, и может использовать фиксированное число байтов для каждого символа.

Если вы хотите иметь возможность кодировать любой символ из любого языка в одном файле, вы можете использовать многобайтовую кодировку, например UTF-8. Похоже, это то, что используется здесь , Когда кодированный текст отправляется в Интернете, заголовок должен указывать, какая кодировка используется. В файловой системе формат файла может записывать эту информацию или может использоваться значение по умолчанию для этой системы. Использование этого значения по умолчанию или попытка угадать часто приводит к повреждению текста.

Вы можете прочитать длину и расшифрованный текст из вашего файла следующим образом:

Path file = Paths.get("data.txt");
byte[] bytes = Files.readAllBytes(file);
System.out.println("bytes.length: " +  bytes.length);
System.out.println("decoded:" + new String(bytes, StandardCharsets.UTF_8));
0 голосов
/ 27 января 2020

То же самое. Примите во внимание тот факт, что каждый символ является кодовой единицей, которая представляет кодовую точку Unicode в кодировке UTF-16, а строка, в свою очередь, состоит из последовательности символов. Так что для русского языка вы получаете 2 байта на символ.

...