关于javascript:在node.js中写入文件

Writing files in Node.js

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


文件系统API中有很多细节。最常见的方法是:

1
2
3
4
5
6
7
8
const fs = require('fs');
fs.writeFile("/tmp/test","Hey there!", function(err) {
    if(err) {
        return console.log(err);
    }

    console.log("The file was saved!");
});


目前有三种方法可以写入文件:

  • fs.write(fd, buffer, offset, length, position, callback

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

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

    所有数据必须同时存储;不能执行顺序写入。

  • fs.createWriteStream(path, [options]

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

  • 顾名思义,WriteStream是一条小溪。按定义,流是"缓冲区",其中包含朝一个方向移动的数据(源代码?目的地)。但可写流不一定是"缓冲"的。当您写入n次时,流被"缓冲",在n+1次时,流将缓冲发送到内核(因为缓冲已满,需要刷新)。

    换句话说,"缓冲区"就是对象。它是否"缓冲"是该对象的属性。

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

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

    1
    2
    3
    write("a")
    write("b")
    write("c")

    你正在做:

    1
    2
    3
    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年6月2日发布的稳定版本)中,现在支持两种功能:cork()uncork()。似乎这些函数最终将允许您缓冲/刷新写调用。

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

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


    你当然可以让它更高级一点。不阻塞,写入位和块,不立即写入整个文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    var fs = require('fs');
    var stream = fs.createWriteStream("my_file.txt");
    stream.once('open', function(fd) {
      stream.write("My first row
    "
    );
      stream.write("My second row
    "
    );
      stream.end();
    });


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    var path = 'public/uploads/file.txt',
    buffer = new Buffer("some content
    "
    );

    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.writeFileSync(file, data[, options])

    1
    2
    3
    fs = require('fs');

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

    异步写入

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

    1
    2
    3
    4
    5
    6
    fs = require('fs');

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

    在哪里?

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

    值得一读官方文件系统(FS)文档。


    我喜欢/文章/文件系统的索引。

    这对我很有用。

    另请参见如何在node.js中写入文件?.

    1
    2
    3
    4
    5
    6
    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的内容:

    1
    Hello World!

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


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

    1
    2
    3
    4
    5
    var fs = require('fs');
    for (var i=0; i<10; i++){
        fs.appendFileSync("junk.csv","Line:"+i+"
    "
    );
    }


    1
    2
    3
    4
    5
     var fs = require('fs');
     fs.writeFile(path +"\\message.txt","Hello", function(err){
     if (err) throw err;
      console.log("success");
    });

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
      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");
                                });
                            }
                    });


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

    下面是一个示例,说明您可以如何执行此操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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');
        }
      });
    };

    您可能还希望通过使用promises和async/await语句来消除回调代码结构中的回调。这将使异步代码结构更加简单。为此,可以使用一个方便的util.promisify(原始)函数。它允许我们从回拨转向承诺。请看下面使用fs函数的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 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);
    }


    在这里,我们使用w+来读/写两个操作,如果没有找到文件路径,它将自动创建。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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"。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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()


    OK,这很简单,因为节点有内置的功能,它被称为EDCOX1×2,它代表文件系统,基本上是NoDEJS文件系统模块…

    所以首先需要在你的Server .js文件中这样:

    1
    var fs = require('fs');

    fs有很少的方法来写文件,但我的首选方法是使用appendFile,这将把东西附加到文件中,如果文件不存在,将创建一个,代码如下:

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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
      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.');        
                }        
            });        
        }        
    }

    fs.createWriteStream(path[,options])

    options may also include a start option to allow writing data at some position past the beginning of the file. Modifying a file rather than replacing it may require a flags mode of r+ rather than the default mode w. The encoding can be any one of those accepted by Buffer.

    If autoClose is set to true (default behavior) on 'error' or 'finish' the file descriptor will be closed automatically. If autoClose is false, then the file descriptor won't be closed, even if there's an error. It is the application's responsibility to close it and make sure there's no file descriptor leak.

    Like ReadStream, if fd is specified, WriteStream will ignore the path argument and will use the specified file descriptor. This means that no 'open' event will be emitted. fd should be blocking; non-blocking fds should be passed to net.Socket.

    If options is a string, then it specifies the encoding.

    之后,阅读这篇长篇文章。你应该理解它是如何工作的。这里有一个createWriteStream()的例子。

    1
    2
    3
    4
    /* 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');

    您可以使用库easy-file-manager

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

    上传和删除文件的示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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);
    });


    请尝试以下操作:

    1
    2
    3
    4
    5
    fs.readFile(`${__dirname}/fileName`, 'utf-8',(err, contents) => {
        if (err) throw Error(err){
            console.log(contents)
        }
    });