【问题标题】:Writing files in Node.js在 Node.js 中编写文件
【发布时间】:2011-01-30 14:27:09
【问题描述】:

我一直在尝试找到一种在使用 Node.js 时写入文件的方法,但没有成功。我该怎么做?

【问题讨论】:

    标签: javascript node.js file express fs


    【解决方案1】:

    目前有三种写文件的方式:

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

      您需要等待回调以确保将缓冲区写入磁盘。它没有缓冲。

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

      所有数据必须同时存储;您无法执行顺序写入。

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

      创建一个WriteStream,这很方便,因为您不需要等待回调。但同样,它没有被缓冲。

    顾名思义,WriteStream 是一个流。根据定义,流是“缓冲区”,其中包含沿一个方向(源 ► 目标)移动的数据。但可写流不一定是“缓冲的”。当您写入 n 次时,流会被“缓冲”,而在时间 n+1 时,流会将缓冲区发送到内核(因为它已满,需要刷新)。

    换句话说:“缓冲区”是对象。它是否“被缓冲”是该对象的属性。

    如果您查看代码,WriteStream 继承自可写的 Stream 对象。如果你注意,你会看到他们是如何刷新内容的;他们没有任何缓冲系统。

    如果你写一个字符串,它会被转换成一个缓冲区,然后发送到原生层并写入磁盘。写入字符串时,它们不会填满任何缓冲区。所以,如果你这样做:

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

    你正在做:

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

    这是对 I/O 层的三个调用。尽管您使用的是“缓冲区”,但数据并未被缓冲。缓冲流可以:fs.write(new Buffer ("abc")),一次调用 I/O 层。

    截至目前,Node.js v0.12(2015 年 2 月 6 日发布的稳定版)现在支持两个功能: cork()uncork()。看来这些函数最终将允许您缓冲/刷新写入调用。

    例如,在 Java 中有一些提供缓冲流的类(BufferedOutputStreamBufferedWriter...)。如果您写入三个字节,这些字节将存储在缓冲区(内存)中,而不是只为三个字节执行 I/O 调用。当缓冲区已满时,内容将被刷新并保存到磁盘。这提高了性能。

    我没有发现任何东西,只是记住应该如何进行磁盘访问。

    【讨论】:

    • +1 - 很好的解释。对于写入流,仔细阅读文档很重要。如果返回 false 或关闭,调用 writer.once('drain', function(){}) 很重要,否则我错过了进程结束时没有耗尽的行。
    • 有没有机会为我们这些想要试用 0.11 预发布节点的人提供如何使用 cork()uncork() 的示例?
    • 目前,Node v0.12 稳定。
    • 根据 GitHub 上的代码分析,fs.writeFile 似乎是你提到的最流行的函数。这里是real world examples for using fs.writeFile
    • npm 上是否有实现缓冲写入的生产质量库?
    【解决方案2】:

    第 1 点:

    如果您想将某些内容写入文件。 意思是:它将删除文件中已保存的所有内容并写入新内容。使用 fs.promises.writeFile()

    第 2 点:

    如果您想将某些内容附加到文件中。 意思是:它不会删除文件中已经保存的任何内容,而是将新项目附加到文件内容中。然后首先读取文件,然后将内容添加到可读值中,然后将其写入文件。所以使用 fs.promises.readFile 和 fs.promises.writeFile()


    示例 1:我想在我的 JSON 文件中写入一个 JSON 对象。

    const fs = require('fs');
    const data = {table:[{id: 1, name: 'my name'}]}
    const file_path = './my_data.json'
    writeFile(file_path, data)
    async function writeFile(filename, writedata) {
      try {
        await fs.promises.writeFile(filename, JSON.stringify(writedata, null, 4), 'utf8');
        console.log('data is written successfully in the file')
      }
      catch (err) {
        console.log('not able to write data in the file ')
      }
    }
    

    示例2: 如果要将数据附加到 JSON 文件。 您想将数据 {id:1, name:'my name'} 添加到同一文件夹根目录下的文件 my_data.json 中。只需调用 append_data (file_path , data ) 函数。

    如果文件存在,它将在 JSON 文件中附加数据。否则它将创建文件并向其中添加数据。

    const fs = require('fs');
    const data = {id: 2, name: 'your name'}
    const file_path = './my_data.json'
    append_data(file_path, data)
    
    async function append_data(filename, data) {
    
      if (fs.existsSync(filename)) {
        var read_data = await readFile(filename)
        if (read_data == false) {
          console.log('not able to read file')
        } else {
          read_data.table.push(data)  //data must have the table array in it like example 1
          var dataWrittenStatus = await writeFile(filename, read_data)
          if (dataWrittenStatus == true) {
            console.log('data added successfully')
          } else {
            console.log('data adding failed')
          }
        }
      }
    }
    
    async function readFile(filePath) {
      try {
        const data = await fs.promises.readFile(filePath, 'utf8')
        return JSON.parse(data)
      }
      catch (err) {
        return false;
      }
    }
    
    async function writeFile(filename, writedata) {
      try {
        await fs.promises.writeFile(filename, JSON.stringify(writedata, null, 4), 'utf8');
        return true
      }
      catch (err) {
        return false
      }
    }
    

    【讨论】:

      【解决方案3】:

      这里我们使用 w+ 进行读/写操作,如果找不到文件路径,则会自动创建。

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

      内容表示您必须写入文件的内容及其长度,“content.length”。

      【讨论】:

        【解决方案4】:

        第 1 点:

        如果您想将某些内容写入文件。 意思是:它将删除文件中已保存的所有内容并写入新内容。使用 fs.promises.writeFile()

        第 2 点:

        如果您想将某些内容附加到文件中。 意思是:它不会删除文件中已经保存的任何内容,而是将新项目附加到文件内容中。然后首先读取文件,然后将内容添加到可读值中,然后将其写入文件。所以使用 fs.promises.readFile 和 fs.promises.writeFile()


        示例 1:我想在我的 JSON 文件中写入一个 JSON 对象。

        const fs = require('fs');
        

        writeFile(文件名,写入数据) 异步函数 writeFile (filename ,writedata) { 尝试 { 等待 fs.promises.writeFile(filename, JSON.stringify(writedata,null, 4), 'utf8'); 返回真 } 捕捉(错误){ 返回假 } }

        【讨论】:

          【解决方案5】:

          您可以使用流写入文件。

          就这样吧:

          const fs = require('fs');
          
          const stream = fs.createWriteStream('./test.txt');
          stream.write("Example text");
          

          【讨论】:

            【解决方案6】:

            同步写入

            fs.writeFileSync(file, data[, options])

            fs = require('fs');
            
            fs.writeFileSync("foo.txt", "bar");
            

            异步写入

            fs.writeFile(file, data[, options], callback)

            fs = require('fs');
            
            fs.writeFile('foo.txt', 'bar', (err) => { if (err) throw err; });
            

            在哪里

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

            值得阅读官方文件系统(fs)docs

            更新:异步/等待

            fs = require('fs');
            util = require('util');
            writeFile = util.promisify(fs.writeFile);
            
            fn = async () => { await writeFile('foo.txt', 'bar'); }
            
            fn()
            

            【讨论】:

              【解决方案7】:

              File System API中有很多细节。最常见的方式是:

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

              【讨论】:

              • 我已经使用 Node 测试过这个脚本,我尝试将文件路径更改为“/home/”,但出现以下错误:{ [Error: EACCES, open '/home/test.txt'] errno: 3, code: 'EACCES', path: '/home/test.txt' } 我如何修改这个脚本以便它将在/tmp之外工作吗?
              • 另请注意,您可以使用 fs.writeFileSync(...) 同步完成相同的事情。
              • 也许它有点旧,但是@AndersonGreen,你需要以 root 或 chmod /home 正确运行 node 以允许当前节点进程所有者的 R/W 权限(你的用户名很难)所以你可以写文件
              • 其实@DenysVitali,问题是jane应该不能将任何文件写入/home/...。通常该目录是 755 root:wheel (或其他)。如果 node 想以 jane 的身份写一个文件,写到/home/jane/test.txt 会更容易。将 /home 更改为比 755 更宽松的内容是一个巨大的错误。
              • @JaneAvriette 好吧,因为他想将文件保存在/home 目录中,所以我建议对它进行 chmod。我知道这可能会产生安全问题。但是,如果用户想在那里保存,那就是解决方案。 P.S:我同意你说的(:
              【解决方案8】:

              您可以使用fs(文件系统)模块写入文件。

              以下是您可以如何做到的示例:

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

              您可能还想通过使用 Promisesasync/await 语句来摆脱这种回调内部回调代码结构。这将使异步代码结构更加平坦。为此,可以使用方便的util.promisify(original) 函数。它允许我们从回调切换到承诺。看看下面带有fs 函数的示例:

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

              【讨论】:

              • 为什么这些是 sn-ps 而不是代码片段?无论如何,它们将永远无法在浏览器中运行。
              • @Zimano 据我了解,问题是关于 nodejs,所以不需要能够在浏览器中运行。
              • @Manfred 没错!我想你误解了我想说的话;有 sn-ps 没有意义,因为它是 nodejs!
              【解决方案9】:

              您可以通过以下代码示例写入文件:

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

              【讨论】:

              • writeFile 多年前已经多次给出答案。这个答案增加了什么?
              • 另外你为什么打开文件?答案不应该是写文件吗?
              【解决方案10】:

              提供的答案已过时,更新的方法是:

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

              see documents here for more info

              【讨论】:

              • (node:23759) ExperimentalWarning: The fs.promises API is experimental
              • @jgraup:你用的是最新版本的node吗?
              • 节点v10.15.0
              • 封闭函数必须是异步的,否则这将不起作用。
              • @Zimano Node 已经支持顶级等待,你不需要异步包装器。
              【解决方案11】:

              好的,这很简单,因为 Node 有内置的功能,它被称为 fs,代表 File System,基本上,NodeJS 文件系统模块。 ..

              所以首先在你的 server.js 文件中要求它,如下所示:

              var fs = require('fs');
              

              fs 几乎没有写入文件的方法,但我首选的方法是使用appendFile,这会将内容附加到文件中,如果文件不存在,将创建一个,代码可以是如下:

              fs.appendFile('myFile.txt', 'Hi Ali!', function (err) {
                if (err) throw err;
                console.log('Thanks, It\'s saved to the file!');
              });
              

              【讨论】:

              • 字符串中的单引号应该被转义。
              【解决方案12】:

              fs.createWriteStream(path[,options])

              options 还可能包含一个start 选项,以允许在文件开头之后的某个位置写入数据。修改而不是替换文件可能需要r+flags 模式而不是默认模式w。编码可以是Buffer 接受的任何一种编码。

              如果在'error''finish' 上将autoClose 设置为true(默认行为),则文件描述符将自动关闭。如果autoClose 为假,则文件描述符不会关闭,即使出现错误。关闭它并确保没有文件描述符泄漏是应用程序的责任。

              ReadStream 一样,如果指定了fdWriteStream 将忽略path 参数并使用指定的文件描述符。这意味着不会发出 'open' 事件。 fd 应该被阻塞;非阻塞fds 应该被传递给net.Socket

              如果options 是字符串,则它指定编码。

              之后,阅读这篇长文。你应该了解它是如何工作的。 所以,这里有一个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');
              

              【讨论】:

              【解决方案13】:

              我知道关于“写入”的问题,但在更一般的意义上,“附加”在某些情况下可能很有用,因为它很容易在循环中使用以将文本添加到文件(无论文件是否存在) .如果要添加行,请使用“\n”,例如:

              var fs = require('fs');
              for (var i=0; i<10; i++){
                  fs.appendFileSync("junk.csv", "Line:"+i+"\n");
              }
              

              【讨论】:

              • 既然它现在可用,我建议使用const 而不是var,即const fs = require('fs');,以避免不必要的副作用,尤其是在您使用更大的代码库时。
              【解决方案14】:

              我喜欢Index of ./articles/file-system

              它对我有用。

              另请参阅How do I write files in 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');
              });
              

              helloworld.txt 的内容:

              Hello World!
              

              更新:
              就像在 Linux 节点中写入当前目录一样,其他一些似乎没有,所以我添加此注释以防万一:
              使用这个ROOT_APP_PATH = fs.realpathSync('.'); console.log(ROOT_APP_PATH); 来获取文件的写入位置。

              【讨论】:

              • 在哪里可以找到文件 helloworld.txt ?我在任何文件夹中都找不到它...谢谢。
              • 在您运行脚本的文件夹中
              • 这很奇怪......我只是在任何地方都找不到它。会隐藏吗?再次感谢~
              • 我刚刚找到它。使用这个 ROOT_APP_PATH = fs.realpathSync('.'); console.log(ROOT_APP_PATH);让我的文件写在哪里。谢谢。
              • @Sérgio:我们需要关闭 writefile 吗?我正在调用另一个进程,我收到一条错误消息,说明文件已开始被其他进程使用。
              【解决方案15】:

              这里是如何从本地读取文件 csv 并将 csv 文件写入本地的示例。

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

              【讨论】:

              • 这会引入与问题无关的各种复杂情况(MongoClient、JSON 等)。
              【解决方案16】:
               var fs = require('fs');
               fs.writeFile(path + "\\message.txt", "Hello", function(err){
               if (err) throw err;
                console.log("success");
              }); 
              

              例如:读取文件并写入另一个文件:

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

              【讨论】:

              • 您在哪里将数据写入“to.text”??
              • 这个答案对关于writeFile的多个现有答案有什么作用?
              【解决方案17】:

              你可以使用库easy-file-manager

              首先从 npm 安装 npm install easy-file-manager

              上传和删除文件的示例

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

              【讨论】:

              • This modules is created to save and remove files.。没有答案。
              【解决方案18】:

              你当然可以让它更高级一点。非阻塞,写点点滴滴,不是一次写整个文件:

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

              【讨论】:

              • 传递给 stream.once 回调的“fd”变量是什么?
              • @ScottDavidTesler 文件描述符,因此您可以在完成后关闭流。
              • 何时关闭流?为什么这是非阻塞的?只是好奇,我正在尝试写入日志文件。
              • 我不确定流何时刷新。我的猜测是有可能按需刷新流。
              • @JoLiss 你将不得不等待它。
              【解决方案19】:
              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');
                      })
                  });
              });
              

              【讨论】:

              • 这演示了如何使用较低级别的 fs 操作写入文件。例如,您可以保证文件何时完成写入磁盘并释放文件描述符。
              猜你喜欢
              • 2012-03-18
              • 1970-01-01
              • 1970-01-01
              • 2021-06-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-04-04
              相关资源
              最近更新 更多