使用Node.js和CoffeeScript遍历文件中的行

aar*_*acy 5 node.js coffeescript

我正在使用带有CoffeScript的Node.js和以下函数迭代文件中的行:

each_line_in = (stream, func) ->
    fs.stat stream.path, (err, stats) ->
        previous = []
        stream.on 'data', (d) ->
            start = cur = 0
            for c in d
                cur++
                if c == 10
                    previous.push(d.slice(start, cur))
                    func previous.join('')
                    previous = []
                    start = cur
            previous.push(d.slice(start, cur)) if start != cur
Run Code Online (Sandbox Code Playgroud)

如果没有将整个文件读入内存,有没有更好的方法呢? 并且通过"更好",我的意思是更简洁,内置到Node.js,更快,或更正确.如果我正在编写Python,我会做这样的事情:

def each_line_in(file_obj, func):
    [ func(l) for l in file_obj ]
Run Code Online (Sandbox Code Playgroud)

我看到这个问题 使用了Peteris Krumin的"懒惰"模块,但我想完成这个,而不添加外部依赖.

Tre*_*ham 6

这是一种相当有效的方法:

eachLineIn = (filePath, func) ->

  blockSize = 4096
  buffer = new Buffer(blockSize)
  fd = fs.openSync filePath, 'r'
  lastLine = ''

  callback = (err, bytesRead) ->
    throw err if err
    if bytesRead is blockSize
      fs.read fd, buffer, 0, blockSize, null, callback

    lines = buffer.toString('utf8', 0, bytesRead).split '\n'
    lines[0] = lastLine + lines[0]
    [completeLines..., lastLine] = lines
    func(line) for line in completeLines
    return

  fs.read fd, buffer, 0, blockSize, 0, callback
  return
Run Code Online (Sandbox Code Playgroud)

您应该在硬件和操作系统上对此进行基准测试,以找到blockSize大文件的最佳值.

请注意,这假定文件行\n仅被除以.如果您不确定文件的用途,则应使用正则表达式split,例如:

.split(/(\\r\\n)|\\r|\\n/)
Run Code Online (Sandbox Code Playgroud)