Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   Функция парсинга строки в массив байт. (https://javascript.ru/forum/project/24335-funkciya-parsinga-stroki-v-massiv-bajjt.html)

B~Vladi 26.12.2011 17:01

Функция парсинга строки в массив байт.
 
Понадобилась мне такая функция, но в гугле я её не нашел. С помощью x-yuri мне удалось это сделать:

function parseStrToBuffer (string) {
  var result = [],
  index = 0,
  length = string.length,
  code;

  for (; index < length; index++) {
    code = string.charCodeAt(index);
    if (code <= 0x7f) {
      result.push(code);
    } else if (code <= 0x7ff) {
      result.push(code >>> 6 | 0xc0,
        code & 0x3f | 0x80);
    } else if (code <= 0xffff) {
      result.push(code >>> 12 | 0xe0,
        code >>> 6 & 0x3f | 0x80,
        code & 0x3f | 0x80);
    } else if (code <= 0x1fffff) {
      result.push(code >>> 18 | 0xf0,
        code >>> 12 & 0x3f | 0x80,
        code >>> 6 & 0x3f | 0x80,
        code & 0x3f | 0x80);
    } else if (code <= 0x3ffffff) {
      result.push(code >>> 24 | 0xf8,
        code >>> 18 & 0x3f | 0x80,
        code >>> 12 & 0x3f | 0x80,
        code >>> 6 & 0x3f | 0x80,
        code & 0x3f | 0x80);
    } else if (code <= 0x7fffffff) {
      result.push(code >>> 30 | 0xfc,
        code >>> 24 & 0x3f | 0x80,
        code >>> 18 & 0x3f | 0x80,
        code >>> 12 & 0x3f | 0x80,
        code >>> 6 & 0x3f | 0x80,
        code & 0x3f | 0x80);
    }
  }

  return result;
}

// Test string: ﻰﺠ﷼ﺒ╤Ή
// Result: [ 239, 187, 176, 239, 186, 160, 239, 183, 188, 239, 186, 146, 226, 149, 164, 206, 137 ]
alert(JSON.stringify(parseStrToBuffer(prompt('Enter string'))));


Функция эквивалентна вызову:
new Buffer('string', 'utf8');

в NodeJS.

Правила кодировки UTF8 брал отсюда.

B@rmaley.e><e 26.12.2011 17:38

Цитата:

Сообщение от B~Vladi
в гугле я её не нашел

utf82str — не то?

nerv_ 26.12.2011 17:43

B~Vladi, можете пояснить логику? Есть строка, разбираете по символам, узнаете код символа, а дальше что? Мне сама формулировка непонятна
Цитата:

Сообщение от B~Vladi
Функция парсинга строки в массив байт.


Nekromancer 26.12.2011 17:52

nerv_,
Код символа это ведь число. Число состоит из байт.
В utf8 специальная система кодирования, где один символ разбивается на несколько байт.
А получить массив байт, это получить все байты, просто разбить числа на составляющие.
В простонародье - создать буфер.

nerv_ 26.12.2011 17:55

Nekromancer, спасибо) Просто не понимаю, как после получения числа, отличного от 255 (если байт это от 0 до 255) или от или -128 до 127 (если байт это от -128 до 127) их записать в байты? Сбросить биты по маске? Тогда в чем смыл?

B@rmaley.e><e 26.12.2011 18:02

Цитата:

Сообщение от nerv_
их записать в байты?

Тогда это будет не 1, а несколько байт. (А именно [log_256 n] + 1, где [] — округление с отбрасыванием дробной части, а n — число)

Nekromancer 26.12.2011 18:05

Число в JavaScript это - doubleword (Двойное слово, 4 байта. Ну или uint32).
Каждый байт получается примерно так:
n & 0xFF
n >>> 8
// далее повторяются шаги, в идеале 4 раз

B~Vladi 26.12.2011 18:16

Цитата:

Сообщение от B@rmaley.e><e
utf82str — не то?

Ну вообще это реализация str2utf8. У них не учитываются 31-битные числа. За ссылку спасибо.

Цитата:

