【发布时间】:2019-10-30 08:39:26
【问题描述】:
首先:我是 JavaScript 的绝对初学者,两周前开始每天学习很多小时。我在 GNU/Linux 上运行 node.JS 服务器,我尝试了很多变体来实现目标。不幸的是,我卡住了,不知道如何继续。
我有一个带有空格和换行符的文本文件,该文件包含大约 2000 行以上的内容。我想将此文本文件读入我的 javascript 程序,以便稍后用作查找表。我不确定是否需要对它进行 JSON 字符串化以供以后使用,也许将其保留为对象/数组很简单,以后我可以将其用于查找函数。我只想从这个文本文件中提取那些包含字符“#”的行并将其用作分隔符。所有其他行都可以忽略。每一行代表一个数据集、元素、对象或任何它被正确调用的东西。最终目标是:用户要求“Apple”,他应该得到“-9.99”和“BTW”(例如)作为答案。以下是原始文本文件的示例:
Sugar# 1051# 331# BAD# 1.23# -4.56# -5.0# WWF#
N3T;
Apple# 551# 3815# F3W# 5.55# -9.99# -1.0# BTW#
BBC;
Berry# 19# 22# FF# 19.5# -12.34# 5.0# CYA#
T1K;
它应该代表 3 个元素,每个元素包含 8 对:
name: 'Sugar'
sec: 1051
ter: 331
wrd: 'BAD'
a: 1.23
b: -4.56
c: -5.0
spon: 'WWF'
name: 'Apple'
sec: 551
ter: 3815
wrd: 'F3W'
a: 5.55
b: -9.99
c: -1.0
spon: 'BTW'
name: 'Berry'
sec: 19
ter: 22
wrd: 'FF'
a: 19.5
b: -12.34
c: 5.0
spon: 'CYA'
一开始我尝试使用 fs.readFileSync 将整个文本文件作为字符串读取,但没有成功。失望的是,我尝试了另一种方法 readline 来读取我的文本文件 line-by-line 并进行过滤,因为我在网上获得了这种方法更多记忆的印象-友好,甚至可以读取非常大的文件。虽然我很确定 3000 行是个笑话 :)
这是我使用 readline 时的代码:
const fs = require('fs');
const readline = require('readline');
function readAndFilter (source, data) {
var fields;
var obj = new Object;
var arr = new Array;
const readAndFilter = readline.createInterface({
input: fs.createReadStream('test.in'),
crlfDelay: Infinity
});
readAndFilter.on('line', (line) => {
if ( line.match( /#/ ) ) {
fields = line.split( '#' ).slice();
obj.name = fields[0].trim();
obj.sec = fields[1].trim();
obj.ter = fields[2].trim();
obj.wrd = fields[3].trim();
obj.a = fields[4].trim();
obj.b = fields[5].trim();
obj.c = fields[6].trim();
obj.spon = fields[7].trim();
console.log(obj);
// let jsonView = JSON.stringify(obj);
// arr.push(obj);
}
});
readAndFilter.on('close', function() {
return arr;
});
}
readAndFilter();
这是代码输出的内容(请注意,我通过为每行输出添加时间戳来自定义控制台日志):
2019-06-16 14:40:10 { name: 'Sugar',
sec: '1051',
ter: '331',
wrd: 'BAD',
a: '1.23',
b: '-4.56',
c: '-5.0',
spon: 'WWF' }
2019-06-16 14:40:10 { name: 'Apple',
sec: '551',
ter: '3815',
wrd: 'F3W',
a: '5.55',
b: '-9.99',
c: '-1.0',
spon: 'BTW' }
2019-06-16 14:40:10 { name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' }
数据字段看起来不错,到目前为止文件已正确处理但是=>对象“obj”将仅保存最后一个数据集(名称:Berry),因为它在每一行之后被重写。我通过切割线仔细检查了
console.log(obj);
从 readAndFilter.on('line', ... 块中插入到 'close' 块中:
[...]
readAndFilter.on('line', (line) => {
if ( line.match( /#/ ) ) {
fields = line.split( '#' ).slice();
obj.name = fields[0].trim();
obj.sec = fields[1].trim();
obj.ter = fields[2].trim();
obj.wrd = fields[3].trim();
obj.a = fields[4].trim();
obj.b = fields[5].trim();
obj.c = fields[6].trim();
obj.spon = fields[7].trim();
// let jsonView = JSON.stringify(obj);
// arr.push(obj);
}
});
readAndFilter.on('close', function() {
console.log(obj);
return arr;
});
[...]
产生的输出是:
{ name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' }
它不能用作查找表,我需要数组中的所有行,以便以后可以访问它们以进行查找例程。所以我尝试使用以下代码将每个对象添加到一个数组中:
[...]
readAndFilter.on('line', (line) => {
if ( line.match( /#/ ) ) {
fields = line.split( '#' ).slice();
obj.name = fields[0].trim();
obj.sec = fields[1].trim();
obj.ter = fields[2].trim();
obj.wrd = fields[3].trim();
obj.a = fields[4].trim();
obj.b = fields[5].trim();
obj.c = fields[6].trim();
obj.spon = fields[7].trim();
// let jsonView = JSON.stringify(obj);
arr.push(obj);
}
});
readAndFilter.on('close', function() {
console.log(arr);
return arr;
});
[...]
现在我得到一个包含三个对象的数组,但只显示最后一个数据集名称:Berry 再次显示
[ { name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' },
{ name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' },
{ name: 'Berry',
sec: '19',
ter: '22',
wrd: 'FF',
a: '19.5',
b: '-12.34',
c: '5.0',
spon: 'CYA' } ]
我什至尝试过使用 concat 和许多其他变体。我到底做错了什么?我使用 readline/line-by-line 技术的方法是否完全错误,我应该改用 fs.readFileSync 吗?我也试过了,这是我使用 fs.readFileSync 的方法:
function readAndFilter () {
var fields;
var obj = new Object;
var arr = new Array;
var data = fs.readFileSync('test.in', 'utf8').replace(/\r\n/g,'\n').split('\n').filter(/./.test, /\#/)
/*
if ( data.match( /#/ ) ) {
fields = data.split( '#' ).slice();
obj.name = fields[0].trim();
obj.cqz = fields[1].trim();
obj.itu = fields[2].trim();
obj.cont = fields[3].trim();
obj.lng = fields[4].trim();
obj.lat = fields[5].trim();
obj.tz = fields[6].trim();
obj.pfx = fields[7].trim();
};
*/
console.log(typeof data + "\n" + data);
}
一旦我开始使用 .split('\n'),变量 data 就是 typeof 对象,因此我无法使用下面的 if 子句。它失败了,因为它只能在字符串上工作。也许我完全指向错误的方向而且它更简单?最终目标是:我想根据这个查找表检查像 "Apple" 这样的搜索字符串并检索适当的值(名称、sec、ter、b 或其中任何一个)。
我非常感谢任何有用的答案或提示。请耐心等待我,老实说:我真的很努力!谢谢大家。
【问题讨论】:
标签: javascript file parsing text filter