HanningWu
V2EX  ›  Node.js

如何使用 nodejs 删除本地文件前 1000 行内容?

  •  
  •   HanningWu · Apr 5, 2017 · 6358 views
    This topic created in 3329 days ago, the information mentioned may be changed or developed.

    我是一个 nodejs 新手,由于某种原因必须利用 nodejs 简单快速地写一个处理文件内容的小小 app 。我看过 nodejs documentation ,有些懵逼,所以偷个懒来 V 站问一下大家。。

    目的是想读取一个包含超多行数的文件,并对每一行内容做一些操作。如果全部读取的话内存不够,打算用一个循环去读取文件内容,每次读 1000 行,对这 1000 行数据进行一些处理之后,删除原文件前 1000 行内容,保证下一次循环不重复读取内容。

    有没有人能告诉我删除本地文件的前 1000 行在 nodejs 中该如何实现

    PS. 我试过 nodejs 的 readStream 模块去一行一行地读取。但是这个方法有一些小毛病,我不想考虑了。如果可以的话,能帮忙解决一下我问的上一个问题也可:请问如何使用 nodejs 的 readline 模块按行读取文件内容然后依次更新到 html 页面中?

    PS 的 PS. 如果能用 shell script 做是超简单的,一个 sed -i '1,1000d' filename.txt 就搞定了,然而不得不用 nodejs。。

    31 replies    2017-04-07 21:45:37 +08:00
    xcatliu
        1
    xcatliu  
       Apr 5, 2017 via iPhone
    可以用 node 开子进程执行 shell ?
    HanningWu
        2
    HanningWu  
    OP
       Apr 5, 2017
    @xcatliu 我需要在 Windows 下用 node-webkit 写 web app , Windows 下可以用 shell 子进程不?
    viko16
        3
    viko16  
       Apr 5, 2017 via Android   ❤️ 1
    xcatliu
        4
    xcatliu  
       Apr 5, 2017 via iPhone   ❤️ 1
    xcatliu
        5
    xcatliu  
       Apr 5, 2017 via iPhone
    @HanningWu 可以跨平台执行 shell 命令
    123s
        6
    123s  
       Apr 5, 2017 via Android
    我怎么感觉方向不对
    MicroPan
        7
    MicroPan  
       Apr 5, 2017   ❤️ 1
    node readline 模块 + socket.io
    readline 模块实现按行读文件
    socket.io 实现 客户端和服务器 交互
    cxbig
        8
    cxbig  
       Apr 5, 2017 via iPhone   ❤️ 1
    这种事用 shell

    linux:
    sed -i -n '1,1000d' your_file

    mac:
    sed -i '' -n '1,1000d' your_file
    HanningWu
        9
    HanningWu  
    OP
       Apr 5, 2017
    @MicroPan 没有接触过 socket.io ,不想现学了。
    HanningWu
        10
    HanningWu  
    OP
       Apr 5, 2017
    @xcatliu 这个 shelljs 看起来很棒啊,我对 shell script 很熟,如果能在 nodejs 里执行 shell script 就太好啦。我马上去试试,超感谢。
    billlee
        11
    billlee  
       Apr 5, 2017
    你这个思路不对啊。不可能从一个文件的头部删除一千行,能实现的方法都是把 1000 行后的内容写到新文件,然后用新文件覆盖掉旧文件
    imxieke
        12
    imxieke  
       Apr 5, 2017 via Android
    @cxbig 那不对啊 前 1000 行读出来了 第二个一千行不行啊。
    quickma
        13
    quickma  
       Apr 5, 2017
    哇, sheeljs ,现在这个 js 啊,真的搞事情。
    newdongyuwei
        14
    newdongyuwei  
       Apr 5, 2017
    如果“目的是想读取一个包含超多行数的文件,并对每一行内容做一些操作”,那无论你文件多大, nodejs 都可以轻松处理啊! nodejs 可以流式读取文件, see https://nodejs.org/dist/latest-v7.x/docs/api/fs.html#fs_fs_createreadstream_path_options 再参考这个 https://nodejs.org/dist/latest-v7.x/docs/api/stream.html#stream_class_stream_readable 监听 data 事件就可以处理目标数据了。
    victory
        15
    victory  
       Apr 5, 2017
    @cxbig 牛 PowerShell 这么做
    cxbig
        16
    cxbig  
       Apr 5, 2017
    @victory PowerShell 不会,我只会 Mac 和 Linux 的方法
    cxbig
        17
    cxbig  
       Apr 5, 2017
    @imxieke 我上面这个命令带上 -i 就直接删除该文件最前面的 1 千行

    如果你要读指定行的话,可以用参数 p ,这命令直接输出到 stdout ,怎么接收看你了
    sed -n '1001,2000p' your_file
    klesh
        18
    klesh  
       Apr 5, 2017 via Android
    windows 下是没有原生 shell 的,参考 14 楼的方法现实些, readline 包也是可以的。
    willakira
        19
    willakira  
       Apr 6, 2017
    删掉原始文件出问题的时候真是会欲哭无泪,比较推荐 stream 读取然后写到新文件
    HanningWu
        20
    HanningWu  
    OP
       Apr 6, 2017
    @newdongyuwei 我用了 readline 模块,用的是 html 页面中一个按钮(button)的 onclick 事件去触发这个基于 readline 模块的文件读取函数。但是我对每一行的处理包括一行修改 html 文件内容的命令。比如 html 页面中有个 <p id="status"><p>。我希望每读取一行之后就利用 document.getElementById("status").innerHTML = line 覆盖 id="status" 的段落原有内容为该行内容。但点击按钮之后,触发文件读取函数这时候页面卡住了,然后等函数运行结束,页面才恢复正常,于是我只看到了最后一行的显示内容。运气过程中“上一行内容被新的一行的内容覆盖”这个显示效果我就看不到了。
    HanningWu
        21
    HanningWu  
    OP
       Apr 6, 2017
    @newdongyuwei 最终,是需要实现这样一个效果,示例代码: https://jsfiddle.net/09kuyn7v/ 。但不是像这个示例中那样,数据从数组中来,我需要的是从文件每一行读取出来,然后以同样的效果通过点击按钮显示到 html 的一个段落中去。
    param
        22
    param  
       Apr 6, 2017 via Android
    @cxbig 为什么 Mac 多个双引号,是干嘛的
    HanningWu
        23
    HanningWu  
    OP
       Apr 6, 2017 via iPhone
    @param 那不是双引号,是两个单引号,用来备份 -i 直接修改的文件。比如你利用 sed -i '.bak' '1,100d' filename.txt 命令去删除 filename.txt 的前 100 行,中端会先备份文件为 filename.txt.bak
    HanningWu
        24
    HanningWu  
    OP
       Apr 6, 2017 via iPhone
    @param 单引号内放空,看起来像双引号时就不备份
    HanningWu
        25
    HanningWu  
    OP
       Apr 6, 2017
    @newdongyuwei 那看是怎么“轻松处理”,我的确可以用 readStrem 来读文件,但是我遇到的问题是读取文件之后无法**动态地依次**显示到 html 页面中去!
    cxbig
        26
    cxbig  
       Apr 6, 2017
    @param 那是两个单引号,这个参数是用来定义重命名后缀的, 23 楼已说明
    当你想直接写回原文件的时候, Linux 只写 -i 就好, Mac 下必须要带空字符串当参数,不然报错
    IJustmaogepao
        27
    IJustmaogepao  
       Apr 6, 2017
    我的想法是可以用 readFile 读出来,再用 split('\n')切割成数组,然后去掉前 1000 个元素。。
    123s
        28
    123s  
       Apr 6, 2017 via Android
    @IJustmaogepao 发文件就坑了
    123s
        29
    123s  
       Apr 6, 2017 via Android
    大文件
    WXYOO1
        30
    WXYOO1  
       Apr 7, 2017
    推荐使用 line-reader 这个包 直接读行,前 1000 行不处理,后面开始写入新文件
    ```
    var lineReader = require('line-reader');

    lineReader.eachLine('file.txt', function(line, last) {
    console.log(line);
    });
    ```
    HanningWu
        31
    HanningWu  
    OP
       Apr 7, 2017
    @WXYOO1 这个包读取文件是同步的还是异步的?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4603 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 164ms · UTC 06:25 · PVG 14:25 · LAX 23:25 · JFK 02:25
    ♥ Do have faith in what you're doing.