Escrevendo arquivos no Node.js

1646

Eu tenho tentado encontrar uma maneira de gravar em um arquivo ao usar o Node.js, mas sem sucesso. Como eu posso fazer isso?

Gjorgji
fonte

Respostas:

2465

Há muitos detalhes na API do sistema de arquivos . A maneira mais comum é:

const fs = require('fs');

fs.writeFile("/tmp/test", "Hey there!", function(err) {
    if(err) {
        return console.log(err);
    }
    console.log("The file was saved!");
}); 

// Or
fs.writeFileSync('/tmp/test-sync', 'Hey there!');
Brian McKenna
fonte
26
Testei esse script usando o Node e tentei alterar o caminho do arquivo para "/ home /", mas recebi o seguinte erro: { [Error: EACCES, open '/home/test.txt'] errno: 3, code: 'EACCES', path: '/home/test.txt' } Como posso modificar esse script para que funcione fora de /tmp?
Anderson Green
130
Observe também que você pode usar fs.writeFileSync (...) para realizar a mesma coisa de forma síncrona.
David Erwin
7
Talvez seja um pouco antigo, mas @AndersonGreen, você precisa executar o nó como root ou chmod / home corretamente para permitir permissões de R / W ao atual proprietário do processo do nó (seu nome de usuário é resistente) para que você possa escrever o arquivo
Denys Vitali
39
Na verdade, @DenysVitali, o problema é que Jane não pode gravar nenhum arquivo /home/.... Geralmente esse diretório é 755 root: wheel (ou qualquer outra coisa). Se o nó quiser gravar um arquivo como Jane, será mais fácil gravar nele /home/jane/test.txt. Mudar /homepara algo mais permissivo que 755 é um grande erro.
jane arc
7
@ JaneAvriette Bem, já que ele queria salvar o arquivo no /homediretório, sugeri que ele fosse modificado. Eu sei que isso pode gerar um problema de segurança. Mas bem, se o usuário quiser salvar lá, essa é a solução. PS: Eu concordo com o que você disse (:
Denys Vitali 29/01
537

Atualmente, existem três maneiras de escrever um arquivo:

  1. fs.write(fd, buffer, offset, length, position, callback)

    Você precisa aguardar o retorno de chamada para garantir que o buffer seja gravado no disco. Não é armazenado em buffer.

  2. fs.writeFile(filename, data, [encoding], callback)

    Todos os dados devem ser armazenados ao mesmo tempo; você não pode executar gravações seqüenciais.

  3. fs.createWriteStream(path, [options])

    Cria um WriteStream, o que é conveniente porque você não precisa esperar por um retorno de chamada. Mas, novamente, não é armazenado em buffer.

A WriteStream, como o nome diz, é um fluxo. Um fluxo por definição é "um buffer" contendo dados que se movem em uma direção (origem ► destino). Mas um fluxo gravável não é necessariamente "armazenado em buffer". Um fluxo é "armazenado em buffer" quando você escreve nhorários e, em seguida n+1, envia o buffer para o kernel (porque está cheio e precisa ser liberado).

Em outras palavras: "Um buffer" é o objeto. Se ele é ou não armazenado em buffer é uma propriedade desse objeto.

Se você olhar para o código, o WriteStreamherda de um Streamobjeto gravável . Se você prestar atenção, verá como eles liberam o conteúdo; eles não têm nenhum sistema de buffer.

Se você escreve uma string, ela é convertida em um buffer e enviada à camada nativa e gravada no disco. Ao escrever strings, eles não estão preenchendo nenhum buffer. Então, se você fizer:

write("a")
write("b")
write("c")

Voce esta fazendo:

fs.write(new Buffer("a"))
fs.write(new Buffer("b"))
fs.write(new Buffer("c"))

São três chamadas para a camada de E / S. Embora você esteja usando "buffers", os dados não são armazenados em buffer. Um fluxo em buffer faria:, fs.write(new Buffer ("abc"))uma chamada para a camada de E / S.

A partir de agora, no Node.js. v0.12 (versão estável anunciada em 06/06/2015) agora suporta duas funções: cork()e uncork(). Parece que essas funções finalmente permitirão armazenar em buffer / liberar as chamadas de gravação.

Por exemplo, em Java, existem algumas classes que fornecem fluxos em buffer ( BufferedOutputStream, BufferedWriter...). Se você escrever três bytes, esses bytes serão armazenados no buffer (memória) em vez de fazer uma chamada de E / S por apenas três bytes. Quando o buffer está cheio, o conteúdo é liberado e salvo no disco. Isso melhora o desempenho.

Não estou descobrindo nada, apenas lembrando como um acesso ao disco deve ser feito.

Gabriel Llamas
fonte
5
+1 - boa explicação. Para o fluxo de gravação, é importante ler os documentos com atenção. Se retornar falso ou fechado, é importante chamar writer.once ('drain', function () {}) ou perdi linhas que não haviam sido esgotadas quando o processo terminou.
Bryanmac
4
alguma chance de você poder fornecer um exemplo de como usar cork()e uncork()para aqueles de nós que desejam experimentar o nó de pré-lançamento 0.11?
professormeowingtons
A partir de agora, o Nó v0.12 é estável.
Aug
De acordo com uma análise de código do GitHub, fs.writeFile parece ser a mais popular das funções que você mencionou. Aqui estão exemplos do mundo real para o uso fs.writeFile
drorw
Existem bibliotecas de qualidade de produção na npmimplementação de gravação em buffer?
Nponeccop 12/05/19
266

Obviamente, você pode torná-lo um pouco mais avançado. Não bloqueando, escrevendo pedaços e partes, não escrevendo o arquivo inteiro de uma só vez:

var fs = require('fs');
var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
  stream.write("My first row\n");
  stream.write("My second row\n");
  stream.end();
});
Fredrik Andersson
fonte
17
Qual é a variável 'fd' passada no retorno de chamada para stream.once?
Scott Tesler
1
Descritor de arquivo @ScottDavidTesler para que você possa fechar o fluxo depois de terminar.
Alexey Kamenskiy
3
Quando fecho o fluxo? Por que isso não é bloqueador? Apenas curioso, estou tentando gravar em um arquivo de log.
MetaGuru 3/13/13
1
Não tenho certeza se quando o fluxo é liberado. Meu palpite é que existe a possibilidade de liberar o fluxo sob demanda.
Fredrik Andersson
1
@JoLiss Você terá que esperar por isso.
Fredrik Andersson /
61

