Sunday, July 20, 2014

Reading Files from STDIN in Dart


I need to read from STDIN on the command-line. Not just a single line, which seems to well understood in Dart, but from an entire file redirected into a Dart script.

My benchmarking work has a life of its own now with several (sometimes competing) requirements. One of those requirements is that the code that actually produces the benchmark raw data cannot use dart:io for writing to files (because it also compiled to JavaScript which does not support dart:io). Given that, my benchmark results are sent to STDOUT and redirected to artifact files:
    ./tool/benchmark.dart --loop-size=$X \
        | tee -a $RESULTS_FILE
Or, the JavaScript version:
    node ./tool/benchmark.dart.js --loop-size=$X \
        | tee -a $RESULTS_FILE
That works great, mostly because Dart's print() sends its data to STDOUT regardless of whether or not it is being run the Dart VM or in Node.js after being put through dart2js.

What I need now is a quick way to summarize the raw results that can work with either the Dart or JavaScript results. Up until now, I have hard-coded the current filename inside the summary script which is then run as:
./tool/summarize_results.dart > $SUMMARY_FILE
The problem with that is twofold: I should not hard-code a filename like that and the artifact filenames should all be managed in the same location.

I could send the filename into the ./tool/summarize_results.dart as an argument. That would, in fact, require a minimal amount of change. But I have a slight preference to be consistent with shell file redirection—if STDOUT output is being redirected to a file, then my preference is to (at least support) reading from a file and piping into the script via STDIN.

Fortunately, this is fairly easy with dart:io's stdin top-level getter. It actually turns out to be very similar to the single-line-of-keyboard-input solutions that are already out there:
_readTotals() {
  var lines = [];

  var line;
  while ((line = stdin.readLineSync()) != null) {
    var fields = line.split('\t');
    lines.add({
      'name': fields[0],
      'score': fields[1],
      'loopSize': fields[2],
      'averageScore': fields[3]
    });
  }

  return lines;
}
The only real “trick” here is the null check at the end of the STDIN input stream. Pleasantly, that was easy to figure out since is it similar to many other languages implementation of STDIN processing.



Day #128

No comments:

Post a Comment