Преобразование не-Unicode двоичных строк в байтовый массив в Javascript

1

Я прочитал двоичный файл, используя ajax с веб-сервера. HTTP-ответ имеет contentType: "application/octet-stream" и содержит двоичную строку, которая представляет собой просто строку байтов (не unicode), например (в шестнадцатеричном формате):

0x00 0x08 0x17 0xA1 0x01

Примечание: в C это будет представлено в виде 5 байтов в памяти:

char buf[5] = {0, 8, 23, 161, 1}

... но в Javascript, который является строкой, представление ASCII - это что-то вроде " " (я не могу на самом деле вставить ее правильно, поскольку не все символы имеют печатаемое представление).

Теперь мне нужно преобразовать это в массив символов или целых чисел, чтобы я мог получить доступ к числовому значению каждого символа в строке. Однако повторение строки примера с использованием функции charCodeAt() возвращает:

[0] 0
[1] 8
[2] 23
[3] 65533
[4] 1

потому что charCodeAt() декодирует символы Unicode, а 0xA1 не распознается как действительный символ юникода, поэтому вместо этого используется Заменяющий символ (65533).

Я хотел бы получить следующее:

[0] 0
[1] 8
[2] 23
[3] 161
[4] 1

Как достичь этого?

Вот фрагмент кода:

$.ajax({
url: url,
type: "get",
success: function(data) { // data contains binary representation of 0x00 0x08 0x17 0xA1 0x01
    var byteTab = []
    for (var n = 0; n < data.length; ++n) {
        byteTab.push(data.charCodeAt(n))
    }
})
Теги:
string
binary
non-unicode

2 ответа

1

Обновление: я не уверен, что [по умолчанию] Ajax - правильный инструмент для работы в этом случае. Независимо от размера файла, как правило, рекомендуется использовать потоки вместо того, чтобы приспособить будущую масштабируемость, так как ваш текущий метод загружает все сразу.

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

Old: Я не уверен, правильно ли я понял ваше представление данных, но я считаю, что вы можете просто использовать parseInt() чтобы превратить шестнадцатеричную строку в десятичную:

var data = ['0x00', '0x08', '0x17', '0xA1', '0x01'];
var parsed = [];

for(var i = 0; i < data.length; i++) {
	parsed.push(parseInt(data[i], 16));
}

console.log(parsed);
console.log(parseInt('0xA1', 16))

Если это не то, что вы имеете в виду, прокомментируйте, и я попытаюсь обновить свой ответ с более конкретной реализацией.

  • 0
    Извиняюсь, если мой вопрос не был ясен в этом отношении - я теперь обновляю вопрос. Содержимое буфера «data», возвращаемое веб-сервером в моем фрагменте кода, представляет собой строку, соответствующую 5 байтам. В C это может быть представлено как: char buf [5] = {0, 8, 23, 161, 1}. В Javascript это возвращается как строка длиной 5. Sine Javascript не работает с «байтами» или «символами», такими как C, я не могу найти способ получить числовое значение отдельных символов в этой строке, поскольку некоторые, например, 0xA1 (161) не являются символами Юникода.
0

Следуя предложению от ответа Хауса, я нашел еще несколько решений проблемы, поэтому я поделюсь своими выводами здесь.

  1. Мое предпочтительное решение - использовать ArrayBuffer для доступа к необработанным данным. К сожалению, Ajax, похоже, не поддерживает его в соответствии с этой статьей, хотя есть возможность добавить поддержку (которую я не мог заставить работать), и нет простого способа создать ArrayBuffer из строки. Однако XMLHttpRequest поддерживает ArrayBuffer как responseType, как описано здесь, поэтому я изменил свой код на следующее, что делает то, что я хочу:

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.responseType = 'arraybuffer';  
    xhr.onload = function() {
        if (this.status == 200) {
            var byteTab=[]
            var uint8View = new Uint8Array(this.response)
            for (var n = 0; n < uint8View.byteLength; n++) {
                byteTab.push(uint8View[n])
            }
    
        } 
    };
    xhr.send();
    
  2. Другое решение - добраться до ArrayBuffer с помощью Blob, что объясняется примером в этом ответе

  3. Другой вариант - использовать Blob вместе с FileReader.readAsBinaryString() в строках примера здесь. Использование readAsBinaryString() преобразует blob в строку unicode, которая затем может быть проанализирована с использованием charCodeAt()

Ещё вопросы

Сообщество Overcoder
Наверх
Меню