Сообщение от B@rmaley.e><e
Есть строка, разбираете по символам, узнаете код символа, а дальше что?

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

Из этой таблице видно, что коды символов могут лежать в некоторых диапазонах. Допустим, если код символа меньше или равно 0x7ff, то символ кодируется одним байтом. Если больше, то несколькими (максимум 6 байт, последняя строка таблицы).

Рассмотрим символ ♫.
Его код 9835, или в бинарном представлении 00100110 01101011, т.е. 16 бит.
UTF8 кодирует 16-битные числа в трех байтах (см. табличку). Т.е. этот символ весит 3 байта, тогда как латинские буквы 1.

Смотрим на табличку:
1110xxxx 10xxxxxx 10xxxxxx

Здесь x - это 1 бит числа, которое мы хотим закодировать. Цифры - служебные биты.
Т.е. мы берём биты числа и раскладываем по нужным местам в соответствующем порядке:

11100010 10011001 10101011
Жирным выделены биты кода нашего символа. Собственно, этим и занимается ветка if(code <= 0xffff):
Цитата:

Сообщение от nerv_
Вижу битовые операторы, но логика их работы не понятна.

Берём нужные биты, двигаем на нужные места (в конец байта) и добавляем служебные в начало.

В итоге, мы получаем 3 байта (3 числа):
Первое: 11100010 - это 226 в десятичной системе.
Второе: 10011001 - это 153 в десятичной системе.
Третье: 10101011 - это 171 в десятичной системе.

Собственно, то что мы и наблюдаем в результирующем массиве.

рони 26.12.2011 18:20

B~Vladi,
this.push(code >>> 24 | 0xf8, это правильно?

B~Vladi 26.12.2011 18:23

Цитата:

Сообщение от рони
this.push(code >>> 24 | 0xf8, это правильно?

Нет, конечно же, исправил. Спасибо, не заметил.

nerv_ 26.12.2011 19:13

Цитата:

Сообщение от Nekromancer
В utf8 специальная система кодирования, где один символ разбивается на несколько байт.

Цитата:

Сообщение от B@rmaley.e><e
Тогда это будет не 1, а несколько байт.

Ну я Вася :lol: Не знаю почему, но думал что необходимо записать все символы 1 байтом) Всем спасибо!

это все работа так влияет) Когда сидишь с кем-то в одном помещении, и у этого "кого-то" весь день рот не закрывается :-E

B~Vladi 26.12.2011 20:45

Цитата:

Сообщение от nerv_
но думал что необходимо записать все символы 1 байтом

Так в кодировке windows-1251, например. Поэтому она не позволяет кодировать больше 255 символов, так как они не влезут в один байт.

Kolyaj 27.12.2011 10:34

Цитата:

Сообщение от nerv_
Ну я Вася Не знаю почему, но думал что необходимо записать все символы 1 байтом) Всем спасибо!

Отличная задача для собеседования: упаковать два байта в один с возможностью дальнейшей распаковки, разумеется. Если в течение пяти секунд, не скажет, что невозможно -- свободен :)

Gozar 27.12.2011 11:56

Цитата:

Сообщение от Kolyaj (Сообщение 146383)
Отличная задача для собеседования: упаковать два байта в один с возможностью дальнейшей распаковки, разумеется. Если в течение пяти секунд, не скажет, что невозможно -- свободен :)

Есть два типа людей, одни хотят работать, другие хотят устроится на работу. Предпочитаю первых, даже если они не ответят на вопрос вообще.

Nekromancer 28.12.2011 11:06

dmitriymar,
вы о чём? Запаковать 2 байта в один в принципе нельзя, это как 2 + 2 = 10.

dmitriymar 28.12.2011 11:07

Фу,гоню хотел написать что возможно текст,но 4 бита не обеспечат все буквы алфавита даж в нижнем регистре любого из языков всего 16 букв можно передать ими.
Но опять,можно уплотнить слегка-вопрос стоит ли того?
В 5 бит можно упаковать нижний регистр русского или англ. алфавита. Итого, в 5 байт-можем упаковать 8 букв.
компрессия практически в 2 раза.
В 6 бит с указанием регистра-20% ,что совсем не мало для крупных-трафик на 20% уменьшить -ощутимо в сравнении -расходы на разработку/экономия трафа-и очень ощутимо

