Подтвердить что ты не робот

Сравнение буфера в Node.js

Я новичок в Node.js. Нет сравнения с Buffer, и я должен использовать такие модули, как buffertools для этой функции.

Но я вижу довольно странное поведение, когда я сравниваю объекты Buffer в чистом Node.

> var b1 = new Buffer([170]);
> var b2 = new Buffer([171]);
> b1
<Buffer aa>
> b2
<Buffer ab>
> b1 < b2
false
> b1 > b2
false
> b1 == b2
false

и

> var b1 = new Buffer([10]);
> var b2 = new Buffer([14]);
> b1
<Buffer 0a>
> b2
<Buffer 0e>
> b1 > b2
false
> b1 < b2
true
> b1 == b2
false

Что на самом деле происходит под капотом?

4b9b3361

Ответ 1

То, как операторы сравнения работают с объектами:

var a = {}, b = {};
a === b; //false
a == b; //false
a > b; //false
a < b; //false

var c = { valueOf : function () { return 0; } };
var d = { valueOf : function () { return 1; } };
c === d; //false
c == d; //false
c > d; //false
c < d; //true

Под капотом

(вид)

Часть 1: Равенство

Это самая легкая часть. И абстрактное равенство (==, spec) и строгое равенство (===, spec) проверьте, ссылаетесь ли вы на один и тот же объект (сравнительный пример сравнения). В этом случае они, очевидно, нет, поэтому они отвечают на false (== spec step 10, === spec step 7).

Поэтому в обоих случаях:

b1 == b2 //false
b1 === b2 //false

Часть 2: сравнение ударяет

Вот интересная часть. Давайте посмотрим, как определяются реляционные операторы (< и >) . Пусть в двух случаях следуют цепочке вызовов.

x = b1 //<Buffer aa>
y = b2 //<Buffer ab>

//11.8.5 The Abstract Relational Comparison Algorithm (http://es5.github.com/#x11.8.5)
Let px be the result of calling ToPrimitive(x, hint Number).
Let py be the result of calling ToPrimitive(y, hint Number).

//9.1 ToPrimitive (http://es5.github.com/#x9.1)
InputType is Object, therefore we call the internal [[DefaultValue]] method with hint Number.

//8.12.8 [[DefaultValue]] (hint) http://es5.github.com/#x8.12.8
We try and fetch the object toString method. If it defined, call it.

И вот мы достигли кульминации: какой метод буфера toString? Ответ лежит внутри внутренней части node.js. Если вы хотите, у вас есть. То, что мы можем найти тривиально, - это эксперимент:

> b1.toString()
'�'
> b2.toString()
'�'

ладно, это не помогло. Вы заметите, что в Алгоритме абстрактного реляционного сравнения (какое большое причудливое имя для <) есть шаг для работы со строками. Он просто преобразует их в их числовое значение - коды char. Позвольте сделать это:

> b1.toString().charCodeAt(0)
65533
> b2.toString().charCodeAt(0)
65533

65533 - важное число. Это сумма двух квадратов: 142^2 + 213^2. Это также является символом замены Unicode, символом, означающим "я не знаю, что случилось". Вот почему его шестнадцатеричный эквивалент FFFD.

Очевидно, 65533 === 65533, поэтому:

b1 < b2 //is
b1.toString().charCodeAt(0) < b2.toString().charCodeAt(0) //is
65533 < 65533 //false
b1 > b2 //following same logic as above, false

И что это.

Чувак, какого черта?

Хорошо, это, должно быть, сбивало с толку, так как мои усилия по разъяснению не были продуманы. Напомним, вот что произошло:

  • Вы создали буфер. Бенджамин Груэнбаум помог мне воссоздать ваш тестовый пример, сделав:

    var b1 = new Buffer([170]), b2 = new Buffer([171]);

  • При выводе на консоль значения преобразуются в их шестнадцатеричный эквивалент (см. Проверка буфера #:

    170..toString(16) === 'aa'

    171..toString(16) === 'ab'

  • Однако внутренне они представляли недопустимые символы (поскольку это не шестнадцатеричное кодирование, опять же, вы можете вникать в реализацию nitty gritty, я не буду (о иронии)). Поэтому при преобразовании в строку они были представлены символом замены Unicode.

  • Так как они разные объекты, любой оператор равенства вернет false.

  • Однако из-за того, что работа была меньше, чем больше, чем больше, они были превращены в строки (а затем и цифры) для сравнения. В свете пункта № 3 это то же значение; поэтому они не могут быть меньше или больше друг друга, что приводит к false.

Наконец, просто чтобы улыбнуться на лице:

b1 <= b2 //true
b1 >= b2 //true

Ответ 2

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

> var b1 = new Buffer([170]);
> var b2 = new Buffer([171]);
> b1 < b2
> b1 > b2
> b1 == b2

Все, что требуется, это: "Как выполнить эквивалентность и меньше/больше, чем сравнение (a.k.a. (total) ordering) на буферах".

Ответ:

  • либо сделать это вручную, пройдя все байты обоих буферов и выполнить сравнение между соответствующими байтами, например. b1[ idx ] === b2[ idx ],

  • или используйте Buffer.compare( b1, b2 ), который дает вам один из -1, 0 или +1, в зависимости от того, будет ли первый буфер сортироваться раньше, точно так же или после второго (сортировка списка d, который содержит буферы, тогда так же просто, как d.sort( Buffer.compare )).

Обратите внимание, что я использую === в моем первом примере; мои частые комментарии на этом сайте относительно злоупотребления текстом == в JavaScript должны сделать его совершенно ясным, почему это так.