Браузер читает целое число из двоичной строки - PullRequest
1 голос
/ 27 мая 2020

У меня есть, например, вот эта строка

'x���'

, которую вы, возможно, не увидите, в зависимости от используемого вами устройства. Это число 2024000250, закодированное как 32-битное целое число со знаком с прямым порядком байтов, которое я сгенерировал с помощью Node

let buffer = new Buffer(4);
b.writeInt32BE(2024000250).toString();

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

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Я могу ошибаться здесь. Но насколько я помню, символы юникода могут быть между 2-4 байтами. Когда вы передаете свои двоичные данные в виде текста на клиентскую сторону, вы рискуете испортить эту информацию, потому что клиент будет интерпретировать их как Unicode.

Если бы я преобразовал этот текст в blob на стороне клиента:

var b = new Blob(['x���'],{type:"application/octet-stream"});
b.size; //10 

Как видите, я получаю 10 байт, что неверно, должно было быть 4.

Вы можете передавать данные напрямую в виде двоичной строки, поскольку вы используете Node, на на стороне сервера:

function createBuffer(v){
    var b = new ArrayBuffer(4),
        vw = new DataView(b);
    vw.setInt32(0,v);
    return b;
}

Это создаст ваш буфер, теперь вы не можете просто отправить его как есть клиенту, либо представить его как json, либо напрямую как двоичную строку. Чтобы представить его как двоичный, вам не нужна вышеуказанная функция, вы могли бы сделать:

("0".repeat(32) + (2024000250).toString(2)).slice(-32); //"01111000101000111100101011111010"

Если хотите json, вы можете сделать:

function convertBuffToBinaryStr(buff){
    var res = [],
        l = buff.byteLength,
        v = new DataView(buff);
    for (var i = 0; i < l; ++i){
        res.push(v.getUint8(i));
    }
    return JSON.stringify(res);
}

Теперь попробуйте видя, что это выводит:

convertBuffToBinaryStr(createBuffer(2024000250)); //"[120,163,202,250]"

На стороне клиента вы должны интерпретировать это:

function interpret(json){
    json = JSON.parse(json);
    return parseInt(json.map((d)=>("0".repeat(8) + d.toString(2)).slice(-8)).join(""),2);
}

Теперь попробуйте:

interpret("[120,163,202,250]"); //2024000250

Примечание: для ваша функция интерпретации, вы должны использовать dataView для setUint8 и использовать getInt32 в конце, поскольку вы используете целые числа со знаком, выше не будет работать для всех случаев.

0 голосов
/ 30 мая 2020

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

Это не совсем то, с чего я начал, но я просто отправлю это для некоторых других заблудших душ.

Это Стоит отметить, что ответ Ибрахима содержит большую часть необходимой информации, но пытается решить проблему XY , которой оказался мой вопрос.

Я просто отправляю свои двоичные данные как двоичные

let buffer = new Buffer(4);
buffer.writeInt32BE(2024000250);

// websocket connection
connection.send(buffer);

Затем в браузере

// message listener
let reader = new FileReader();
reader.addEventListener('loadend', () => {
  let view = new DataView(reader.result);

  // there goes the precious data
  console.log(view.getInt32());
});
reader.readAsArrayBuffer(message.data);

Честно говоря, это вызывает у меня рвотный рефлекс. Почему я использую программу чтения файлов, чтобы получить данные из двоичного сообщения? Есть большая вероятность, что существует лучший способ сделать это, если да, пожалуйста, добавьте к этому ответу.

Другие методы, которые я нашел, - это API выборки, который не лучше, чем программа чтения файлов с точки зрения взлома и Blob.prototype.arrayBuffer, который еще не полностью поддерживается.

...