9

I'm trying to read a text file asynchronously and line-by-line under Node.js. I have the following CoffeeScript code:

readline  = require 'readline'
fs        = require 'fs'

#--------------------------------------------------------------------
lines_of = ( route, handler ) ->
  #..................................................................
  stream = readline.createInterface
    input:    fs.createReadStream route
    output:   process.stdout
    terminal: false
  #..................................................................
  stream.on 'close', ->
    handler null, null
  #..................................................................
  stream.on 'error', ( error ) ->
    handler error
  #..................................................................
  stream.on 'line', ( line ) ->
    handler null, line

It works fine except the very last line of files is never reported unless it is terminated by a newline. is there any way to remedy this (except, of course, adding the newline manually)?

Yves M.
  • 29,855
  • 23
  • 108
  • 144
flow
  • 3,624
  • 36
  • 48
  • simple solution, if files aren't too large: maybe just use `readFile` and split on `\n`? – WiredPrairie Aug 26 '13 at 19:28
  • Yeah, this is definitely not what readline is for. You would use readline if you were making a shell or a REPL, not for reading a file. You want the `fs` module: http://nodejs.org/api/fs.html – Aaron Dufour Aug 26 '13 at 19:53
  • your comment strikes me as being both correct and technically disputable—after all, 'hacking' is all about appropriating tools where appropriate. more to the point: the streams abstraction tells you to view not so much files, http requests, and stdin keyboard events, but 'streams of data'. that said, if readline doesn't have a way to communicate 'dangling bits' (before a newline, but after the input stream has finished), then it's its *API*, not its *intended purpose* that makes this library a bad fit for the task at hand. – flow Aug 27 '13 at 11:34
  • @WiredPrairie: yes, this is a good solution for small files, but i need to read files with tens of thousands of lines. both processing logic and processing speed profit from doing this the asynchronous way. – flow Aug 27 '13 at 11:37
  • So, the answer is, "no", there is no way to remedy this using the API you had selected. You'll need to find another module or write the few lines of code necessary to do line-by-line processing. – WiredPrairie Aug 27 '13 at 12:01
  • I just tried your example on small and huge files and the code runs as expected. `readline` sends the last line via the `'line'` handler before calling the `'close'` handler. However, I guess your problem is that the stream never closes and readline will not know when the last line is finished. Or maybe in your `handler` has some broken logic, e.g., overwriting the last line with `null` after `readline` calls `handler(null,null)` to indicate the closing of the stream? To avoid such errors, you should use different handlers for different events. – Juve Jun 05 '15 at 09:54

2 Answers2

1

You should use the fs module for this, and split the file contents on \n chars to determine where lines end.

erikvold
  • 15,988
  • 11
  • 54
  • 98
0

Seems to be fixed since 0.12.2 https://github.com/nodejs/node-v0.x-archive/issues/7238

AndSmith
  • 741
  • 1
  • 6
  • 12