好的代码像粥一样,都是用时间熬出来的。

概述

文件 I/O 是由简单封装的标准 POSIX 函数提供的。 通过 require('fs') 使用该模块。

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

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

// 异步示例
const fs = require('fs'); fs.unlink('/tmp/hello', (err) => {
if (err) throw err;
console.log('已成功删除 /tmp/hello');
});

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

//同步示例
const fs = require('fs'); try {
fs.unlinkSync('/tmp/hello');
console.log('已成功删除 /tmp/hello');
} catch (err) {
// 处理错误
}

在进程中,建议使用异步版本。 同步的版本将阻塞整个进程,直到它们完成(停止所有连接)。但是异步操作不保证执行顺序所以,所以在使用时请注意使用对象执行顺序。

文件系统标志

flags可以是:

'a' - 打开文件用于追加。如果文件不存在,则创建该文件。
'ax' - 与 'a' 相似,但如果路径已存在则失败。
'a+' - 打开文件用于读取和追加。如果文件不存在,则创建该文件。
'ax+' - 与 'a+' 相似,但如果路径已存在则失败。
'as' - 以同步模式打开文件用于追加。如果文件不存在,则创建该文件。
'as+' - 以同步模式打开文件用于读取和追加。如果文件不存在,则创建该文件。
'r' - 打开文件用于读取。如果文件不存在,则出现异常。
'r+' - 打开文件用于读取和写入。如果文件不存在,则出现异常。
'rs+' - 以同步模式打开文件用于读取和写入。指示操作系统绕过本地的文件系统缓存。
'w' - 打开文件用于写入。如果文件不存在则创建文件,如果文件已存在则截断文件。
'wx' - 与 'w' 相似,但如果路径已存在则失败。
'w+' - 打开文件用于读取和写入。如果文件不存在则创建文件,如果文件已存在则截断文件。
'wx+' - 与 'w+' 相似,但如果路径已存在则失败。

底层接口

打开文件

异步打开

// fs.open
path <string> | <Buffer> | <URL>
flags <string> | <number> 参阅支持的文件系统标志。
mode <integer> 默认值: 0o666(可读写)。
callback <Function>
- err <Error>
- fd <integer>
var fs = require('fs')
fs.open('1.txt','r',function(err,fs){
console.log(err)
console.log(fs)
})

执行结果:

$ node 1.js
null
3

注意: 使用'rs+'模式不会使fs.open()进入同步阻塞调用。如果那是你想要的,则应该使用fs.openSync()

同步打开

// fs.openSync
path <string> | <Buffer> | <URL>
flags <string> | <number> 参阅支持的文件系统标志。
mode <integer> 默认值: 0o666。
返回: <number>
返回表示文件描述符的整数。
var fs = require('fs');
var result = fs.openSync('1.txt','r');
console.log(result);

执行结果:

$ node 1.js
3

读取文件

fd <integer> 从 fd 指定的文件中读取数据。
buffer <Buffer> | <TypedArray> | <DataView> 数据将写入的缓冲区。
offset <integer> buffer 中开始写入的偏移量
length <integer> 是一个整数,指定要读取的字节数
position <integer> 参数指定从文件中开始读取的位置。 如果 position 为 null,则从当前文件位置读取数据,并更新文件位置。 如果 position 是整数,则文件位置将保持不变。
callback <Function>
- err <Error>
- bytesRead <integer>
- buffer <Buffer>
var fs = require('fs');
fs.open('1.txt','r',function(err,fd){
if(err){
console.log('文件打开失败');
}else{
var bf = Buffer.alloc(5);
fs.read(fd,bf,0,3,null,function(err,len,buffer){
console.log(err);
console.log(len);
console.log(buffer);
})
}
});

执行结果:

$ node 1.js
null
3
<Buffer 68 65 6c 00 00>

同步读取

fd <integer>
buffer <Buffer> | <TypedArray> | <DataView>
offset <integer>
length <integer>
position <integer>
返回: <number>
返回 bytesRead 的数量。
var fs = require('fs');
var fd = fs.openSync('1.txt','r');
var bf = Buffer.alloc(5);
var result = fs.readSync(fd,bf,0,3,null);
console.log(result);

执行结果:

$ node 1.js
3

写入文件

fd <Integer>  文件标识
buffer <String> | <Buffer> 要将buffer中的数据写入到文件中
offset <Integer> buffer对象中要写入的数据的起始位置
length <Integer> length是一个整数,指定要写入的字节数
position <Integer> 指定从文件开始写入数据的位置的偏移量。 如果 typeof position !== 'number',则数据从当前位置写入
callback <Function> 回调有三个参数(err, written, buffer),其中written指定从buffer写入了多少字节

