fs 模块提供了一个 API,用于以模仿标准 POSIX 函数的方式与文件系统进行交互。

要使用此模块:

所有文件系统操作都具有同步和异步的形式。

异步的形式总是将完成回调作为其最后一个参数。 传给完成回调的参数取决于具体方法,但第一个参数始终预留用于异常。 如果操作成功完成,则第一个参数将为 null 或 undefined

使用同步的操作发生的异常会立即抛出,可以使用 try…catch 处理,也可以允许冒泡。

使用异步的方法时无法保证顺序。 因此,以下的操作容易出错,因为 fs.stat() 操作可能在 fs.rename() 操作之前完成:

要正确地排序这些操作,则将 fs.stat() 调用移动到 fs.rename() 操作的回调中:

在繁忙的进程中,强烈建议使用这些调用的异步版本。 同步的版本将阻塞整个进程,直到它们完成(停止所有连接)。

虽然不推荐这样使用,但大多数 fs 函数允许省略回调参数,在这种情况下,使用一个会重新抛出错误的默认回调。 要获取原始调用点的跟踪,则设置 NODE_DEBUG 环境变量:

不推荐在异步的 fs 函数上省略回调函数,因为可能导致将来抛出错误。

$ cat script.js
function bad() {
  require('fs').readFile('/');
}
bad();

$ env NODE_DEBUG=fs node script.js
fs.js:88
        throw backtrace;
        ^
Error: EISDIR: illegal operation on a directory, read
    <stack trace.>


1.fs.stat 检测是文件还是目录  

fs.stat('D:/Temp', function (err, stats) {
if (err) {
console.log(err);
return false;
}
console.log('文件:' + stats.isFile());
console.log('目录:' + stats.isDirectory());
});


2.fs.mkdir 创建目录  

//接收参数:

//path            将创建的目录路径

//mode          目录权限(读写权限),默认0777

//callback      回调,传递异常参数err

fs.mkdir('D:/Temp1', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('创建目录成功');
});


3.fs.writeFile 创建写入文件  

//filename      (String)            文件名称

//data        (String | Buffer)    将要写入的内容,可以使字符串 或 buffer数据。

//options        (Object)           option数组对象,包含:

//· encoding   (string)            可选值,默认 ‘utf8′,当data使buffer时,该值应该为 ignored。

//· mode         (Number)        文件读写权限,默认值 438

//· flag            (String)            默认值 ‘w'

//callback {Function}  回调,传递一个异常参数err。

fs.writeFile('D:/Temp/temp.txt', 'fs写入文件内容', 'utf8', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('写入成功');
});


4.fs.appendFile 追加文件  

fs.appendFile('D:/Temp/t1.txt', '这是第一次追加写入的内容', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('写入成功');
});

fs.appendFile('D:/Temp/t1.txt', '这是第二次追加写入的内容111\n', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('写入成功');
});


5.fs.readFile 读取文件  

fs.readFile('D:/Temp/t1.txt', function (err, data) {
if (err) {
console.log(err);
return false;
}
console.log(data);
console.log(data.toString());
});


6.fs.readdir 读取目录  

fs.readdir('D:/', function (err, data) {
if (err) {
console.log(err);
return false;
}
console.log(data);
});


7.fs.rename 重命名 

改名、剪切

fs.rename('D:/Temp/t1.txt', 'D:/Temp/t1_A.txt', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('修改名字成功');
});

fs.rename('D:/Temp/t1.txt', 'D:/TempAAA/tttt.txt', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('修改名字成功');
});


8.fs.rmdir 删除目录 

只能删除目录,并且目录为空

fs.rmdir('D:/Temp1', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('删除目录成功');
});


9.fs.unlink 删除文件 

fs.unlink('D:/Temp1/tttt.txt', function (err) {
if (err) {
console.log(err);
return false;
}
console.log('删除文件成功');
});


案例:递归读取文件夹下所有文件夹

let filesList = [];
getFolder('D:/');

function getFolder(path) {
try {
let files = fs.readdirSync(path);
for (let i = 0, len = files.length; i < len; i++) {
try {
let stats = fs.statSync(path + files[i]);
if (stats.isDirectory()) { /*目录*/
filesList.push(files[i]); /*保存数据*/
let tmpPath = path + files[i] + '/';//完整路径
getFolder(tmpPath);
}
} catch (err) {
console.log(err);
}
}
} catch (err) {
console.log(err);
}
};


10.fs.createReadStream 从文件流中读取数据

//流的方式读取文件
let readStream=fs.createReadStream('D:/Temp/t2.txt');

let str='';/*保存数据*/
let count=0; /*次数*/
readStream.on('data',function(chunk){
str+=chunk;
count++;
})

//读取完成
readStream.on('end',function(){
console.log(count);
console.log('读取完成:'+str);
})

//读取失败
readStream.on('error',function(err){
console.log('读取失败'+err);
})


11.fs.createWriteStream 写入文件

let data = '我是从流中写入的数据,我要保存起来11\n';

// 创建一个可以写入的流,写入到文件 output.txt
let writerStream = fs.createWriteStream('D:/Temp/temp.txt');

for(let i=0;i<100;i++){
writerStream.write(data,'utf8');
}

//标记写入完成
writerStream.end();

writerStream.on('finish',function(){
console.log('写入完成');
})

//失败
writerStream.on('error',function(){
console.log('写入失败');
})


12.管道流

// 创建一个可读流
let readerStream = fs.createReadStream('D:/Temp/t2.txt');
// 创建一个可写流
let writerStream = fs.createWriteStream('D:/Temp/output.txt');

// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);

console.log("程序执行完毕");

管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。