在Node.js中写入文件


1642

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

Answers:


2461

文件系统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!');

25
我已经使用Node测试了此脚本,并尝试将文件路径更改为“ / home /”,但出现以下错误:{ [Error: EACCES, open '/home/test.txt'] errno: 3, code: 'EACCES', path: '/home/test.txt' } 如何修改此脚本,使其在外部运行/tmp
安德森·格林

129
还要注意,您可以使用fs.writeFileSync(...)同步完成同一件事。
David Erwin

7
也许它有点旧,但是@AndersonGreen,您需要以root或chmod / home身份正确运行节点,以允许当前节点进程所有者(您的用户名很难)具有读/写权限,因此您可以编写文件
Denys Vitali

38
实际上,@ DenysVitali的问题在于jane不应该将任何文件写入/home/...。通常,该目录为755 root:wheel(或其他任何目录)。如果node要以jane的形式编写文件,则写入起来会更容易/home/jane/test.txt。更改/home为比755更宽容的东西是一个巨大的错误。
jane arc

7
@JaneAvriette好吧,因为他想将文件保存在/home目录中,所以我建议将其更改为chmod。我知道这可能会产生安全问题。但是,如果用户想保存在那里,那就是解决方案。附言:我同意您的意见(:
Denys Vitali 2014年

535

当前有三种写入文件的方式:

  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调用。当缓冲区已满时,内容将被刷新并保存到磁盘。这样可以提高性能。

我什么也没发现,只是想起应该如何进行磁盘访问。


5
+1-不错的解释。对于写流,请务必仔细阅读文档。如果返回false或close,则重要的是调用writer.once('drain',function(){}),或者我错过了进程结束时尚未耗尽的行。
bryanmac 2014年

4
任何机会,你可以提供如何使用的例子cork(),并uncork()为我们这些谁想要尝试发布前0.11节点?
Professormeowingtons

到目前为止,Node v0.12稳定。
2015年8

根据来自GitHub的代码分析,fs.writeFile似乎是您提到的最流行的功能。这是使用fs.writeFile的真实示例
drorw

是否有关于npm实施缓冲写入的生产质量库?
nponeccop

265

您当然可以使其更高级。非阻塞,一点一点地写入,而不是一次写入整个文件:

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

17
传递给stream.once回调的'fd'变量是什么?
Scott Tesler

1
@ScottDavidTesler文件描述符,这样您就可以在完成后关闭流。
阿列克谢·卡门斯基

3
我什么时候关闭流?为什么不阻塞?只是好奇,我正在尝试写入日志文件。
MetaGuru

1
我不确定是否在刷新流时。我的猜测是有可能按需冲洗流。
Fredrik Andersson

1
@JoLiss您将不得不等待。
Fredrik Andersson 2014年

60

同步写

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

fs = require('fs');

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

异步写

fs.writeFile(文件,数据[,选项],回调)

fs = require('fs');

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

哪里

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

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


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

2
这演示了如何使用较低级别的fs操作写入文件。例如,您可以保证文件何时完成写入磁盘并释放文件描述符。
肖恩·格洛弗

由于在此示例中,如果将偏移量设置为'0'(=的第三个参数fs.write()),则此示例仅在所有内容都足够短以至于可以在单个写入调用中写入的情况下才起作用。
曼弗雷德

30

我喜欢./articles/file-system的索引

它为我工作。

另请参阅如何在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?我在任何文件夹中都找不到...谢谢。
Kai Feng Chew

在文件夹中运行脚本
塞尔吉奥

太奇怪了……我在任何地方都找不到。它会被隐藏吗?再次感谢〜
凯锋咀嚼

6
我刚刚找到了。使用此ROOT_APP_PATH = fs.realpathSync('。'); console.log(ROOT_APP_PATH); 把我的文件写到哪里。谢谢。
Kai Feng Chew

@Sérgio:我们需要关闭writefile吗?我正在调用另一个进程,并且收到有关文件被其他进程开始使用的错误消息。
阿米尔(Amir)

23

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

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

在此处查看文档以获取更多信息


1
(node:23759) ExperimentalWarning: The fs.promises API is experimental
jgraup19年

@jgraup:您是否正在使用最新版本的node?
TrevTheDev '19

节点v10.15.0
jgraup19年

7
封闭功能必须是异步的,否则将无法正常工作。
Zimano

1
@wintercounter真是太好了!
Zimano

18

我知道有关“写入”的问题,但在更一般的意义上,“附加”在某些情况下可能有用,因为在循环中将文本添加到文件中很容易使用(无论文件是否存在)。如果要添加行,请使用“ \ 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');避免不必要的副作用,尤其是在使用较大代码库的情况下。
曼弗雷德

10

好的,这很简单,因为Node具有内置功能,它被称为fs代表文件系统,基本上代表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!');
});

3
字符串中的单引号应转义。
塔默(Tamer)

8
 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什么作用?
Dan Dascalescu

7

您可以使用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语句来摆脱这种callback-inside-callback代码结构。这将使异步代码结构更加平坦。为此,可以使用方便的util.promisify(原始)函数。它使我们能够从回调切换到承诺。看一下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);
}

1
为什么这些片段而不是代码片段?无论如何,它们将永远无法在浏览器中运行。
Zimano

@Zimano据我所知,问题是关于nodejs的,因此不需要能够在浏览器中运行。
曼弗雷德

1
@Manfred就是这样!我认为您误解了我想说的话;片段是没有意义的,因为它是nodejs!
Zimano

4

在这里,我们使用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”。


2

这是如何从本地读取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()

1
这会引入与问题无关的各种复杂性(MongoClient,JSON等)。
Dan Dascalescu

2

fs.createWriteStream(path[,options])

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

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

ReadStream一样,如果fd已指定,则WriteStream将忽略该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');

createWriteStream之前的多个答案年中已经提到过。
Dan Dascalescu

0

你可以使用图书馆 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);
});

2
This modules is created to save and remove files.。没有答案。
绿色,

-1

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

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

1
writeFile几年前已经多次给出答案。这个答案增加了什么?
Dan Dascalescu

另外为什么要打开文件?答案不应该与写文件有关吗?
米歇尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.