执行结果

$ node 1.js
null
3
<Buffer 74 65 73 74>

[注意]多次对同一文件使用fs.write且不等待回调,是不安全的。对于这种情况,强烈推荐使用 fs.createWriteStream  当我们要对打开的文件进行写操作的时候,打开文件的模式应该是读写模式

同步写入

fd <integer>
buffer <Buffer> | <TypedArray> | <DataView>
offset <integer>
length <integer>
position <integer>
返回: <number> 写入的字节数。
var fs = require('fs');
var fd = fs.openSync('1.txt','r+');
var bf = Buffer.alloc(5);
var result = fs.writeSync(fd,bf,0,3,null);
console.log(result);

执行结果:

$ node 1.js
3

关闭文件

fd - 通过 fs.open() 方法返回的文件描述符。
callback - 回调函数,没有参数。
var fs = require('fs');
fs.open('1.txt','r+',function(err,fd){
if(err){
console.log('文件打开失败');
}else{
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功");
});
}
});
$ node 1.js
文件关闭成功

同步关闭

var fs = require('fs');
var fd = fs.openSync('1.txt','r+');
fs.closeSync(fd);

文件操作

文件读取

同步读取

// fs.readFileSync
path <string> | <Buffer> | <URL>
options <string> | <Object>
encoding <string> 默认值: 'utf8'。
withFileTypes <boolean> 默认值: false。 返回: <string[]> | <Buffer[]> | <fs.Dirent[]>
var fs = require('fs');
var data; try{
data = fs.readFileSync('./1.txt', 'utf8');
console.log('文件内容: ' + data);
}catch(err){
console.error('读取文件出错: ' + err.message);
}

执行结果为:

$ node 1.js
文件内容: hello rock

异步读取

// fs.readFile
path <string> | <Buffer> | <URL>
options <string> | <Object>
- encoding <string> 默认值: 'utf8'。
- withFileTypes <boolean> 默认值: false。
callback <Function>
- err <Error>
- files <string[]> | <Buffer[]> | <fs.Dirent[]>
var fs = require('fs');

fs.readFile('./1.txt', 'utf8', function(err, data){
if(err){
return console.error('读取文件出错: ' + err.message);
}
console.log('文件内容: ' + data);
});

执行结果也为:

$ node 1.js
文件内容: hello rock

通过文件流读取

适合读取大文件

path <string> | <Buffer> | <URL>
options <string> | <Object>
- flags <string> 参阅支持的文件系统标志。默认值: 'r'。
- encoding <string> 默认值: null。
- fd <integer> 默认值: null。
- mode <integer> 默认值: 0o666。
- autoClose <boolean> 默认值: true。
- start <integer>
- end <integer> 默认值: Infinity。
- highWaterMark <integer> 默认值: 64 * 1024。
返回: <fs.ReadStream> 参阅[可读流]。
var fs = require('fs');
var readStream = fs.createReadStream('./1.txt', 'utf8'); readStream
.on('data', function(chunk) {
console.log('读取数据: ' + chunk);
})
.on('error', function(err){
console.log('出错: ' + err.message);
})
.on('end', function(){ // 没有数据了
console.log('没有数据了');
})
.on('close', function(){ // 已经关闭,不会再有事件抛出
console.log('已经关闭');
});

执行结果:

$ node 1.js
读取数据: hello rock
没有数据了
已经关闭

文件写入

异步写入

// fs.writeFile
file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。
data <string> | <Buffer> | <TypedArray> | <DataView>
options <Object> | <string>
- encoding <string> | <null> 默认值: 'utf8'。
- mode <integer> 默认值: 0o666。
- flag <string> 参阅支持的文件系统标志。默认值: 'w'。
callback <Function>
- err <Error></Error>
var fs = require('fs');
fs.writeFile('./1.txt', 'hello rock', 'utf8', function(err){
if(err) throw err;
console.log('文件写入成功');
});

执行结果:

$ node 1.js
文件写入成功

同步写入

// fs.writeFileSync
file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。
data <string> | <Buffer> | <TypedArray> | <DataView>
options <Object> | <string>
- encoding <string> | <null> 默认值: 'utf8'。
- mode <integer> 默认值: 0o666。
- flag <string> 参阅支持的文件系统标志。默认值: 'w'。 返回 undefined。
var fs = require('fs');
try{
fs.writeFileSync('./1.txt', 'hello rock', 'utf8');
console.log('文件写入成功');
}catch(err){
throw err;
}

执行结果:

$ node 1.js
文件写入成功

通过文件流写入

