繁体   English   中英

如何使用大文件,NodeJS流和管道

[英]how to work with large files, NodeJS streams, and pipes

我对NodeJS流有点新,我越了解它,我越相信它不是一个特别简单和稳定的东西。 我正在尝试使用csv / csv-parse (显然是最流行的带有NodeJS的CSV模块)使用管道API读取大文件,这涉及到同一作者使用流转换

我在这里遇到的部分内容实际上是可重复的而不实际使用解析器,因此我对这些部分进行了评论以使示例更简单(对于那些喜欢JavaScript而不是CoffeeScript的人, 还有一个JS版本 ):

#-------------------------------------------------------------------------------
fs                        = require 'fs'
transform_stream          = require 'stream-transform'
log                       = console.log
as_transformer            = ( method ) -> transform_stream method, parallel: 11
# _new_csv_parser           = require 'csv-parse'
# new_csv_parser            = -> _new_csv_parser delimiter: ','

#-------------------------------------------------------------------------------
$count = ( input_stream, title ) ->
  count = 0
  #.............................................................................
  input_stream.on 'end', ->
    log ( title ? 'Count' ) + ':', count
  #.............................................................................
  return as_transformer ( record, handler ) =>
    count += 1
    handler null, record

#-------------------------------------------------------------------------------
read_trips = ( route, handler ) ->
  # parser      = new_csv_parser()
  input       = fs.createReadStream route
  #.............................................................................
  input.on 'end', ->
    log 'ok: trips'
    return handler null
  input.setMaxListeners 100 # <<<<<<
  #.............................................................................
  # input.pipe parser
  input.pipe $count input, 'trips A'
    .pipe $count    input, 'trips B'
    .pipe $count    input, 'trips C'
    .pipe $count    input, 'trips D'
    # ... and so on ...
    .pipe $count    input, 'trips Z'
  #.............................................................................
  return null

route = '/Volumes/Storage/cnd/node_modules/timetable-data/germany-berlin-2014/trips.txt'
read_trips route, ( error ) ->
  throw error if error?
  log 'ok'

输入文件包含204865行GTFS数据; 我不是在这里解析它,只是原始读它,所以我猜我用上面的代码计算的是数据块。

我正在从一个柜台到一个柜台管道输送,并且预计会像第一个柜台那样经常到达最后一个柜台; 然而,这就是我得到的:

trips A: 157
trips B: 157
trips C: 157
...
trips U: 157
trips V: 144
trips W: 112
trips X: 80
trips Y: 48
trips Z: 16

在早期的设置中,我实际上解析了数据,我得到了这个:

trips A: 204865
trips B: 204865
trips C: 204865
...
trips T: 204865
trips U: 180224
trips V: 147456
trips W: 114688
trips X: 81920
trips Y: 49152
trips Z: 16384

所以看起来这条小溪一路上都是干涸的。

我怀疑输入流的end事件在尝试确定是否所有处理都已完成时听不到可靠的信号 - 毕竟,假设处理只能在流完全完成的一段时间完成处理是合乎逻辑的。消耗。

所以我寻找另一个事件来监听(没有找到一个)并延迟调用回调(使用setTimeoutprocess.nextTicksetImmediate ),但无济于事。

如果有人能够指出,这将是伟大的

  • (1) setTimeoutprocess.nextTicksetImmediate之间的关键区别是在这个上下文中,和
  • (2)如何可靠地确定最后一个字节是否已由管道的最后一个成员处理。

更新我现在认为问题在于流变换有问题,有人报告了一个非常相似的问题与几乎相同的数字(他有234841记录,最终得到16390,我有204865,最终得到16384)。 不是证据,而是过于接近偶然。

我抛弃了流转换并改为使用event-stream.map ; 测试然后运行正常。

几天后,我想我可以说流变换有大文件的问题。

我已经切换到事件流 ,这是IMHO一个更好的解决方案,因为它是完全通用的(即它通常是关于流,而不是特别是关于CSV数据的流)。 我已经在我的早期pipdreams模块的文档中概述了有关NodeJS中的流库的一些想法,该模块提供了许多常用的流操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM