노드에서 파일에 추가하는 방법?


505

로그 파일에 문자열 을 추가 하려고 합니다. 그러나 writeFile은 문자열을 쓰기 전에 매번 내용을 지 웁니다.

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

이 방법을 쉽게 수행하는 방법을 알고 있습니까?

답변:


799

때때로 추가하는 경우을 사용할 수 있습니다 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');

그러나 동일한 파일에 반복적으로 추가하는 경우 파일 핸들재사용하는 것이 훨씬 좋습니다 .


6
Node v0.8.0부터
denysonique

59
fs.appendFile 이 파일에 대한 링크를 열어서 추가가 더 빠른지 아는 사람이 있습니까? (각 쓰기를 열고 닫는 대신) nodejs.org/api/…
nelsonic

7
편리한 경우 : 이것은 비동기입니다. 이것은 이상한 타이밍과 다른 것들을 초래할 수 있습니다. 예 : process.exit()바로 뒤에 fs.appendFile있는 경우 출력이 전송되기 전에 종료 될 수 있습니다. (사용하는 return것이 좋습니다.)
SilentSteel

6
최악의 경우 동기 버전을 사용할 수 있습니다 appendFileSync. nodejs.org/api/… 그러나 비동기 작업 인 Node의 큰 이점 중 하나를 잃을 수도 있습니다. 오류가 발생했는지 확인하십시오. 아마도 일부 OS에서는 파일 핸들을 동시에 요청하면 액세스가 거부 될 수 있습니다. 확실하지 않습니다.
SilentSteel

5
@ chrisdew 업데이트 주셔서 감사합니다 ..... 만약 우리가 여기에 허용 된 답변을 사용하지 않으면, 우리는 어떻게해야합니까? 이 딜레마를 어떻게 해결 했습니까?
zipzit

214

로그 파일에 쓰려고 할 때 (예 : 파일 끝에 데이터 추가) 절대 사용 하지 마십시오 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활성화되면 기록되므로 타임 스탬프에 의해 로그가 기록되지 않습니다. 예를 들어 테스트 할 수 있으며 100000 대신 1000을 설정하면 순서는 무작위이며 파일에 대한 액세스에 따라 다릅니다.

파일에 추가하려면 다음 과 같이 쓰기 가능한 스트림 을 사용해야합니다 .

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되므로 프로세스가 끝나면 파일이 종료되고 너무 많은 파일을 열지 않아도됩니다 .


2
이 자리에 있습니다.
Pogrindis

3
큰 답변에 감사드립니다.하지만 제 의심은 Javascript의 비동기 특성으로 인해. stream.end()전에 실행 stream.write()되므로 기본 옵션이므로 stream.end()언급 하지 않았을 때 사용하지 말아야하는 AutoClose:True이유는 무엇입니까? 사용하다.
Aashish Kumar

13
due to asynchronous nature of Javascript... 뭐? Array.forEach는 동기 작업입니다. JS는 동 기적입니다. 약속 및 비동기 / 대기와 같은 비동기 작업을 관리하는 몇 가지 방법을 제공합니다.
Sharcoux

1
내가 추측에는 요 fs.appendFile비동기 방식으로 그것을 실행하기 때문에 내가 믿는, (그냥 비동기 10000 파일 핸들을 만드는) 너무 많은 열려있는 파일에 결과를 appendFileSync도하지, 비슷한 문제가없는 것입니다 fs.appendFile적절한 간격 (1 초는 아마 더 충분하다)와 또는 큐잉.
사과 사과

1
@RedwolfPrograms 사용량이 많은 서버 로그의 경우 사실 일 수 있습니다. 실행 로그 당 한 번은 아닐 수도 있습니다. 어쨌든, 나는이 답변의 요점 (적어도 이유)이 정확하지 않다고 말합니다.
apple apple

122

createWriteStream을 사용하는 코드는 모든 쓰기에 대해 파일 설명자를 작성합니다. log.end는 쓰기 직후에 노드를 닫도록 요청하기 때문에 더 좋습니다.

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');

6
첫 줄 누락! 'var fs = require ('fs ');'이어야합니다.
Stormbytes

5
또는 더 나은 var fs = require('graceful-fs')것으로 알려진 일부 문제를 해시했습니다. 자세한 내용은 문서 를 참조하십시오.
Marko Bonaci

3
모두 처음과 끝 라인 - P 불구하고 같은 라인에있는
binki

5
참고 : 사용하는 fs.createWriteStream경우을 사용하십시오 flags. 당신이 사용하는 경우 fs.writeFile다음이다 flag. 자세한 정보는 Node JS Docs-파일 시스템 을 참조하십시오.
Anish Nair

2
조심해! : 매개 변수는 "플래그"하지만 "플래그"(단수)하지 nodejs.org/api/...
베니 노이게 바우어

25

또한 기존 파일에 데이터를 추가하기 위해 appendFile플래그를 전달할 수도 writeFile있습니다.

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

플래그 'a'를 전달하면 파일 끝에 데이터가 추가됩니다.


3
참고 : 사용하는 fs.createWriteStream경우을 사용하십시오 flags. 당신이 사용하는 경우 fs.writeFile다음이다 flag. 자세한 정보는 Node JS Docs-파일 시스템 을 참조하십시오.
Anish Nair

19

그것을 열고 나서 써야합니다.

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');
    });
  });
});

다음은 매개 변수를 설명하는 데 도움이되는 몇 가지 링크입니다.

개방
쓰기
닫기


편집 :이 답변은 더 이상 유효하지 않습니다 . 추가 하려면 새로운 fs.appendFile 메소드를 살펴보십시오 .


1
supercobra가 지속적으로 로그를 로그 파일에 기록하는 것처럼 보이지만이 경우 fs.write를 사용하지 않는 것이 좋습니다. 대신 fs.createWriteStream을 사용하십시오. 읽기 nodejs.org/docs/v0.4.8/api/all.html#fs.write
화가 키위

10
nodejs v0.4.10부터 더 이상 대답이 정확하지 않습니다.
Ruben Tan

666이 아니라 '0666'이어야합니다.
Ya Zhuang

13

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!');
});

선적 서류 비치


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

5
sync ()는 100 % 확실하게 확신하지 않는 한 거의 항상 나쁜 생각입니다. 그럼에도 불구하고, 당신은 아마 잘못하고있을 것입니다.
Zane Claes

4
그것이 잘못되었다는 것을 의미하지는 않습니다. 그것은 단지 그것을 동 기적으로한다. Node.js에 대한 모범 사례는 아니지만 지원됩니다.
Luis R.

2
나는 구어체의 구어체 적 의미에서 "우리가 잘못하고있다"라는 문구를 사용하고 있었다. 분명히 그것은 지원됩니다 = P
Zane Claes

7
비동기로 동의하지만 때로는 대화 형 스크립트를 작성하는 경우 동기화가 좋습니다.
bryanmac

7
단일 사용자 명령 행 앱 (예 : 스크립트를 사용하여 작업)을 수행하는 경우 동기식으로 작성하는 것이 좋습니다. 그렇게하면 물건을 만드는 것이 더 빠릅니다. 이 목적이 아닌 경우 왜 노드에 동기화 방법이 있습니까?
Jan Święcki

3

파일에 한 줄씩 로그를 작성하는 쉽고 스트레스없는 방법을 원한다면 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');

노드 v8.9.4로 테스트되었습니다.


2

나의 접근 방식은 다소 특별하다. 나는 기본적으로 WriteStream솔루션을 사용 하지만 실제로를 사용하여 fd를 '클로징'하지 않습니다 stream.end(). 대신 cork/를 사용 uncork합니다. 이것은 RAM 사용량이 적다는 이점을 얻었으며 (누구에게나 중요한 경우) 로깅 / 레코딩에 사용하는 것이 더 안전하다고 생각합니다 (원래의 사용 사례).

다음은 매우 간단한 예입니다. 방금 for쇼케이스에 의사 루프를 추가 했습니다. 제작 코드에서 웹 소켓 메시지를 기다리고 있습니다.

var stream = fs.createWriteStream("log.txt", {flags:'a'});
for(true) {
  stream.cork();
  stream.write("some content to log");
  process.nextTick(() => stream.uncork());
}

uncork 다음 틱에서 데이터를 파일로 플러시합니다.

필자의 시나리오에서는 다양한 크기에서 초당 최대 200 회의 쓰기가 최고입니다. 그러나 야간에는 분당 소수의 쓰기 만 필요합니다. 코드는 피크 타임에도 안정적인 성능을 발휘합니다.


1

오픈 플래그 제어가 때로는 유용하기 때문에이 제안 만 제공합니다. 예를 들어, 기존 파일을 먼저 잘라낸 다음 일련의 쓰기를 추가 할 수 있습니다.이 경우 파일을 열 때 '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\'s saved!');
      });
    });
  });


1

사용 fs.appendFile또는 것은 fsPromises.appendFile당신이 파일에 무언가를 추가 할 필요가있을 때 가장 빠르고 가장 강력한 옵션입니다.

제안 된 답변 중 일부와 달리 파일 경로가 appendFile함수에 제공되면 실제로 닫힙니다 . 파일 핸들을 전달할 때만 파일 핸들을 fs.open()닫을 때주의해야합니다.

파일에서 50,000 줄 이상으로 시도했습니다.

예 :

(async () => {
  // using appendFile.
  const fsp = require('fs').promises;
  await fsp.appendFile(
    '/path/to/file', '\r\nHello world.'
  );

  // using apickfs; handles error and edge cases better.
  const apickFileStorage = require('apickfs');
  await apickFileStorage.writeLines(
    '/path/to/directory/', 'filename', 'Hello world.'
  );
})();

여기에 이미지 설명을 입력하십시오

참조 : https://github.com/nodejs/node/issues/7560
예제 실행 : https://github.com/apickjs/apickFS/blob/master/writeLines.js


0

전체 스크립트는 다음과 같습니다. 파일 이름을 입력하고 실행하면 작동합니다! 다음 은 스크립트 배후의 논리에 대한 비디오 자습서 입니다.

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);

0

가장 쉬운 방법은

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

무엇보다 쉬워? 정확히 같은 appendFileSync솔루션 을 제공하는 최고의 답변을 확인 했습니까 ?
Dan Dascalescu

0
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');
}

0

denysonique의 답변 외에도 appendFile콜백 전달 대신 약속이 반환되는 경우 NodeJS 의 비동기 유형 및 기타 비동기 메소드가 사용되는 경우가 있습니다. 이를 위해서는 promisifyHOF로 함수를 감싸 거나 promise 네임 스페이스에서 비동기 함수를 가져와야합니다.

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

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

도움이 되었기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.