我有一种情况,我需要逐行处理流中的一些数据。问题是数据的编码事先不知道;它可能是UTF-8
或任何传统的单字节编码(例如Latin1
,ISO-8859-5
等)。它将不 UTF16
或像EBCDIC
这样的外来物,所以我可以合理地期望\n
是明确的,所以理论上我可以把它分成几行。在某些时候,当我遇到一个空行时,我需要将其余的流馈送到其他地方(不将它分成行,但仍然没有任何重新编码);从HTTP风格的标题开始,然后是不透明的主体。
这是我得到的:
function processStream(stream) {
var buffer = '';
function splitLines(data) {
buffer += data;
var lf = buffer.indexOf('\n');
while (lf >= 0) {
var line = buffer.substr(0, lf - 1);
buffer = buffer.substr(lf + 1);
this.emit('line', line);
lf = buffer.indexOf('\n');
}
}
function processHeader(line) {
if (line.length) {
// do something with the line
} else {
// end of headers, stop splitting lines and start processing the body
this
.removeListener('data', splitLines)
.removeAllListeners('line')
.on('data', processBody);
if (buffer.length) {
// process leftover buffer as part of the body
processBody(buffer);
buffer = '';
}
}
}
function processBody(data) {
// do something with the body chunks
}
stream.setEncoding('binary');
stream
.on('data', splitLines)
.on('line', processHeader);
}
它完成了这项工作,但问题是binary
编码已被弃用,将来可能会消失,让我没有这个选项。如果(很可能,何时)它与编码不匹配,所有其他Buffer
编码将破坏数据或完全解码它。使用Uint8Array
代替对数据进行缓慢且不方便的Javascript循环只是为了找到换行符。
有关如何动态地将流拆分为行的任何建议,同时保持编码无关而不使用使用binary
编码?
答案 0 :(得分:5)
免责声明:我不是Javascript开发人员。
在某些时候,当我遇到一个空行时,我需要将其余的流提供给其他地方(不将其分成行,但仍然没有任何重新编码)
右。在这种情况下,听起来你真的根本不想将数据视为文本。像处理任何二进制数据一样对待它,并将其拆分为字节0x0A。 (请注意,如果它是从Windows开始的,那么可能也希望删除任何尾随的0x0D值。)
我确实知道它的文字,但是如果没有任何编码信息,对数据进行任何解释都是危险的。
所以你应该保留两个州:
当您收到数据时,您在逻辑上想要创建一个新数组,当前缓冲区在新数据之前。 (为了提高效率,您可能不希望实际创建这样的数组,但我会这样做,直到您开始工作。)查找任何0x0A字节,并相应地拆分数组(创建一个新的字节数组为现有数组的“切片”,并将切片添加到列表中)。新的“当前缓冲区”将是您在最终0x0A之后留下的任何数据。
如果你连续看到两个0x0A值,那么你将进入第二种只复制数据的模式。
这都假设Javascript / Node组合允许您将二进制数据操作为二进制数据,但如果没有,我会感到震惊。重要的一点是不在任何时候将其解释为文本。