Gravação síncrona

fs.writeFileSync (arquivo, dados [, opções])

fs = require('fs');

fs.writeFileSync("synchronous.txt", "synchronous write!")

Gravação assíncrona

fs.writeFile (arquivo, dados [, opções], retorno de chamada)

fs = require('fs');

fs.writeFile('asynchronous.txt', 'asynchronous write!', (err) => {
  if (err) throw err;
  console.log('The file has been saved!');
});

Onde

file <string> | <Buffer> | <URL> | <integer> filename or file descriptor
data <string> | <Buffer> | <Uint8Array>
options <Object> | <string>
callback <Function>

Vale a pena ler o arquivo oficial do sistema (fs) docs .

Moriarty
fonte
53
var path = 'public/uploads/file.txt',
buffer = new Buffer("some content\n");

fs.open(path, 'w', function(err, fd) {
    if (err) {
        throw 'error opening file: ' + err;
    }

    fs.write(fd, buffer, 0, buffer.length, null, function(err) {
        if (err) throw 'error writing file: ' + err;
        fs.close(fd, function() {
            console.log('file written');
        })
    });
});
Senhor P
fonte
2
isso demonstra como gravar um arquivo usando operações fs de nível inferior. por exemplo, você pode garantir quando o arquivo terminou de gravar no disco e lançou os descritores de arquivo.
Sean Glover
Como neste exemplo o deslocamento é definido como '0' (= terceiro parâmetro de fs.write()), este exemplo funciona apenas se tudo for curto o suficiente para ser gravado em uma única chamada de gravação.
Manfred
31

