Хорошо, я не очень хорошо знаком с Node.js, но вы можете довольно близко познакомиться с некоторыми основными понятиями:
Узел сообщает:
'ascii' - только для 7-битных данных ASCII. Это кодирование быстрое и, если оно установлено, удаляет старший бит.
Обновление После перечитывания описания nod.js, я думаю, это просто означает, что оно упадет 127 и сосредоточится только на первых 7 битах, поэтому это можно упростить до:
def node_js_ascii(bytes)
bytes.map {|b| b % 128 }
.reject(&127.method(:==))
.pack('C*')
.encode(Encoding::UTF_8)
end
node_js_ascii(a)
#=> #=> "5qx9\bpR\"Ho\u0004.\u0012R>\u0005XPa:\vj|v\u0013?T\u001E~xL"
Теперь единственное отличие состоит в том, что node.js использует «\ u000b» для представления вертикальной табуляции, а ruby использует «\ v», а в ruby используются символы в верхнем регистре вместо Юникода («\ u001E» против «\ u001e») ) (вы можете справиться с этим, если захотите)
Обратите внимание Эта форма кодирования необратима из-за того, что в вашем байтовом массиве есть символы размером более 8 бит.
TL; DR (предыдущее объяснение и решение работает только до 8 бит)
Хорошо, мы знаем, что максимальное поддерживаемое десятичное число составляет 127 ("1111111".to_i(2)
), и этот узел будет отбрасывать старший бит, если установить значение [я предполагаю] 241 (8-битное число станет 113, если мы уберем старший бит)
С этим пониманием мы можем использовать:
a = [53, 127, 241, 120, 57, 136, 112, 210, 162, 200, 111, 132, 46, 146, 210, 62, 133, 88, 80, 97, 58, 139, 234, 252, 246, 19, 191, 84, 30, 126, 248, 76].map do |b|
b < 128 ? b : b - 128
end.pack('C*')
#=> "5\x7Fqx9\bpR\"Ho\x04.\x12R>\x05XPa:\vj|v\x13?T\x1E~xL"
Тогда мы можем закодировать это как UTF-8
примерно так:
a.encode(Encoding::UTF_8)
#=> "5\u007Fqx9\bpR\"Ho\u0004.\u0012R>\u0005XPa:\vj|v\u0013?T\u001E~xL"
но здесь все еще есть проблема.
Кажется, Node.js также игнорирует Delete (127), когда он конвертирует в 'ascii' (я имею в виду, что старший бит установлен, но если мы удаляем его, то он равен 63 ("?"), Что не соответствует вывод) так что мы тоже можем это исправить
a = [53, 127, 241, 120, 57, 136, 112, 210, 162, 200, 111, 132, 46, 146, 210, 62, 133, 88, 80, 97, 58, 139, 234, 252, 246, 19, 191, 84, 30, 126, 248, 76].map do |b|
b < 127 ? b : b - 128
end.pack('C*')
#=> "5\xFFqx9\bpR\"Ho\x04.\x12R>\x05XPa:\vj|v\x13?T\x1E~xL"
a.encode(Encoding::UTF_8, undef: :replace, replace: '')
#=> "5qx9\bpR\"Ho\u0004.\u0012R>\u0005XPa:\vj|v\u0013?T\u001E~xL"
Теперь, поскольку 127 - 128 = -1 (отрицательный бит со знаком) становится "\ xFF" неопределенным символом в UTF-8, поэтому мы добавляем undef: :replace
, что делать, если символ не определен, используйте replace и добавляем replace: ''
заменить ничем.