Javascript 从基于文件的流中解析头会产生意外的结果

Javascript 从基于文件的流中解析头会产生意外的结果,javascript,arrays,node.js,node.js-stream,Javascript,Arrays,Node.js,Node.js Stream,实际上,我正在编写一个小的解析器来使用node streams io.js处理一些日志文件,但我认为这并不重要 我将按照中的示例解析标题。我可以成功地拆分缓冲区并抓取头,但只要调用stream.unshift,它似乎就会连接头字符串和剩余字符串 在为这个问题设置一些示例代码时,我发现在查看基于文件的流时会发生这种行为。每当我使用基于字符串的流时,即使文件的文本与字符串完全相同,问题也不会发生 以下是“我的文本编辑器”(my text editor)中打开空白字符时文件的外观,以供比较: 我需要

实际上,我正在编写一个小的解析器来使用node streams io.js处理一些日志文件,但我认为这并不重要

我将按照中的示例解析标题。我可以成功地拆分缓冲区并抓取头,但只要调用stream.unshift,它似乎就会连接头字符串和剩余字符串

在为这个问题设置一些示例代码时,我发现在查看基于文件的流时会发生这种行为。每当我使用基于字符串的流时,即使文件的文本与字符串完全相同,问题也不会发生

以下是“我的文本编辑器”(my text editor)中打开空白字符时文件的外观,以供比较:

我需要一些帮助来理解为什么会发生这种情况

var StringDecoder=需要'string_decoder'。StringDecoder; //在伪\u流中设置基于字符串的流 变量流=要求“流”; var fake_file='文件类型:SOME-HEADER-DATE\r\n' +'标题\u结束\r\n' +“1234 |记录的数据| 1 | 2 | 3 | 4 | 5 |一些其他记录的数据\x1E\r\n” +“1235 |记录的数据| 1 | 2 | 3 | 4 | 5 |一些其他记录的数据\x1E\r\n” +“1236 |记录的数据| 1 | 2 | 3 | 4 | 5 |一些其他记录的数据\x1E\r\n” var fake_stream=新的stream.Readable; fake_stream.pushnew Bufferfake_文件“utf8”; 假_stream.pushnull; //在文件流中设置基于文件的流 //文件minimal_test_log.glf具有如上所示的文本,其中的控制字符未被替换 var fs=要求“fs”; var file='C:\\Some\\Path\\To\\minimal\u test\u log.glf'; var file_stream=fs.createReadStreamfile; //为什么我在这里得到不同的结果? parseHeaderfile_流,函数错误,头,流{ console.log'processing file_stream:'+header.length; //结果:处理文件\u流:184 //这将导致两个部分连接在一起,而没有标题_END/r/n }; parseHeaderfake_流,函数错误,头,流{ console.log'processing fake_stream:'+header.length; //结果:处理假_流:28 //这些结果正是我所期望的,一切在你结束之前 }; //略加修改的示例位于https://iojs.org/api/stream.htmlstream_readable_unshift_chunk 函数parseHeaderstream,回调{ 在'error'上,回调; 在“可读”上,在“可读”上; var解码器=新的StringDecoder'utf8'; var头=; 函数onReadable{ 变量块,buf,剩余; var header\u boundary=/header\u END\r\n/g; 而null!==chunk=stream.read{ var str=decoder.writechunk; 如果str.matchheader\u边界{ var split=str.splitheader\u边界; 页眉+=拆分.shift; 剩余=split.join; buf=剩余的新缓冲区“utf8”; 如果buf.length{ stream.unshiftbuf; } //从这一点开始,标题长度不同 stream.removeListener'error',回调; stream.removeListener'readable',onReadable; callbacknull、标头、流; }否则{ 头+=str; } } } } 因此,向onReadable添加计数器表明它被调用了两次。由于标头声明的范围比onReadable更广,所以它保留了标头中存储的内容。第二次通过onReadable函数时,header_boundary将不匹配,if语句与else子句短路,将日志的其余部分附加到header

我重读了这本书,了解到了这一点

一旦内部缓冲区耗尽,当更多数据可用时,将再次触发可读事件

我相信当我调用stream.unshiftbuf;时就会发生这种情况;。每当我使用unshift将数据添加回流时,就会触发第二个可读事件

正在为基于文件和基于字符串的流激发第二个可读事件。然而,他们之间的时机似乎有点不同。在基于字符串的流中,在触发第二个可读事件时,回调已经执行。在基于文件的流中,只有在引发可读事件并将额外数据附加到头变量之后,才会执行回调

我还没有完全弄清楚为什么不同的流之间的时间是不同的,但它给了我足够的时间继续我的工作