А в 7 бит можно запаковать и регистр и 2 языка.-экономия с утф8 в два раза при использовании только русского и меньше при совместном использовании русского и англ. 8 бит можем использовать для указания что это число ,конечно здесь можем использовать числа от 0 до 127. но ничего не мешает разбивать крупные числа на более мелкие. Итого, имеем в итоге экономию около 50% трафа-совсем не мало.

Цитата:

Сообщение от Nekromancer
вы о чём? Запаковать 2 байта в один в принципе нельзя, это как 2 + 2 = 10.

Вобще можно,при условии что каждый байт использует не более 4 бит.Побитовые операции в языке есть.Можно вытащить,
но это только для узких задач-допустим все данные это числа от 0 до 15. Каждое из них в представлении обычном представляет один байт,но их возможно упаковать в один байт а затем распарсить.
Так что говорить что невозможно-не стоит. Возможно, если задача позволяет.
Да и опять,если применить чуть более сложную систему,то можно запаковать с компрессией более чем в два раза в общем-так что в принципе можно говорить что возможно иметь на входе н байт -на выходе н/2 и соответственно в обратную сторону.Условия задачи выполнены -значит задача успешно решена)

dmitriymar 28.12.2011 11:42

Цитата:

utf8 специальная система кодирования, где один символ разбивается на несколько байт.
кстати,не всё так просто.
http://otvety.google.ru/otvety/threa...295b834537ed63

Nekromancer 28.12.2011 11:56

Цитата:

Сообщение от dmitriymar
Вобще можно,при условии что каждый байт использует не более 4 бит.

2 + 2 = 10 тоже возможно, при условии, что 2 это 5. Байт в программировании это 8мь бит, и я вроде как не помню устройств где это не так. Вы прибегаете к крайностям.
Цитата:

Сообщение от dmitriymar
кстати,не всё так просто.

На первой странице есть алгоритм. Моё общее утверждение не нужно воспринимать как 100%-ное определение.

dmitriymar 28.12.2011 12:10

Цитата:

Сообщение от Nekromancer
На первой странице есть алгоритм. Моё общее утверждение не нужно воспринимать как 100%-ное определение.

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

dmitriymar 28.12.2011 12:13

Цитата:

Сообщение от Nekromancer
Байт в программировании это 8мь бит, и я вроде как не помню устройств где это не так

были "компы" в 50-60 годах, советская разработка, у каких была логика отличная от привычных 0 и 1 ,соответственно и байт у них другой если вообще был.
http://ru.wikipedia.org/wiki/%D0%A2%...B8%D0%BA%D0%B0

Nekromancer 28.12.2011 12:15

dmitriymar,
Несколько это - некоторое количество. Я прекрасно понимаю, что в utf8 для передачи кода символа может быть достаточно и одного байта. Это как бы логично, что код этого знака умещается.

Но я не понимаю к чему вы вообще ведёте.

Nekromancer 28.12.2011 12:16

Цитата:

Сообщение от dmitriymar
были "компы" в 50-60 годах, советская разработка, у каких была логика отличная от привычных 0 и 1 ,соответственно и байт у них другой если вообще был.
http://ru.wikipedia.org/wiki/%D0%A2%...B8%D0%BA%D0%B0

Ну я рад за них. Это ничего не меняет, нууу вообще никак.

dmitriymar 28.12.2011 12:24

Цитата:

Сообщение от Nekromancer
Но я не понимаю к чему вы вообще ведёте.

вот к этому.
Цитата:

Сообщение от Kolyaj
Отличная задача для собеседования: упаковать два байта в один с возможностью дальнейшей распаковки, разумеется. Если в течение пяти секунд, не скажет, что невозможно -- свободен

Возможно,только возможность реализации зависит от задачи и входных данных.И соответственно,утверждать что невозможно,если возможно в частных случаях(а таких в вебе 90%-работа с текстом) -неверно .
90% -возможно объединить
10%-невозможно.
так возможно? если 9 к 1 ?:)

