Я прочитал двоичный файл, используя 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))
}
})
Обновление: я не уверен, что [по умолчанию] 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))
Если это не то, что вы имеете в виду, прокомментируйте, и я попытаюсь обновить свой ответ с более конкретной реализацией.
Следуя предложению от ответа Хауса, я нашел еще несколько решений проблемы, поэтому я поделюсь своими выводами здесь.
Мое предпочтительное решение - использовать 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();
Другое решение - добраться до ArrayBuffer с помощью Blob, что объясняется примером в этом ответе
Другой вариант - использовать Blob вместе с FileReader.readAsBinaryString() в строках примера здесь. Использование readAsBinaryString() преобразует blob в строку unicode, которая затем может быть проанализирована с использованием charCodeAt()