为了账号安全,请及时绑定邮箱和手机立即绑定

节点 - 从大文件中删除子字符串

节点 - 从大文件中删除子字符串

HUH函数 2022-09-29 17:12:46
我需要从文件中删除子字符串(仅出现在文件的特定已知行中)。有一些简单的解决方案是将所有文件数据读取到字符串,删除子字符串,然后将固定数据写入文件。这是我在这里找到的代码:节点 js - 从文本文件中删除字符串var data = fs.readFileSync('banlist.txt', 'utf-8');var newValue = data.replace(new RegEx("STRING_TO_REMOVE"), '');fs.writeFileSync('banlist.txt', newValue, 'utf-8');我的问题是,文件很大 - 多达十亿行日志,所以我无法将所有内容读取到内存中。
查看完整描述

4 回答

?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

为什么不是一个简单的转换流和? 可以将回调作为第二个参数,即 如果您需要替换单词而不是完全删除它们。replace()replace.replace(/bad1|bad2|bad3/g, filterWords)


const fs = require("fs")

const { pipeline, Transform } = require("stream")

const { join } = require("path")


const readFile = fs.createReadStream("./words.txt")

const writeFile = fs.createWriteStream(

  join(__dirname, "words-filtered.txt"),

  "utf8"

)


const transformFile = new Transform({

  transform(chunk, enc, next) {

    let c = chunk.toString().replace(/bad/g, "replaced")

    this.push(c)

    next()

  },

})


pipeline(readFile, transformFile, writeFile, (err) => {

  if (err) {

    console.log(err.message)

  }

})


查看完整回答
反对 回复 2022-09-29
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

https://nodejs.org/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback

不要一次读取整个文件...阅读其中的一小段缓冲。并用缓冲的片段寻找您的输入....然后增加您的缓冲区起始位置并再次执行此操作....建议让每个缓冲区开始,而不是在前一个缓冲区的末尾...但至少与所搜索数据的预期大小重叠,这样您就不会遇到一半数据位于一个缓冲区的末尾,而另一半位于另一个缓冲区的开头


查看完整回答
反对 回复 2022-09-29
?
千万里不及你

TA贡献1784条经验 获得超9个赞

您可以使用文件读取流。但是,您必须找到一种方法来检测读取数据是否仅包含部分结果。


查看完整回答
反对 回复 2022-09-29
?
慕运维8079593

TA贡献1876条经验 获得超5个赞

您可能想要做的是使用流,以便在部分读取后写入。此示例可能适合您。您需要将输出文本文件“.tmp”复制到原始文件上,以便在问题中获得相同的行为。它的工作原理是阅读一个块,然后查看你是否遇到了一条新线。然后它处理该行,写入它,然后将其从缓冲区中删除。这应该有助于解决您的记忆问题。


var fs = require("fs");

var readStream = fs.createReadStream("./BFFile.txt", { encoding: "utf-8" });

var writeStream = fs.createWriteStream("./BFFile.txt.tmp");


const STRING_TO_REMOVE = "badword";

var buffer = ""


readStream.on("data", (chunk) => {

    buffer += chunk;

    var indexOfNewLine = buffer.search("\n");

    while (indexOfNewLine !== -1) {

        var line = buffer.substring(0, indexOfNewLine + 1);

        buffer = buffer.substring(indexOfNewLine + 1, buffer.length);

        line = line.replace(new RegExp(STRING_TO_REMOVE), "");

        writeStream.write(line);

        indexOfNewLine = buffer.search("\n");

    }

})


readStream.on("end", () => {

    buffer = buffer.replace(new RegExp(STRING_TO_REMOVE), "");

    writeStream.write(buffer);

    writeStream.close();

})

此解决方案有一些假设,例如数据是UTF-8,每行可能只有1个坏词,每行都有一些文本(我没有测试),并且每行都以新行结尾而不是其他行结尾。


以下是 Node 中流的文档,我的另一个想法是使用管道和转换流,但这似乎是过度杀戮。


查看完整回答
反对 回复 2022-09-29
  • 4 回答
  • 0 关注
  • 75 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信