Node.js如何删除文件中的第一行

9nvpjoqh  于 2023-01-08  发布在  Node.js
关注(0)|答案(4)|浏览(195)

我正在做一个简单的Node.js应用程序,我需要删除文件中的第一行。请是任何方式如何做到这一点?我认为这将是可能的与fs.write,但如何?

pbwdgjma

pbwdgjma1#

这是从文件中删除第一行的流版本。
由于它使用流,意味着你不需要加载整个文件在内存中,所以它是更有效和快速的方式,以及可以工作在非常大的文件,而无需填补内存在您的硬件上。

var Transform = require('stream').Transform;
var util = require('util');

// Transform sctreamer to remove first line
function RemoveFirstLine(args) {
    if (! (this instanceof RemoveFirstLine)) {
        return new RemoveFirstLine(args);
    }
    Transform.call(this, args);
    this._buff = '';
    this._removed = false;
}
util.inherits(RemoveFirstLine, Transform);

RemoveFirstLine.prototype._transform = function(chunk, encoding, done) {
    if (this._removed) { // if already removed
        this.push(chunk); // just push through buffer
    } else {
        // collect string into buffer
        this._buff += chunk.toString();

        // check if string has newline symbol
        if (this._buff.indexOf('\n') !== -1) {
            // push to stream skipping first line
            this.push(this._buff.slice(this._buff.indexOf('\n') + 2));
            // clear string buffer
            this._buff = null;
            // mark as removed
            this._removed = true;
        }
    }
    done();
};

像这样使用它:

var fs = require('fs');

var input = fs.createReadStream('test.txt'); // read file
var output = fs.createWriteStream('test_.txt'); // write file

input // take input
.pipe(RemoveFirstLine()) // pipe through line remover
.pipe(output); // save to file

另一种方式,这是不推荐的。
如果你的文件不是很大,而且你不介意把它们加载到内存中,加载文件,删除行,保存文件,但它是缓慢的,不会工作得很好的大文件。

var fs = require('fs');

var filePath = './test.txt'; // path to file

fs.readFile(filePath, function(err, data) { // read file to memory
    if (!err) {
        data = data.toString(); // stringify buffer
        var position = data.toString().indexOf('\n'); // find position of new line element
        if (position != -1) { // if new line element found
            data = data.substr(position + 1); // subtract string based on first line length

            fs.writeFile(filePath, data, function(err) { // write file
                if (err) { // if error, report
                    console.log (err);
                }
            });
        } else {
            console.log('no lines found');
        }
    } else {
        console.log(err);
    }
});
8fq7wneg

8fq7wneg2#

下面是另一种方法:

const fs = require('fs');
const filePath = './table.csv';

let csvContent = fs.readFileSync(filePath).toString().split('\n'); // read file and convert to array by line break
csvContent.shift(); // remove the the first element from array
csvContent = csvContent.join('\n'); // convert array back to string

fs.writeFileSync(filePath, csvContent);
xtfmy6hx

xtfmy6hx3#

感谢@Lilleman的评论,我对原来的解决方案做了修改,它需要一个第三方模块“逐行”,可以防止内存溢出和赛车条件下,处理非常大的文件。

const fs = require('fs');
const LineReader = require('line-by-line');

const removeLines = function(srcPath, destPath, count, cb) {

  if(count <= 0) {
    return cb();
  }

  var reader = new LineReader(srcPath);
  var output = fs.createWriteStream(destPath);

  var linesRemoved = 0;
  var isFirstLine = true;

  reader.on('line', (line) => {
    if(linesRemoved < count) {
      linesRemoved++;
      return;
    }
    reader.pause();

    var newLine;
    if(isFirstLine) {
      newLine = line;
      isFirstLine = false;
    } else {
      newLine = '\n' + line;
    }

    output.write(newLine, () => {
      reader.resume();
    });
  })
  .on('error', (err) => {
    reader.pause();
    return cb(err);
  })
  .on('close', () => {
    return cb();
  })
}

----------------以下为原始解决方案------------
受另一个答案的启发,这里是一个修改后的流版本:

const fs = require('fs');
const readline = require('readline');

const removeFirstLine = function(srcPath, destPath, done) {

  var rl = readline.createInterface({
    input: fs.createReadStream(srcPath)
  });
  var output = fs.createWriteStream(destPath);
  var firstRemoved = false;

  rl.on('line', (line) => {
    if(!firstRemoved) {
      firstRemoved = true;
      return;
    }
    output.write(line + '\n');
  }).on('close', () => {
    return done();
  })
}

并且可以通过将“firstRemoved”更改为计数器来轻松修改它以删除一定数量的行:

var linesRemoved = 0;
...
if(linesRemoved < LINES_TO_BE_REMOVED) {
  linesRemoved++;
  return;
}
...
wb1gzix0

wb1gzix04#

下面是一个使用基于Promise的文件系统API的简单解决方案。

const fs = require('node:fs/promises')
const os = require('node:os')

async function removeLines(path, numLinesToRemove) {
    const data = await fs.readFile(path, { encoding: 'utf-8' })
    const newData = data
        .split(os.EOL)              // split data into array of strings
        .slice(numLinesToRemove)    // remove first N lines of array
        .join(os.EOL)               // join array into a single string

    // overwrite original file with new data
    return fs.writeFile(path, newData)
}

相关问题