fs文件系统
本文转载于:http://blog.csdn.net/wade333777/article/details/69218537
一、概述
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:
var fs = require("fs")
API文档:http://www.runoob.com/nodejs/nodejs-fs.html
require(‘readline’) 模块提供了一个接口,用于从可读流(如 process.stdin)读取数据,每次读取一行。 它可以通过以下方式使用:
const readline = require('readline');
API文档:http://nodejs.cn/api/readline#readline_rl_write_data_key
1.异步和同步
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
// 同步读取
var data = fs.readFileSync('input.txt');
console.log("同步读取: " + data.toString());
// 异步读取
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取: " + data.toString());
});
2.打开文件
以下为在异步模式下打开文件的语法格式:
fs.open(path, flags[, mode], callback)
参数使用说明如下:
path - 文件的路径。
flags - 文件打开的行为。具体值详见下文。
mode - 设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。
callback - 回调函数,带有两个参数如:callback(err, fd)。
flags 参数可以是以下值:
Flag | 描述 |
---|---|
r | 以读取模式打开文件。如果文件不存在抛出异常。 |
r+ | 以读写模式打开文件。如果文件不存在抛出异常。 |
rs | 以同步的方式读取文件。 |
rs+ | 以同步的方式读取和写入文件。 |
w | 以写入模式打开文件,如果文件不存在则创建。 |
wx | 类似 ‘w’,但是如果文件路径存在,则文件写入失败。 |
w+ | 以读写模式打开文件,如果文件不存在则创建。 |
wx+ | 类似 ‘w+’, 但是如果文件路径存在,则文件读写失败。 |
a | 以追加模式打开文件,如果文件不存在则创建。 |
ax | 类似 ‘a’, 但是如果文件路径存在,则文件追加失败。 |
a+ | 以读取追加模式打开文件,如果文件不存在则创建。 |
ax+ | 类似 ‘a+’, 但是如果文件路径存在,则文件读取追加失败。 |
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
});
3.获取文件信息
fs.stat(path, callback)
参数使用说明如下:
path - 文件路径。
callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。
fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:
fs.stat('/Users/liuht/code/itbilu/demo/fs.js', function (err, stats) {
console.log(stats.isFile()); //true
})
4.写入文件
以下为异步模式下写入文件的语法格式:
fs.writeFile(filename, data[, options], callback)
如果文件存在,该方法写入的内容会覆盖旧的文件内容。
参数使用说明如下:
path - 文件路径。
data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(流) 对象。
options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 ‘w’
callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
5.读取文件
以下为异步模式下读取文件的语法格式:
fs.read(fd, buffer, offset, length, position, callback)
该方法使用了文件描述符来读取文件。
参数使用说明如下:
fd - 通过 fs.open() 方法返回的文件描述符。
buffer - 数据写入的缓冲区。
offset - 缓冲区写入的写入偏移量。
length - 要从文件中读取的字节数。
position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。
6.关闭文件
以下为异步模式下关闭文件的语法格式:
fs.close(fd, callback)
该方法使用了文件描述符来读取文件。
参数使用说明如下:
fd - 通过 fs.open() 方法返回的文件描述符。
callback - 回调函数,没有参数。
其他方法 | 描述 |
---|---|
fs.rename(oldPath, newPath, callback) | 文件重命名 |
fs.unlink(path, callback) | 删除文件 |
fs.readdir(path, callback) | 读取目录 |
fs.createReadStream(path[, options])返回ReadStream 对象 | 读取大文件 |
fs.createWriteStream(path[, options]) | 写大文件 |
二、实战
公司项目平时处理BUG积攒了大量的垃圾输出标记print语句,所以就想写个工具干掉这些垃圾语句,最近也是喜欢研究nodejs这种前后端通吃的语言,索性就拿来练练手:
// 删除文件中的特殊符号信息(删除print标记)
// 1.遍历当前目录,判断是否是文件
// 2.不是文件是目录,继续递归遍历
// 3.是文件,开始做特殊处理,一行一行读取,开始做处理
// 4.判断当前行内容中是否有print
// 5.有的话,读完文件后替换源文件,没有的话则跳过到下一个文件
const fs = require('fs')
const readline = require('readline')
const os = require('os')
//要处理的特殊字符
var special_chars = ['print']
console.log('当前执行目录:'+__dirname)
//列表当前目录中的文件
function listFile(_dir_name){
fs.readdir(_dir_name,function(_err,_files){
if(_err)
return console.log(_err)
if(!_files.length)
return console.log(_dir_name + ' have no files to show! \n')
_files.forEach(function(_file_name){
if(filterFile(_file_name)){
var full_name = _dir_name + '/' + _file_name
fs.stat(full_name,function(_err,_stat){
if(_stat.isDirectory())
listFile(full_name)
else
dealFile(full_name)
})
}
})
})
}
// 拆分全路径下的路径和文件名
function splitPathFile(_full_name){
if(_full_name == '')
throw('splitPathFile _full_name is null')
var __s = _full_name.split('/')
var __file_name = __s[__s.length-1]
var __path_name = ''
if(__s.length > 1){
for (var i = 0; i <= __s.length-2; i++) {
__path_name = __path_name + __s[i] + '/'
}
}
return [__path_name,__file_name]
}
// 处理文件
function dealFile(_full_name){
console.log('dealFile:'+_full_name)
var __is_special = false
var __path_name = splitPathFile(_full_name)[0]
var __file_name = splitPathFile(_full_name)[1]
var __tmp_name = __path_name + __file_name + 'tmp.txt'
var __output = fs.createWriteStream(__tmp_name)
var rl = readline.createInterface({
input : fs.createReadStream(_full_name),
output : __output
})
rl.on('line',function(_line){
// console.log('文件单行内容:'+_line)
var __is = filterSpecialChar(_line)
if(__is){
__is_special = true
console.log('__is_special = true')
}else{
__output.write(_line + os.EOL)
}
})
rl.on('close',function(){
console.log(_full_name + " is closed")
if(__is_special){
fs.unlink(_full_name,function(_err){
if(_err){
return console.log(_err)
}
fs.rename(__tmp_name,_full_name,function(_err){
if(_err){
return console.log(_err)
}
console.log('文件处理完毕1:' + _full_name)
})
})
}else{
fs.unlink(__tmp_name,function(_err){
if(_err){
return console.log(_err)
}
console.log('文件处理完毕2:' + _full_name)
})
}
})
}
// 过滤特殊字符
function filterSpecialChar(_str){
var __is = false
_str = _str.trim()
// console.log(_str.indexOf('print'))
for(var i =0;i < special_chars.length;i++){
if(_str.indexOf(special_chars[i]) == 0){
return true
}
}
return false
}
//过滤器,做文件过滤工作,例如.DS_Store文件
function filterFile(_file_name){
if(_file_name.charAt(0) == '.')
return false
return true
}
listFile(__dirname)