V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
HanningWu
V2EX  ›  Node.js

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

  •  
  •   HanningWu · 2017-04-05 18:41:21 +08:00 · 5584 次点击
    这是一个创建于 2779 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我是一个 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 条回复    2017-04-07 21:45:37 +08:00
    xcatliu
        1
    xcatliu  
       2017-04-05 18:48:02 +08:00 via iPhone
    可以用 node 开子进程执行 shell ?
    HanningWu
        2
    HanningWu  
    OP
       2017-04-05 18:55:40 +08:00
    @xcatliu 我需要在 Windows 下用 node-webkit 写 web app , Windows 下可以用 shell 子进程不?
    viko16
        3
    viko16  
       2017-04-05 19:00:35 +08:00 via Android   ❤️ 1
    xcatliu
        4
    xcatliu  
       2017-04-05 19:03:55 +08:00 via iPhone   ❤️ 1
    xcatliu
        5
    xcatliu  
       2017-04-05 19:04:17 +08:00 via iPhone
    @HanningWu 可以跨平台执行 shell 命令
    123s
        6
    123s  
       2017-04-05 19:11:57 +08:00 via Android
    我怎么感觉方向不对
    MicroPan
        7
    MicroPan  
       2017-04-05 19:19:51 +08:00   ❤️ 1
    node readline 模块 + socket.io
    readline 模块实现按行读文件
    socket.io 实现 客户端和服务器 交互
    cxbig
        8
    cxbig  
       2017-04-05 19:22:36 +08:00 via iPhone   ❤️ 1
    这种事用 shell

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

    mac:
    sed -i '' -n '1,1000d' your_file
    HanningWu
        9
    HanningWu  
    OP
       2017-04-05 19:23:09 +08:00
    @MicroPan 没有接触过 socket.io ,不想现学了。
    HanningWu
        10
    HanningWu  
    OP
       2017-04-05 19:24:53 +08:00
    @xcatliu 这个 shelljs 看起来很棒啊,我对 shell script 很熟,如果能在 nodejs 里执行 shell script 就太好啦。我马上去试试,超感谢。
    billlee
        11
    billlee  
       2017-04-05 20:15:53 +08:00
    你这个思路不对啊。不可能从一个文件的头部删除一千行,能实现的方法都是把 1000 行后的内容写到新文件,然后用新文件覆盖掉旧文件
    imxieke
        12
    imxieke  
       2017-04-05 20:42:23 +08:00 via Android
    @cxbig 那不对啊 前 1000 行读出来了 第二个一千行不行啊。
    x7395759
        13
    x7395759  
       2017-04-05 20:45:51 +08:00
    哇, sheeljs ,现在这个 js 啊,真的搞事情。
    newdongyuwei
        14
    newdongyuwei  
       2017-04-05 21:18:16 +08:00
    如果“目的是想读取一个包含超多行数的文件,并对每一行内容做一些操作”,那无论你文件多大, 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  
       2017-04-05 21:24:47 +08:00
    @cxbig 牛 PowerShell 这么做
    cxbig
        16
    cxbig  
       2017-04-05 21:52:10 +08:00
    @victory PowerShell 不会,我只会 Mac 和 Linux 的方法
    cxbig
        17
    cxbig  
       2017-04-05 21:57:16 +08:00
    @imxieke 我上面这个命令带上 -i 就直接删除该文件最前面的 1 千行

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

    lineReader.eachLine('file.txt', function(line, last) {
    console.log(line);
    });
    ```
    HanningWu
        31
    HanningWu  
    OP
       2017-04-07 21:45:37 +08:00
    @WXYOO1 这个包读取文件是同步的还是异步的?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5086 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 03:55 · PVG 11:55 · LAX 19:55 · JFK 22:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.