Eu gostei do Index ./articles/file-system .

Funcionou para mim.

Consulte também Como gravar arquivos no node.js? .

fs = require('fs');
fs.writeFile('helloworld.txt', 'Hello World!', function (err) {
    if (err) 
        return console.log(err);
    console.log('Wrote Hello World in file helloworld.txt, just check it');
});

Conteúdo do helloworld.txt:

Hello World!

Atualização:
Como no nó Linux, escreva no diretório atual, parece que em alguns outros não, então eu adiciono este comentário para o caso:
Usando isso ROOT_APP_PATH = fs.realpathSync('.'); console.log(ROOT_APP_PATH);para chegar onde o arquivo está gravado.

Sérgio
fonte
Onde encontrar o arquivo helloworld.txt? Não consigo encontrá-lo em nenhuma pasta ... obrigado.
Kai Feng Chew
na pasta em que você executa o script
Sérgio
Estranho ... simplesmente não consigo encontrá-lo em lugar nenhum. Será que vai ficar escondido? obrigado novamente ~
Kai Feng Chew 18 /
6
Acabei de encontrar. Usando este ROOT_APP_PATH = fs.realpathSync ('.'); console.log ( ROOT_APP_PATH ); para obter meu onde o arquivo foi escrito. Obrigado.
Kai Feng Chew
@ Sérgio: precisamos fechar o arquivo de gravação? Estou chamando outro processo e estou recebendo uma mensagem de erro referente ao arquivo que é iniciado por outro processo.
Amir
24

As respostas fornecidas são datadas e uma maneira mais recente de fazer isso é:

const fsPromises = require('fs').promises
await fsPromises.writeFile('/path/to/file.txt', 'data to write')

consulte os documentos aqui para obter mais informações

TrevTheDev
fonte
1
(node:23759) ExperimentalWarning: The fs.promises API is experimental
jgraup
@ jgraup: você está usando a versão mais recente do nó?
precisa saber é o seguinte
Nodev10.15.0
jgraup
7
A função de fechamento deve ser assíncrona ou isso não funcionará.
Zimano 29/08/19
1
@wintercounter Isso é muito fofo!
Zimano 27/04
19

Eu sei que a pergunta feita sobre "gravação", mas em um sentido mais geral, "anexar" pode ser útil em alguns casos, pois é fácil usar um loop para adicionar texto a um arquivo (se o arquivo existe ou não). Use "\ n" se você quiser adicionar linhas, por exemplo:

var fs = require('fs');
for (var i=0; i<10; i++){
    fs.appendFileSync("junk.csv", "Line:"+i+"\n");
}
Astra Bear
fonte
Como agora está disponível, recomendo o uso, em constvez de var, ou seja const fs = require('fs');, para evitar efeitos colaterais indesejados, principalmente se você estiver trabalhando com uma base de código um pouco maior.
Manfred
11

OK, é bastante simples, já que o Node possui funcionalidade interna para isso, é chamado fsde File System e, basicamente, o módulo NodeJS File System ...

Então, primeiro exija-o no seu arquivo server.js, desta forma:

var fs = require('fs');

fstem poucos métodos para gravar no arquivo, mas minha maneira preferida é usar appendFile, isso anexará as coisas ao arquivo e, se o arquivo não existir, criará um, o código pode ser como abaixo:

fs.appendFile('myFile.txt', 'Hi Ali!', function (err) {
  if (err) throw err;
  console.log('Thanks, It\'s saved to the file!');
});
Alireza
fonte
3
aspas simples na string devem ser escapadas.
Tamer
9
 var fs = require('fs');
 fs.writeFile(path + "\\message.txt", "Hello", function(err){
 if (err) throw err;
  console.log("success");
}); 

Por exemplo: leia o arquivo e grave em outro arquivo:

  var fs = require('fs');
    var path = process.cwd();
    fs.readFile(path+"\\from.txt",function(err,data)
                {
                    if(err)
                        console.log(err)
                    else
                        {
                            fs.writeFile(path+"\\to.text",function(erro){
                                if(erro)
                                    console.log("error : "+erro);
                                else
                                    console.log("success");
                            });
                        }
                });
Masoud Siahkali
fonte
Onde você está gravando os dados no "to.text"?
Ravi Shanker Reddy
O que essa resposta adiciona às várias respostas já existentes writeFile?
Dan Dascalescu 23/10/19
9

Você pode gravar em um arquivo usando o módulo fs (sistema de arquivos).

Aqui está um exemplo de como você pode fazer isso:

const fs = require('fs');

const writeToFile = (fileName, callback) => {
  fs.open(fileName, 'wx', (error, fileDescriptor) => {
    if (!error && fileDescriptor) {
      // Do something with the file here ...
      fs.writeFile(fileDescriptor, newData, (error) => {
        if (!error) {
          fs.close(fileDescriptor, (error) => {
            if (!error) {
              callback(false);
            } else {
              callback('Error closing the file');
            }
          });
        } else {
          callback('Error writing to new file');
        }
      });
    } else {
      callback('Could not create new file, it may already exists');
    }
  });
};

Você também pode se livrar dessa estrutura de código de retorno de chamada dentro de retorno usando promessas e async/ awaitinstruções. Isso tornará a estrutura de código assíncrona muito mais simples. Para fazer isso, pode ser utilizada uma função útil util.promisify (original) . Ele nos permite alternar entre retornos de chamada e promessas. Veja o exemplo com as fsfunções abaixo:

// Dependencies.
const util = require('util');
const fs = require('fs');

// Promisify "error-back" functions.
const fsOpen = util.promisify(fs.open);
const fsWrite = util.promisify(fs.writeFile);
const fsClose = util.promisify(fs.close);

// Now we may create 'async' function with 'await's.
async function doSomethingWithFile(fileName) {
  const fileDescriptor = await fsOpen(fileName, 'wx');

  // Do something with the file here...

  await fsWrite(fileDescriptor, newData);
  await fsClose(fileDescriptor);
}
Oleksii Trekhleb
fonte
1
Por que esses trechos e não pedaços de código? Eles nunca serão capazes de rodar em um navegador de qualquer maneira.
Zimano 29/08/19
@Zimano Pelo que entendi, a pergunta era sobre nodejs, portanto não precisa ser capaz de executar em um navegador.
Manfred
1
@Manfred Exactly! Eu acho que você não entendeu o que eu estava tentando dizer; não faz sentido ter trechos, pois é nodejs!
Zimano
5

Aqui usamos w + para ler / gravar as duas ações e, se o caminho do arquivo não for encontrado, ele será criado automaticamente.

fs.open(path, 'w+', function(err, data) {
    if (err) {
        console.log("ERROR !! " + err);
    } else {
        fs.write(data, 'content', 0, 'content length', null, function(err) {
            if (err)
                console.log("ERROR !! " + err);
            fs.close(data, function() {
                console.log('written success');
            })
        });
    }
});

Conteúdo significa o que você precisa gravar no arquivo e seu comprimento, 'content.length'.

Gunjan Patel
fonte
3

Aqui está o exemplo de como ler o arquivo csv do local e gravar o arquivo csv no local.

var csvjson = require('csvjson'),
    fs = require('fs'),
    mongodb = require('mongodb'),
    MongoClient = mongodb.MongoClient,
    mongoDSN = 'mongodb://localhost:27017/test',
    collection;

function uploadcsvModule(){
    var data = fs.readFileSync( '/home/limitless/Downloads/orders_sample.csv', { encoding : 'utf8'});
    var importOptions = {
        delimiter : ',', // optional 
        quote     : '"' // optional 
    },ExportOptions = {
        delimiter   : ",",
        wrap        : false
    }
    var myobj = csvjson.toSchemaObject(data, importOptions)
    var exportArr = [], importArr = [];
    myobj.forEach(d=>{
        if(d.orderId==undefined || d.orderId=='') {
            exportArr.push(d)
        } else {
            importArr.push(d)
        }
    })
    var csv = csvjson.toCSV(exportArr, ExportOptions);
    MongoClient.connect(mongoDSN, function(error, db) {
        collection = db.collection("orders")
        collection.insertMany(importArr, function(err,result){
            fs.writeFile('/home/limitless/Downloads/orders_sample1.csv', csv, { encoding : 'utf8'});
            db.close();
        });            
    })
}

uploadcsvModule()
KARTHIKEYAN.A
fonte
1
Isso apresenta todos os tipos de complicações (MongoClient, JSON etc.) que não pertencem à questão.
Dan Dascalescu 23/10/19
3

fs.createWriteStream(path[,options])

optionstambém pode incluir uma startopção para permitir a gravação de dados em alguma posição após o início do arquivo. Modificar um arquivo em vez de substituí-lo pode exigir um flagsmodo r+em vez do modo padrão w. A codificação pode ser qualquer uma das aceitas pelo Buffer .

Se autoCloseestiver definido como verdadeiro (comportamento padrão) 'error'ou 'finish'o descritor de arquivo será fechado automaticamente. E seautoClose for falso, o descritor de arquivo não será fechado, mesmo se houver um erro. É de responsabilidade do aplicativo fechá-lo e garantir que não haja vazamento do descritor de arquivo.

Como o ReadStream , se fdfor especificado, o WriteStream ignorará o pathargumento e usará o descritor de arquivo especificado. Isso significa que nenhum 'open'evento será emitido. fddeve estar bloqueando; fds sem bloqueio devem ser passados ​​para net.Socket .

Se optionsfor uma sequência, especifica a codificação.

Depois, lendo este longo artigo. Você deve entender como isso funciona. Então, aqui está um exemplo de createWriteStream().

/* The fs.createWriteStream() returns an (WritableStream {aka} internal.Writeable) and we want the encoding as 'utf'-8 */
/* The WriteableStream has the method write() */
fs.createWriteStream('out.txt', 'utf-8')
.write('hello world');

fonte
createWriteStreamjá foi mencionado em várias respostas anos antes desta.
Dan Dascalescu 23/10/19
0

Você pode usar a biblioteca easy-file-manager

instale primeiro a partir do npm npm install easy-file-manager

Exemplo para fazer upload e remover arquivos

var filemanager = require('easy-file-manager')
var path = "/public"
var filename = "test.jpg"
var data; // buffered image

filemanager.upload(path,filename,data,function(err){
    if (err) console.log(err);
});

filemanager.remove(path,"aa,filename,function(isSuccess){
    if (err) console.log(err);
});
Christoper
fonte
2
This modules is created to save and remove files.. Não é uma resposta.
Verde
-1

Você pode gravar em um arquivo pelo seguinte exemplo de código:

var data = [{ 'test': '123', 'test2': 'Lorem Ipsem ' }];
fs.open(datapath + '/data/topplayers.json', 'wx', function (error, fileDescriptor) {
  if (!error && fileDescriptor) {
    var stringData = JSON.stringify(data);
    fs.writeFile(fileDescriptor, stringData, function (error) {
      if (!error) {
        fs.close(fileDescriptor, function (error) {
          if (!error) {
            callback(false);
          } else {
            callback('Error in close file');
          }
        });
      } else {
        callback('Error in writing file.');
      }
    });
  }
});
Mudassir
fonte
1
writeFilejá havia sido dada como resposta várias vezes, anos atrás. O que essa resposta adiciona?
Dan Dascalescu 23/10/19
Também por que você abriu o arquivo? A resposta não deveria ser sobre a gravação de arquivos?
Michal