path <string> | <Buffer> | <URL>
options <string> | <Object>
- flags <string> 参阅支持的文件系统标志。默认值: 'w'。
- encoding <string> 默认值: 'utf8'。
- fd <integer> 默认值: null。
- mode <integer> 默认值: 0o666。
- autoClose <boolean> 默认值: true。
- start <integer>
返回: <fs.WriteStream> 参阅可写流。
var fs = require('fs');
var writeStream = fs.createWriteStream('./1.txt', 'utf8');
writeStream
.on('close', function(){ // 已经关闭,不会再有事件抛出
console.log('已经关闭');
});
writeStream.write('hello');
writeStream.write('rock');
writeStream.end('');

执行结果:

$ node 1.js
已经关闭

追加文件

file - 文件名或文件描述符。
data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(流) 对象。
options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'
callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
var fs = require('fs');
var filename = '1.txt';
fs.appendFile(filename,' world',function(err){
console.log(err);
})

执行结果

$ node 1.js
null

同步追加

var fs = require('fs');
var filename = '1.txt';
fs.appendFileSync(filename,' lalala');

删除文件

path - 文件路径。
callback - 回调函数,没有参数。
var fs = require('fs');
var filename = '1.txt';
fs.unlink(filename, function(err) {
if (err) {
return console.log('删除失败');
}
console.log("删除成功");
});

执行结果:

$ node 1.js
删除成功

同步删除

var fs = require('fs');
var filename = '1.txt';
fs.unlink(filename);

重命名

oldPath <String> | <Buffer>
newPath <String> | <Buffer>
callback <Function> 回调只有一个可能的异常参数
var fs = require('fs');
var filename = 'a.txt';
fs.rename(filename,'2.new.txt',function(err){
console.log(err);
})
$ node 1.js
null

同步重命名

var fs = require('fs');
var filename = '2.new.txt';
var result = fs.renameSync(filename,'a.txt');

文件信息

path <string> | <Buffer> | <URL>
options <Object>
bigint <boolean> 返回的 fs.Stats 对象中的数值是否应为 bigint 型。默认值: false。
callback <Function>
- err <Error>
- stats <fs.Stats>
var fs = require('fs');
var filename = 'a.txt';
fs.stat(filename,function(err,stats){
console.log(err);
console.log(stats);
});

执行结果

$ node 1.js
null
Stats {
dev: 163689085,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: undefined,
ino: 9007199254854088,
size: 0,
blocks: undefined,
atimeMs: 1562684836201.136,
mtimeMs: 1562684836201.136,
ctimeMs: 1562684998231.913,
birthtimeMs: 1562684836201.136,
atime: 2019-07-09T15:07:16.201Z,
mtime: 2019-07-09T15:07:16.201Z,
ctime: 2019-07-09T15:09:58.232Z,
birthtime: 2019-07-09T15:07:16.201Z }

stats类中的方法有

stats.isFile()  如果是文件返回 true,否则返回 false。
stats.isDirectory() 如果是目录返回 true,否则返回 false。
stats.isBlockDevice() 如果是块设备返回 true,否则返回 false。
stats.isCharacterDevice() 如果是字符设备返回 true,否则返回 false。
stats.isSymbolicLink() 如果是软链接返回 true,否则返回 false。
stats.isFIFO() 如果是FIFO,返回true,否则返回false。FIFO是UNIX中的一种特殊类型的命令管道。
stats.isSocket() 如果是 Socket 返回 true,否则返回 false。
var fs = require('fs');
var filename = 'a.txt';
fs.stat(filename,function(err,stats){
console.log(stats.isFile());//true
});

监听

filename <String> | <Buffer>
options <String> | <Object> 参数可选,如果options是一个字符串,则它指定了encoding。否则options应该以一个对象传入
persistent <Boolean> 指明如果文件正在被监视,进程是否应该继续运行。默认为true
recursive <Boolean> 指明是否全部子目录应该被监视,或只是当前目录。 适用于当一个目录被指定时,且只在支持的平台。默认为false
encoding <String> 指定用于传给监听器的文件名的字符编码。默认为'utf8'
listener <Function> 回调函数有两个参数 (eventType, filename)。 eventType可以是'rename'或'change',filename是触发事件的文件的名称
fs.watch('txt', (eventType, filename) => {
console.log(`事件类型是: ${eventType}`);
if (filename) {
console.log(`提供的文件名: ${filename}`);
} else {
console.log('未提供文件名');
}
});
var fs = require('fs');
var filename = '1.txt';
fs.watch(filename,function(eventType, _filename){
console.log(eventType);//change
if(_filename){
console.log(_filename + '发生了改变');//'1.txt发生了改变'
}else{
console.log('...');
} })

[注意]当一个文件出现或消失在一个目录里时,'rename'也会被触发

