Skip to content

Instantly share code, notes, and snippets.

@Scarysize
Created November 2, 2017 21:23
Show Gist options
  • Save Scarysize/03ff6c35a6c4062900a9c22869b42db2 to your computer and use it in GitHub Desktop.
Save Scarysize/03ff6c35a6c4062900a9c22869b42db2 to your computer and use it in GitHub Desktop.
Like Node.js 'readline' for HTML5 File API.
const DEFAULT_CHUNK_SIZE = 1024;
class LineReader {
constructor(options) {
this.chunkSize = options.chunkSize || DEFAULT_CHUNK_SIZE;
this.onLine = options.onLine;
this.onEnd = options.onEnd;
this.reader = new FileReader();
this.canRead = true;
this.chunk = '';
this.lines = null;
this.reader.addEventListener('load', this.handleReaderLoad.bind(this));
}
handleReaderLoad() {
this.chunk += this.reader.result;
const hasNewLine = /\n|\r/.test(this.chunk);
if (hasNewLine) {
this.lines = this.chunk.match(/[^\r\n]+/g);
if (this.hasMoreData()) {
const lineFinished = this.chunk[this.chunk.length - 1] === '\n';
this.chunk = lineFinished ? '' : this.lines.pop();
}
this.step();
return;
}
if (this.hasMoreData()) {
this.read();
return;
}
if (this.chunk.length > 0) {
this.onLine(this.chunk);
this.onEnd();
return;
}
this.onEnd();
}
hasMoreData() {
return this.readPos < this.fileLength;
}
step() {
if (this.lines.length === 0) {
if (this.hasMoreData()) {
this.read();
return;
}
this.onEnd();
return;
}
if (this.canRead) {
this.onLine(this.lines.shift());
this.step();
return;
}
this.onEnd();
}
read(file) {
if (file) {
this.file = file;
this.fileLength = file.size;
this.readPos = 0;
this.chunk = '';
this.lines = [];
}
this.readPos += this.chunkSize;
this.reader.readAsText(
this.file.slice(this.readPos, this.readPos + this.chunkSize)
);
}
abort() {
this.canRead = false;
}
}
window.LineReader = LineReader;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment