Почему байт в Java I / O может представлять символ? - PullRequest
2 голосов
/ 17 сентября 2010

Почему байт в Java I / O может представлять символ?

И я вижу символы только ASCII.Тогда это не динамично, верно?

Есть ли какое-то объяснение этому?

В чем разница между байтовыми потоками и символьными потоками?

Ответы [ 4 ]

32 голосов
/ 17 сентября 2010

Байты не являются символами. В одиночку они не могут даже представлять символов.

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

Только один раз в сочетании с кодировкой байты могут представлять символы. В некоторых кодировках (например, ASCII или ISO-8859-1) один байт может представлять один символ ... и многие кодировки даже совместимы с ASCII (это означает, что коды символов от 0 до 127 соответствуют определению ASCII для них). .но без оригинального отображения вы не знаете, что имеете.

Без кодирования байты являются просто 8-разрядными целыми числами.

Вы можете интерпретировать их как угодно, наложив на них кодировку. Это именно то, что вы делаете, когда вы конвертируете byte в char, скажем new String(myBytes) и т. Д., Или даже редактируете файл, содержащий байты, в текстовом редакторе. (В этом случае это редактор, применяющий кодировку.) При этом вы можете даже получить что-то, что имеет смысл. Но, не зная оригинальной кодировки, вы не можете точно знать, что эти байты должны были представлять.

Это может быть даже не текст.

Например, рассмотрим последовательность байтов 0x48 0x65 0x6c 0x6c 0x6f 0x2e. Это можно интерпретировать как:

  • Hello. в ASCII и совместимых 8-битных кодировках;
  • dinner в какой-то 8-битной кодировке, которую я придумал, чтобы доказать это;
  • 䡥汬漮 в формате с обратным порядком байтов UTF-16 *;
  • стальной синий пиксель, за которым следует серовато-желтоватый, в RGB;
  • load r101, [0x6c6c6f2e] на каком-то неизвестном языке ассемблера процессора;

или любой другой миллион вещей. Эти шесть байтов не могут сказать вам, какая интерпретация верна.

С текстом, по крайней мере, для этого нужны кодировки.

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


Разница между потоком байтов и потоком символов заключается в том, что поток символов пытается работать с символами, а не байтами. (На самом деле он работает с единицами кода UTF-16. Но поскольку мы знаем кодировку, этого достаточно для большинства целей.) Если он обернут вокруг потока байтов, поток символов использует кодировку для преобразования байтов, считанных из базового потока байтов. char с (или char с записано в поток в байтах).

* Примечание: я не знаю, является ли "䡥 汬 漮" ненормативной лексикой или даже имеет какой-либо смысл ... но компьютер не знает, если вы не запрограммируете его для чтения на китайском языке.

9 голосов
/ 17 сентября 2010

Байты могут представлять некоторые символы по той же причине, что int может представлять long.

Char является 16-битным.Байт 8 бит.Кроме того, char не подписан, байт подписан.

Попробуйте сделать это:

char c = 'a';
System.out.println(c);
byte b = (byte)c;
c = (char)b;
System.out.println(c);

Это выдаст:

a
a

Теперь попробуйте заменить 'a' на nDash(Юникод 2013).Вот так:

char c = '–';
System.out.println(c);
byte b = (byte)c;
c = (char)b;
System.out.println(c);

Будет выведено:

–

3 голосов
/ 29 сентября 2010

В C и C ++ char содержит один байт, а типы char используются для обозначения 8-разрядного целого числа, а также одного символа текста.Java не подобен этому.

В Java char и byte - это разные типы данных.char содержит один символ Unicode, который (как правило) больше байта.byte содержит 8-битное целое число.Когда вы преобразуете char (или char[] или String) в байтовый массив (тип byte[]), строка кодируется в соответствии с некоторой кодировкой символов (обычно UTF-8), и в результате получается какэта конкретная строка будет храниться в памяти (или на диске), если она была записана в соответствии с этой кодировкой символов.

Java IO поддерживает чтение байтовых массивов (byte[]) непосредственно на диск или с диска, потому что такобычно работает с бинарными файлами (т. е. нетекстовыми файлами, где разрывы строк не должны преобразовываться, а строки не должны перекодироваться).Байты в этом файле могут соответствовать символам в 8-битной кодировке (например, ASCII или ISO8859- *), но если вы собираетесь использовать их таким образом, вам следует выполнить явное преобразование вchar[] или String).

0 голосов
/ 02 декабря 2011

Причина, по которой это байт, связана с историческими американскими вычислениями.Память, скорость, память - все это было чрезвычайно дорого (и большое ), когда были изобретены базовые вычислительные концепции.Проекты были очень упрощены и были ориентированы на североамериканский англоязычный мир (и в некоторой степени все еще остаются).

Несколько байтов, таких как int, были добавлены только после открытия иностранного (в США) рынкаи у компьютеров было больше оперативной памяти и места для хранения.Мир использует сложные системы письма, такие как китайский, для которых требуется более одного байта на символ .Вы, вероятно, из той части мира, где требуются многобайтовые символы.Когда я изучал программирование в Северной Америке, все, что мне нужно было учитывать, - это символы ASCII.Java-дизайнеры тоже были в основном из Северной Америки.

Например, китайский логографический письменный алфавит огромный по моим североамериканским abcdefghijklmnopqrstuvwxyz стандартам.

...