Nekromancer 28.12.2011 12:27

dmitriymar,
Невозможно. У вас есть чёткое определение - упаковать 2 байта в один. Это означает сохранить значения 16ти битов в 8ми.

А с твои подходом я и 8 байт с один определённым битом упакую в байт. Только где мне ещё хранить данные, что мне пришлось упаковать именно так и сколько определённых битов было.

В общем вопрос задаётся естественно в общем виде.

dmitriymar 28.12.2011 12:34

Цитата:

Сообщение от Nekromancer
Невозможно. У вас есть чёткое определение - упаковать 2 байта в один

простите,не соглашусь-поскольку это вопрос прозвучал бы на собеседовании в веб конторе-то в 90% задач решаемых это возможно.
И из области философии -если существует вероятность что это возможно(а это возможно примеры, я привёл)-то утверждение что это невозможно вообще-как раз является неправильным. И соответственно, человека ответившего что это невозможно в принципе не при каких условиях-нужно забраковывать. Мотивация простая-не думает,мыслит шаблонно,говорит то что хотят от него услышать и прочее...
В нашей жизни нет чёткого чёрного или белого чтоб мыслить шаблонами.
А если мыслить так,то архиваторов в природе не должно быть,но вы ими ведь пользуетесь?

Nekromancer 28.12.2011 12:39

dmitriymar,
Когда дадут частный пример на собеседовании, тогда и будешь фантазировать и думать как решить. Я считаю, что всегда на собеседовании нужно уточнять, что имеется введу, когда вопрос не однозначный.

На счёт философии, увы, не готов обсуждать это.

Kolyaj 28.12.2011 12:43

dmitriymar,
вы почему-то в моей формулировке вместо фразы "два байта" видите слово "символ", хотя там однозначно написано два байта без указания, что в этих байтах хранится.

dmitriymar 28.12.2011 12:46

Цитата:

Сообщение от Nekromancer
Я считаю, что всегда на собеседовании нужно уточнять, что имеется введу, когда вопрос не однозначный.

дак я и не считаю этот вопрос однозначным. а примирительно к веб(практически весь объём передаваемой информации текст) это возможно практически на 100%. и вопрос звучащий на собеседовании в веб конторе уже определяет частично контекст применения:)

dmitriymar 28.12.2011 12:47

Kolyaj,
возможно не правильно вас понял,но и вы не уточняете вопрос общий или применителен к веб.
а учитывая что вы веб разработчик контекст я бы определил относительно веб,а для веб ответ однозначен-возможно в большинстве случаев
Абстрактный пример,контора занимается уменьшением трафа передаваемой информации по сети.
Собеседование:
Возможно?
НЕТ.
А если подумать?
НЕТ.
До свидания.Вы не подходите

Nekromancer 28.12.2011 12:49

dmitriymar,
Этот вопрос как раз однозначный. Байт в вебе ничем не отличается. Особенно в наши дни, речь легко может идти о графике или о ячейки памяти. Так что байт в первую очередь это байт, ну как бы логично.

dmitriymar 28.12.2011 12:58

Цитата:

Сообщение от Nekromancer
Так что байт в первую очередь это байт, ну как бы логично.

байт это объём информации содержащий 8 бит.-и задача сократить количество байт хранящих этот объём информации.
можно ли сократить количество байт хранящих информацию(запаковка/распаковка) без изменения количества информации -да.архиваторы явный пример. в вопросе была фраза упаковка распаковка. Пример документ вёрд- упакованный/распакованный -разница более чем в два раза

если речь не идёт о 2х конкретных байтах,да и то нужно смотреть возможно или нет
если каждый из байт содержит число до 127-то возможно
если любой число от 128 до 255-то не возможно
дай однозначный ответ исходя из этого-возможно или нет?

Nekromancer 28.12.2011 13:14

dmitriymar,
Ну вот и вы дошли до упоминания бит. А если у меня занято уже 9 бит из 16ти, то видимо нельзя запаковать, да?

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

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

