d11 theme
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

140 lines
4.5 KiB

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.streamLineByLineAsync = exports.streamFileLineByLineAsync = exports.lineReaderAsync = exports.readFile = void 0;
// cSpell:ignore curr
// cSpell:words zlib iconv
const fs = require("fs");
const iconv = require("iconv-lite");
const zlib = require("zlib");
const readline = require("readline");
const defaultEncoding = 'utf8';
function readFile(filename, encoding = defaultEncoding) {
return new Promise((resolve, reject) => {
const data = [];
const stream = prepareFileStream(filename, encoding, reject);
let resolved = false;
function complete() {
resolve(data.join(''));
resolved = resolved || (resolve(data.join('')), true);
}
stream.on('error', reject);
stream.on('data', (d) => data.push(d));
stream.on('close', complete);
stream.on('end', complete);
});
}
exports.readFile = readFile;
/**
* Reads a file line by line. The last value emitted by the Observable is always an empty string.
* @param filename
* @param encoding defaults to 'utf8'
*/
function lineReaderAsync(filename, encoding = defaultEncoding) {
return streamFileLineByLineAsync(filename, encoding);
}
exports.lineReaderAsync = lineReaderAsync;
function prepareFileStream(filename, encoding, fnError) {
const pipes = [];
if (filename.match(/\.gz$/i)) {
pipes.push(zlib.createGunzip());
}
pipes.push(iconv.decodeStream(encoding));
const fileStream = fs.createReadStream(filename);
fileStream.on('error', fnError);
const stream = pipes.reduce((s, p) => s.pipe(p).on('error', fnError), fileStream);
return stream;
}
/**
* Emit a file line by line
* @param filename full path to the file to read.
* @param encoding defaults to 'utf8'
*/
function streamFileLineByLineAsync(filename, encoding = defaultEncoding) {
const fnError = (e) => {
iter.throw && iter.throw(e);
};
const stream = prepareFileStream(filename, encoding, fnError);
const iter = streamLineByLineAsync(stream);
return iter;
}
exports.streamFileLineByLineAsync = streamFileLineByLineAsync;
/**
* Emit a file line by line
* @param filename full path to the file to read.
* @param encoding defaults to 'utf8'
*/
function streamLineByLineAsync(stream, encoding = defaultEncoding) {
let data = '.';
let done = false;
let error;
const buffer = [];
const pending = [];
const fnError = (e) => {
error = e;
};
const fnComplete = () => {
// readline will consume the last newline without emitting an empty last line.
// If the last data read contains a new line, then emit an empty string.
if (data.match(/(?:(?:\r?\n)|(?:\r))$/)) {
buffer.push('');
}
processBuffer();
done = true;
};
// We want to capture the last line.
stream.on('data', (d) => (data = dataToString(d, encoding)));
stream.on('error', fnError);
const rl = readline.createInterface({
input: stream,
terminal: false,
});
rl.on('close', fnComplete);
rl.on('line', (text) => {
buffer.push(text);
processBuffer();
});
function registerPromise(resolve, reject) {
pending.push({ resolve, reject });
processBuffer();
}
function processBuffer() {
if (error && pending.length && !buffer.length) {
const p = pending.shift();
p === null || p === void 0 ? void 0 : p.reject(error);
return;
}
while (pending.length && buffer.length) {
const p = pending.shift();
const b = buffer.shift();
if (b !== undefined && p) {
p.resolve({ done: false, value: b });
}
}
if (!done) {
pending.length ? rl.resume() : rl.pause();
}
if (done && pending.length && !buffer.length) {
const p = pending.shift();
p === null || p === void 0 ? void 0 : p.resolve({ done, value: undefined });
}
}
const iter = {
[Symbol.asyncIterator]: () => iter,
next() {
return new Promise(registerPromise);
},
throw(e) {
fnError(e);
return new Promise(registerPromise);
},
};
return iter;
}
exports.streamLineByLineAsync = streamLineByLineAsync;
function dataToString(data, encoding = 'utf8') {
if (typeof data === 'string') {
return data;
}
return data.toString(encoding);
}
//# sourceMappingURL=fileReader.js.map