Как добавить файл в Node?

Я пытаюсь добавить строку в файл журнала. Однако writeFile будет стирать содержимое каждый раз перед записью строки.

fs.writeFile('log.txt', 'Hello Node', function (err) {
  if (err) throw err;
  console.log('It\ saved!');
}); // => message.txt erased, contains only 'Hello Node'

Есть идеи, как сделать это простым способом?

Ответ 1

Для случайных добавлений вы можете использовать appendFile, который создает новый дескриптор файла при каждом вызове:

Асинхронно:

const fs = require('fs');

fs.appendFile('message.txt', 'data to append', function (err) {
  if (err) throw err;
  console.log('Saved!');
});

Синхронно:

const fs = require('fs');

fs.appendFileSync('message.txt', 'data to append');

Но если вы неоднократно добавляете к одному и тому же файлу, гораздо лучше повторно использовать дескриптор файла.

Ответ 2

Если вы хотите записать в файл журнала, то есть добавить данные в конец файла, никогда не используете appendFile, appendFile открывает дескриптор файла для каждого фрагмента данных, который вы добавляете в свой файл, через некоторое время вы получаете красивую ошибку EMFILE.

Я могу добавить, что appendFile не проще в использовании, чем WriteStream.

Пример с appendFile:

console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
    fs.appendFile("append.txt", index+ "\n", function (err) {
        if (err) console.log(err);
    });
});
console.log(new Date().toISOString());

До 8000 на моем компьютере, вы можете добавить данные в файл, затем вы получите это:

{ Error: EMFILE: too many open files, open 'C:\mypath\append.txt'
    at Error (native)
  errno: -4066,
  code: 'EMFILE',
  syscall: 'open',
  path: 'C:\\mypath\\append.txt' }

Кроме того, appendFile будет писать, когда он включен, поэтому ваши журналы не будут записываться по метке времени. Вы можете проверить с примером, установить 1000 вместо 100000, порядок будет случайным, зависит от доступа к файлу.

Если вы хотите добавить файл, вы должны использовать доступный для записи поток, подобный этому:

var stream = fs.createWriteStream("append.txt", {flags:'a'});
console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
    stream.write(index + "\n");
});
console.log(new Date().toISOString());
stream.end();

Вы заканчиваете это, когда хотите. Вы даже не обязаны использовать stream.end(), по умолчанию AutoClose:true, поэтому ваш файл завершится, когда завершится ваш процесс, и вы избежите открытия слишком большого количества файлов.

Ответ 3

Ваш код с помощью createWriteStream создает дескриптор файла для каждой записи. log.end лучше, потому что он запрашивает node закрыть сразу после записи.

var fs = require('fs');
var logStream = fs.createWriteStream('log.txt', {'flags': 'a'});
// use {'flags': 'a'} to append and {'flags': 'w'} to erase and write a new file
logStream.write('Initial line...');
logStream.end('this is the end line');

Ответ 4

Кроме appendFile, вы также можете передать флаг в writeFile для добавления данных в существующий файл.

fs.writeFile('log.txt', 'Hello Node',  {'flag':'a'},  function(err) {
    if (err) {
        return console.error(err);
    }
});

Пропустив флаг 'a', данные будут добавлены в конце файла.

Ответ 5

Вам нужно открыть его, а затем написать ему.

var fs = require('fs'), str = 'string to append to file';
fs.open('filepath', 'a', 666, function( e, id ) {
  fs.write( id, 'string to append to file', null, 'utf8', function(){
    fs.close(id, function(){
      console.log('file closed');
    });
  });
});

Вот несколько ссылок, которые помогут объяснить параметры

open
write
close


EDIT. Этот ответ более недействителен, посмотрите на новый метод fs.appendFile для добавления.

Ответ 6

Node.js 0.8 имеет fs.appendFile:

fs.appendFile('message.txt', 'data to append', (err) => {
  if (err) throw err;
  console.log('The "data to append" was appended to file!');
});

Документация

Ответ 7

fd = fs.openSync(path.join(process.cwd(), 'log.txt'), 'a')
fs.writeSync(fd, 'contents to append')
fs.closeSync(fd)

Ответ 8

Если вам нужен простой и удобный способ записи журналов построчно в файле, я рекомендую fs-extra:

const os = require('os');
const fs = require('fs-extra');

const file = 'logfile.txt';
const options = {flag: 'a'};

async function writeToFile(text) {
  await fs.outputFile(file, '${text}${os.EOL}', options);
}

writeToFile('First line');
writeToFile('Second line');
writeToFile('Third line');
writeToFile('Fourth line');
writeToFile('Fifth line');

Протестировано с Node v8.9.4.

Ответ 9

Я предлагаю это предложение только потому, что иногда полезно управлять открытыми флагами, например, вы можете сначала усечь его существующим файлом, а затем добавить к нему ряд записей - в этом случае используйте флаг "w", когда открывая файл и не закрывайте его до тех пор, пока все записи не будут выполнены. Конечно, appendFile может быть тем, что вам нужно: -)

  fs.open('log.txt', 'a', function(err, log) {
    if (err) throw err;
    fs.writeFile(log, 'Hello Node', function (err) {
      if (err) throw err;
      fs.close(log, function(err) {
        if (err) throw err;
        console.log('It\ saved!');
      });
    });
  });

Ответ 10

Использование jfile package:

myFile.text+='\nThis is new line to be appended'; //myFile=new JFile(path);

Ответ 11

Здесь полный script. Заполните имена файлов и запустите их, и они должны работать! Здесь видеоурок по логике script.

var fs = require('fs');

function ReadAppend(file, appendFile){
  fs.readFile(appendFile, function (err, data) {
    if (err) throw err;
    console.log('File was read');

    fs.appendFile(file, data, function (err) {
      if (err) throw err;
      console.log('The "data to append" was appended to file!');

    });
  });
}
// edit this with your file names
file = 'name_of_main_file.csv';
appendFile = 'name_of_second_file_to_combine.csv';
ReadAppend(file, appendFile);

Ответ 12

более простой способ сделать это

const fs = require('fs');
fs.appendFileSync('file.txt', 'message to append into file');

Ответ 13

const inovioLogger = (logger = "") => {
    const log_file = fs.createWriteStream(__dirname + '/../../inoviopay-${new Date().toISOString().slice(0, 10)}.log', { flags: 'a' });
    const log_stdout = process.stdout;
    log_file.write(logger + '\n');
}

Ответ 14

В дополнение к денисоническому ответу, иногда асинхронный тип appendFile и другие асинхронные методы в NodeJS используются там, где обещание возвращается вместо передачи обратного вызова. Для этого вам нужно обернуть функцию с promisify HOF или импортировать асинхронные функции из пространства имен обещаний:

const { appendFile } = require('fs').promises;

await appendFile('path/to/file/to/append', dataToAppend, optionalOptions);

Я надеюсь, что это поможет 😉

Ответ 15

Из документации по nodejs.

  // Creates /tmp/a/apple, regardless of whether '/tmp' and /tmp/a exist.
    fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
      if (err) throw err;
    });

В Windows использование fs.mkdir() в корневом каталоге даже с рекурсией приведет к ошибке:

    fs.mkdir('/', { recursive: true }, (err) => {
      // => [Error: EPERM: operation not permitted, mkdir 'C:\']
    });

Посмотрите на https://nodejs.org/api/fs.html#fs_fs_mkdir_path_options_callback