Node.js + MongoDB + AngularJS - 6 访问文件系统-1

在Node.js中,与文件系统的交互是非常重要的,特别是如果你需要通过管理动态文件支持web应用程序或服务。Node.js在fs模块中提供了与文件系统进行交互的良好接口。

1. 同步和异步文件系统调用

Node.js提供的fs模块使得几乎所有的功能都有两种形式可供选择:异步和同步。
应该尽可能地限制使用同步文件系统调用。
异步和同步的区别:
- 异步调用需要用一个回调函数作为额外的参数。回调函数在文件系统请求完成时被执行,并且通常包含一个错误作为其第一个参数。
- 异步调用会自动处理异常;并且如果发生异常,就把一个错误对象作为第一个参数传递。为了在同步调用中处理异常,必须使用try/catch块。
- 同步调用立即运行,并且除非它们完成,否则执行不会返回到当前线程。异步调用被放置在事件队列中,并且执行返回到正在运行的线程的代码,但是实际的调用直到它被事件循环提取出来时才会执行。

2. 打开和关闭文件

Node.js为打开文件提供了同步和异步方式。一旦文件被打开,你就可以从中读取数据或将数据写入它,这取决于用来打开文件的标志。

fs.open(path, flags, [mode], callback)
fs.openSync(path, flags, [mode])

path参数指定文件系统的标准路径字符串。flags参数指定打开文件的模式,读、写、追加等,可选的mode参数设置文件访问模式,默认是0666,这表示可读且可写。

模式 说明
r 打开文件用于读取。如果该文件不存在,则会出现异常
r+ 打开文件用于读写。如果文件不存在,则会出现异常
rs 在同步模式下打开文件用于读取。这与强制使用fs.openSync()是不一样的。当使用这种模式时,操作系统将绕过本地文件系统缓存。因为它可以让你跳过可能失效的本地缓存,所以这对NFS挂载是有用的。你应该只在必要时使用该标志,因为它可能会对性能产生负面影响
rs+ 同rs,除了打开文件用于读取和写入外
w 打开文件用于写操作。如果它不存在,就创建该文件;或者如果它存在,则截断该文件
wx 同w;但如果路径存在,则打开失败
w+ 打开文件用于写操作。如果它不存在,就创建该文件;或者如果它确实存在,则截断该文件
wx+ 同w+;但如果路径存在,则打开失败
a 打开文件用于追加。如果它不存在,则创建该文件
ax 同a;但如果路径存在,则打开失败
a+ 打开文件进行读取和追加。如果它不存在,则创建该文件
ax+ 同a+;但如果路径存在,则打开失败

一旦文件被打开,你需要关闭它以迫使操作系统把更改刷新到磁盘并释放操作系统锁。

fs.close(fd, callback)
fs.closeSync(fd) 
fs.open('myFile', 'w', function(err, fd) {
    if(!err) {
        fs.close(fd) ;    
    }
}) ;

var fd = fs.openSync('myFile', 'w') ;
fs.closeSync(fd) ;

3. 写入文件

fs提供了四种方式写入文件:

  • 简单文件写入
  • 同步文件写入
  • 异步文件写入
  • 流式文件写入

所有这些方法都接受一个String或Buffer对象作为输入。

3.1 简单文件写入

将数据写入一个文件的最简单方法是使用writeFile()方法中的一种。

fs.writeFile(path, data, [options], callback)
fs.writeFileSync(path, data, [options])

path参数指定文件的路径,这可以是相对或绝对路径。data参数指定将被写入到文件中的String或Buffer对象。可选的options参数是一个对象,它可以定义包含文件字符串编码,以及打开文件时使用的模式和标志的encoding、mode和flag属性。

var fs = require( 'fs' ) ;

var config = {
  maxFile: 20,
  maxConnections: 15,
  rootPath: '/webrooot'
} ;

var configText = JSON.stringify( config ) ;
var options = { encoding: 'utf8', flag: 'w' } ;

fs.writeFile( 'config.txt', configText, options, function( err ) {
  if( err ) {
    consolg.log( 'Config Write Failed' ) ;
  } else {
    console.log( 'Config Saved' ) ;
  }
} ) ;

3.2 同步文件写入

文件写入的同步方法涉及在返回执行正在运行的线程之前。
要同步写入文件,先用openSync()打开它来获取一个文件描述符,然后使用fs.writeSync()将数据写入文件。

fs.writeSync(fd, data, offset, length, position)

fd参数是openSync()返回的文件描述符。data参数指定将被写入文件中的String或Buffer对象。offset参数指定data参数中开始阅读的索引。如果你想从字符串或缓冲区的当前索引开始,这个值应该为null。length参数指定要写入的字节数,你可以指定null,表示一直写到数据缓冲区的末尾。position参数指定在文件中开始写入的位置;若要使用文件的当前位置,就把该值指定为null。