Отвечая на последний ваш вопрос:
2 байта однозначно упаковать в один невозможно. Возможно упаковать 8 любых бит их этих байт 2х байт. Так как по определению - байт, это 8 произвольных бит, состоящих из единиц и нулей, то в один байт можно упаковать только один байт.

Так доказываются теоремы в математике.

dmitriymar 28.12.2011 13:25

Цитата:

Сообщение от Nekromancer
Так доказываются теоремы в математике.

Явно полез в дебри.
Тем более веб,когда мы знаем что придёт на наш запрос и как работать с этой информацией,Сами задаём форматы,правила.Там где возможны варианты ,однозначности быть не может. Точнее,однозначно будет то,что если правильно задали параметры для задачи и решение согласно этим параметрам-то однозначно получим правильный результат и однозначно будет выигрыш в чём то(зависит не велосипед ли изобретаем,ну и от степени сумашествия гения):)

nerv_ 28.12.2011 13:44

Всем привет) Немного почитал тему, и увидел, что речь в ней идет об архиваторах. Как именно работают их алгоритмы мне не известно, но согласно этой статье LZMA и этому разъяснению Метод сжатия с использованием словаря.
Иными словами, это
Цитата:

Сообщение от Kolyaj
упаковать два байта в один с возможностью дальнейшей распаковки

просто не возможно.

Еще можно вспомнить про хеширование, но оно не позволит решить вышеупомянутую задачу.

Kolyaj 28.12.2011 13:53

Архиваторы умеют архивировать только какое-то подмножество данных. Для любого архиватора можно найти последовательность произвольной длины, которую он не сможет сжать. Т.е. в общем случае сжать два байта в один нельзя. Частное решение именно для двух байт можно было бы послушать, я пока не вижу. Три упаковать в два легче.

dmitriymar 28.12.2011 14:01

Цитата:

Сообщение от nerv_
Немного почитал тему, и увидел, что речь в ней идет об архиваторах

об архиваторах речь не идёт. поскольку изначально ясно что если паковать н байтов ,то колимество будет m(количество после пакования)+1 указывающий что упаковку-в лучшем случае.
речь идёт о вебе,где можно создать изначально структуру и изначально знать что в ней без доп байт,что в большинстве случаев реализуемо и в этом случае можем получить вместо 2 х байт 1 и распаковать их назад без последствий.поэтому применительно к веб нет ответа однозначного

dmitriymar 28.12.2011 14:01

Цитата:

Сообщение от Kolyaj
Для любого архиватора можно найти последовательность произвольной длины, которую он не сможет сжать.

также можно найти последовательность какую он сожмёт не в 2 раза а в 15 и более

B~Vladi 28.12.2011 14:11

Цитата:

Сообщение от Kolyaj
Частное решение именно для двух байт можно было бы послушать

Цитата:

Сообщение от dmitriymar
в этом случае можем получить вместо 2 х байт 1 и распаковать их назад без последствий

dmitriymar, так расскажи нам скорее:yes:

dmitriymar 28.12.2011 14:15

Цитата:

Сообщение от B~Vladi
dmitriymar, так расскажи нам скорее

Я не читал первую страницу этой темы.
глянь там ранее. ты когда делаешь аякс запрос и знаешь что придёт текст -ничего не мешает его соответствующе упаковать на сервере и распаковать на клиенте.XHR2 позволяет. вопрос сколько ресов сожрёт
Цитата:

Сообщение от Kolyaj
Частное решение именно для двух байт можно было бы послушать, я пока не вижу. Три упаковать в два легче.

посмотри там выше -для текста -с 2х байт утф8 получаем один -если речь идёт об использовании текстовой информации на 2х языках,при условии что мы знаем какие это языки и ограничиваем набор символов-в пределах разумного
конечно,частично повторяет принцип утф8 с латиницей,но в варианте с русским сокращает объём,да и чарсет у страницы остаётся утф-8-что в плюс.

Nekromancer 28.12.2011 14:21

dmitriymar,
а как распаковать?

Кстати можно при желании и в первом лвле, но всё вопрос.


Часовой пояс GMT +3, время: 14:02.