每天学点node系列-fs文件系统的更多相关文章

  1. 每天学点node系列-fs文件系统(续)

    理想如果不向现实做一点点屈服,那么理想也将归于尘土. 创建目录 异步创建目录 path<string> | <Buffer> | <URL> options < ...

  2. Node.js fs文件系统模块

    一.读取文件几个步骤 1.先引入fs文件系统模块 2.使用readfile 或 readFileSync 注意点:它们的回调函数有两个参数,第一个是err,第二个是data,得到的data是buffe ...

  3. 每天学点node系列-stream

    在编写代码时,我们应该有一些方法将程序像连接水管一样连接起来 -- 当我们需要获取一些数据时,可以去通过"拧"其他的部分来达到目的.这也应该是IO应有的方式. -- Doug Mc ...

  4. 每天学点node系列-http

    任何可以使用JavaScript来编写的应用,最终会由JavaScript编写.--Atwood's Law http模块概览 http模块主要用于创建http server服务,并且 支持更多特性 ...

  5. 每天学点node系列-zlib

    永不放弃,永不放弃又有两个原则,第一个原则是永不放弃,第二个原则就是:当你想放弃时回头看第一个原则. 概览 做过web性能优化的同学,对性能优化大杀器gzip应该不陌生.浏览器向服务器发起资源请求,比 ...

  6. Node.js:fs文件系统模块

    fs文件系统模块,这是一个非常重要的模块,对文件的操作都基于它.该模块的所有方法都有同步和异步两种方式,下面便介绍一下该模块的使用. 1.检测当前进程对文件的权限 使用fs.access(path[, ...

  7. node.js中fs文件系统模块的使用

    node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法 ...

  8. node.js常用的fs文件系统

    fs文件系统模块对于系统文件及目录进行一些读写操作. 模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync(). 异步的 ...

  9. node.js中常用的fs文件系统

    fs文件系统模块对于系统文件及目录进行一些读写操作. 模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync(). 异步的 ...

随机推荐

  1. C/S和B/S两种架构区别与优缺点分析

    C/S和B/S,是再普通不过的两种软件架构方式,都可以进行同样的业务处理,甚至也可以用相同的方式实现共同的逻辑.既然如此,为何还要区分彼此呢?那我们就来看看二者的区别和联系. 一.C/S 架构 1. ...

  2. 【C#】【WPF】如何读写app.config文件

    WPF生成的项目中会有.exe.config.一般是系统默认配置的 格式是xml格式,C#的项目可以直接读写这些文件.方法代码如下. public static string GetConnectio ...

  3. 【转】微信退款时候报”请求被中止: 未能创建 SSL/TLS 安全通道“或”The request was aborted: Could not create SSL/TLS secure channel“的错误

    退款测试在我本机测试一切都是正常的,但是发布到了服务器就报这样的一个错啦 但是无论百度或者google或者bing,你能够搜索到的结果都很类似,综合起来就是加这样一些代码,如下 ServicePoin ...

  4. nginx 负载均衡,多站点共享Session

    原文:nginx 负载均衡,多站点共享Session nginx 负载均衡,多站点共享Session 多站点共享Session常见的作法有: 使用.net自动的状态服务(Asp.net State S ...

  5. Ptypes一个开源轻量级的c++库,包括对一些I/O操作、网络通信、多线程和异常处理的封装

    C++开源项目入门级:Ptypes    Ptypes一个开源轻量级的c++库,包括对一些I/O操作.网络通信.多线程和异常处理的封装.虽然代码有限,包括的内容不少,麻雀虽小,五脏俱全.    提高: ...

  6. SpringMVC使用MultipartFile文件上传,多文件上传,带参数上传

    一.配置SpringMVC 二.单文件与多文件上传 三.多文件上传 四.带参数上传 一.配置SpringMVC 在spring.xml中配置: <!-- springmvc文件上传需要配置的节点 ...

  7. Debug监视器(监视运行期程序通过API函数OutputDebugString输出的字符串)

    http://download.csdn.net/detail/zswang/207199

  8. 项目集成dubbo

    dubbo 用户指南: http://dubbo.io/User+Guide-zh.htm 开发指南:http://dubbo.io/Developer+Guide-zh.htm#DeveloperG ...

  9. WPF全局异常捕获

    跟着<WPF专业编程开发指南>这书打的代码的,自己在正式项目中测试通过,可以抓取到全局的异常,用的log4net来记录日志 核心代码: 写在App.xaml.cs中 /// <sum ...

  10. The Portable Executable File Format from Top to Bottom(每个结构体都非常清楚)

    The Portable Executable File Format from Top to Bottom Randy KathMicrosoft Developer Network Technol ...