var fs = require('fs') ;
var veggieTray = ['carrots', 'celery', 'olives'] ;
fd = fs.openSync('veggie.txt', 'w') ;
while(veggieTray.length) {
    veggie = veggieTray.pop() + ' ' ;
    var bytes = fs.writeSync(fd, veggie, null, null) ;
    console.log('Wrote %s %dbytes', veggie, bytes) ;
}

3.3 异步写入文件

文件写入的异步方法在事件队列中放置一个写入请求,然后将控制返回给调用代码。除非事件循环提取出写入请求,并且执行它;否则实际的写操作不会发生。在同一个文件上执行多个异步写入请求时,你需要小心。因为除非你在执行下一个写入之前等待第一个写入回调函数完成,否则你不能保证执行的顺序。

fs.write(fd, data, offset, length, position, callback)

callback参数必须是可以接受error和bytes两个参数的函数,其中error是在写的过程中发生的错误,而bytes指定写入的字节数。

var fs = require('fs') ;
var fruitBowl = ['apple', 'orange', 'banana', 'grapes'] ;

function writeFruit(fd) {
    if(fruitBowl.length) {
        var fruit = fruitBowl.pop() + ' ' ;
        fs.write(fd, fruit, null, null, function (err, bytes) {
            if(err) {
                console.log('File Write Failed.') ;
            } else {
                console.log('Wrote; %s %dbytes', fruit, bytes) ;
                writeFruit(fd) ;
            }
        }) ;
    } else {
        fs.close(fd) ;
    }
}

fs.open('fruit.txt', 'w', function (err, fd) {
    writeFruit(fd) ;
}) ;

3.4 流式文件写入

往一个文件写入大量数据时,最好的方法之一是使用流,其中包括把文件作为一个Writeable流打开。

fs.createWriteStream(path, [options])

一旦你打开了Writeable文件流,就可以使用标准的流式write(buffer)方法来写入它。当你写入完成后,再调用end()方法来关闭流。

var fs = require('fs') ;
var grains = ['wheat', 'rice', 'oats'] ;
var options = {encoding: 'utf8', flag: 'w'} ;
var fileWriteStream = fs.createWriteStream('grains.txt', options) ;
fileWriteStream.on('close', function () {
    console.log('File closed.') ;
}) ;
while(grains.length) {
    var data = grains.pop() + ' ' ;
    fileWriteStream.write(data) ;
    console.log('Wrote: %s', data) ;
}

fileWriteStream.end() ;

4. 读取文件

4中方式从文件中读取数据:

  • 简单文件读取
  • 同步文件读取
  • 异步文件读取
  • 流式文件读取

4.1 简单文件读取

fs.readFile(path, [options], callback)
fs.readFileSync(path, [options])
var fs = require('fs') ;
var options = {encoding: 'utf8', flag: 'r'} ;
fs.readFile('config.txt', options, function (err, data) {
    if (err) {
        console.log('Failed to open Config File.') ;
    } else {
        console.log('Config Loaded.')
        var config = JSON.parse(data) ;
        console.log('Max Files: ' + config.maxFile) ;
        console.log('Max Connections: ' + config.maxConnections) ;
        console.log('/root path: ' + config.rootPath) ;
    }
}) ;

4.2 同步读取文件

fs.readSync(fd, buffer, offset, length, position)
var fs = require('fs') ;

fd = fs.openSync('veggie.txt', 'r') ;
var veggies = '' ;
do {
    var buf = new Buffer(5) ;
    buf.fill() ;
    var bytes = fs.readSync(fd, buf, null, 5) ;
    console.log('read %dbytes', bytes) ;
    veggies += buf.toString() ;
} while (bytes > 0) ;

fs.closeSync(fd) ;
console.log('Veggies: ' + veggies) ;

4.3 异步文件读取

fs.read(fd, buffer, offset, length, position, callback)

callback参数必须是一个可以接受error、bytes和buffer这3个参数的函数。

var fs = require('fs') ;
function readFruit(fd, fruits) {
    var buf = new Buffer(5) ;
    buf.fill() ;
    fs.read(fd, buf, 0, 5, null, function (err, bytes, data) {
        if (bytes > 0) {
            console.log('read %dbytes', bytes) ;
            fruits += data ;
            readFruit(fd, fruits) ;
        } else {
            fs.close(fd) ;
            console.log('Fruits; %s', fruits) ;
        }
    }) ;
}

fs.open('fruit.txt', 'r', function (err, fd) {
    readFruit(fd, "") ;
}) ;

4.4 流式文件读取

fs.createReadStream(path, [options])
var fs = require('fs') ;
var options = {encoding: 'utf8', flag: 'r'} ;
var fileReadStream = fs.createReadStream('grains.txt', options) ;

fileReadStream.on('data', function (chunk) {
    console.log('Grains: %s', chunk) ;
    console.log('Read %d bytes of data', chunk.length) ;
}) ;

fileReadStream.on('close', function () {
    console.log('File Closed.') ;
}) ;
原创文章 27 获赞 18 访问量 3万+

猜你喜欢

转载自blog.csdn.net/b635781894/article/details/51276025