目录
愿得一心人,白头不相离。
本文为本人略读官网文档后的大略笔记,实在不适合他人阅读。
前言
Node.js提供一组类似 UNIX(POSIX)标准的文件操作API。
引入
var fs = require("fs")
1. 异步和同步
Node.js文件系统模块(fs模块)中的方法均有异步和同步2种
同步方法
带有Sync的方法都是同步方法
异步方法(建议使用)
函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)
- 例1
input.txt
hello world
hello cx,,,
test.js
var fs = require("fs");
// 异步读取
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取: " + data.toString());
});
// 同步读取
var data = fs.readFileSync('input.txt');
console.log("同步读取: " + data.toString());
console.log("程序执行完毕。");
node test.js
终端输出
同步读取: hello world
hello cx,,,
程序执行完毕。
异步读取: hello world
hello cx,,,
2. 打开文件
异步
fs.open(path, flags[, mode], callback)
参数说明
1. path
文件路径
2. flags
文件打开的行为
3. mode
设置文件模式(权限),文件创建默认权限为 0666(可读,可写)。
4. callback
回调函数,带有两个参数如:callback(err, fd)。
flag | 说明 |
---|---|
r | 以读取模式打开文件。如果文件不存在抛出异常。 |
r+ | 以读写模式打开文件。如果文件不存在抛出异常。 |
rs | 以同步的方式读取文件。 |
rs+ | 以同步的方式读取和写入文件。 |
w | 以写入模式打开文件,如果文件不存在则创建。 |
wx | 类似 'w',但是如果文件路径存在,则文件写入失败。 |
w+ | 以读写模式打开文件,如果文件不存在则创建。 |
wx+ | 类似 'w+', 但是如果文件路径存在,则文件读写失败。 |
a | 以追加模式打开文件,如果文件不存在则创建。 |
ax | 类似 'a', 但是如果文件路径存在,则文件追加失败。 |
a+ | 以读取追加模式打开文件,如果文件不存在则创建。 |
ax+ | 类似 'a+', 但是如果文件路径存在,则文件读取追加失败。 |
- 例1
test.js
var fs = require("fs");
// 异步打开文件
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
});
node test.js
准备打开文件!
文件打开成功!
3. 获取文件信息
异步
fs.stat(path, callback)
参数说明
1. path
文件路径
2. callback
回调函数,带有两个参数如:callback(err, stats)。stats 是 fs.Stats 对象,包含文件信息
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) |
- 例1
test.js
var fs = require("fs");
console.log("准备打开文件!");
fs.stat('input.txt', function (err, stats) {
if (err) {
return console.error(err);
}
console.log(stats);
console.log("读取文件信息成功!");
// 检测文件类型
console.log("是否为文件(isFile) ? " + stats.isFile());
console.log("是否为目录(isDirectory) ? " + stats.isDirectory());
});
node test.js
准备打开文件!
Stats {
dev: 16777220,
mode: 33188,
nlink: 1,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 12936007339,
size: 23,
blocks: 8,
atimeMs: 1586078630059.4458,
mtimeMs: 1586078311736.4148,
ctimeMs: 1586078311736.4148,
birthtimeMs: 1583913497259.461,
atime: 2020-04-05T09:23:50.059Z,
mtime: 2020-04-05T09:18:31.736Z,
ctime: 2020-04-05T09:18:31.736Z,
birthtime: 2020-03-11T07:58:17.259Z
}
读取文件信息成功!
是否为文件(isFile) ? true
是否为目录(isDirectory) ? false
4. 写入文件
异步
// 如果文件存在,会覆盖旧的文件内容
fs.writeFile(file, data[, options], callback)
参数说明
1. file
文件名或文件描述符。
2. data
要写入文件的数据,可以是 String(字符串) 或 Buffer(缓冲) 对象。
3. options
该参数是一个对象,包含 {encoding, mode, flag}。
默认编码为 utf8, 模式为 0666 , flag 为 'w'
4. callback
回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
- 例1
test.js
var fs = require("fs");
console.log("准备写入文件");
fs.writeFile('input.txt', '我是通 过fs.writeFile 写入文件的内容', function(err) {
if (err) {
return console.error(err);
}
console.log("数据写入成功!");
console.log("--------我是分割线-------------")
console.log("读取写入的数据!");
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取文件数据: " + data.toString());
});
});
node test.js(运行完毕后查看input.txt,内容已被更换)
准备写入文件
数据写入成功!
--------我是分割线-------------
读取写入的数据!
异步读取文件数据: 我是通 过fs.writeFile 写入文件的内容
5. 读取文件
异步
fs.read(fd, buffer, offset, length, position, callback)
参数说明
1. fd
通过 fs.open() 方法返回的文件描述符。
2. buffer
数据写入的缓冲区。
3. offset
缓冲区写入的写入偏移量。
4. length
要从文件中读取的字节数。
5. position
文件读取的起始位置
如果 position 的值为 null,则会从当前文件指针的位置读取。
6. callback
回调函数,有三个参数err, bytesRead, buffer
err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。
- 例1
test.js
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开已存在的文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件:");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
console.log(bytes + " 字节被读取");
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
});
});
node test.js
准备打开已存在的文件!
文件打开成功!
准备读取文件:
47 字节被读取
hello world
hello cx,,,
6. 关闭文件
异步
fs.close(fd, callback)
参数说明
1. fd
通过 fs.open() 方法返回的文件描述符。
2. callback
回调函数,没有参数。
- 例1
test.js
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件!");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功");
});
});
});
node test.js
准备打开文件!
文件打开成功!
准备读取文件!
hello world
hello cx,,,
文件关闭成功
7. 截取文件
异步
fs.ftruncate(fd, len, callback)
参数说明
1. fd
通过 fs.open() 方法返回的文件描述符。
2. len
文件内容截取的长度。
3. callback
回调函数,没有参数
- 例1
test.js
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("截取10字节内的文件内容,超出部分将被去除。");
// 截取文件
fs.ftruncate(fd, 10, function(err){
if (err){
console.log(err);
}
console.log("文件截取成功。");
console.log("读取相同的文件");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功!");
});
});
});
});
node test.js
准备打开文件!
文件打开成功!
截取10字节内的文件内容,超出部分将被去除。
文件截取成功。
读取相同的文件
hello worl
文件关闭成功!
8. 删除文件
异步
fs.unlink(path, callback)
参数说明
1. path
文件路径。
2. callback
回调函数,没有参数。
- 例1
test.js
var fs = require("fs");
console.log("准备删除文件!");
fs.unlink('input.txt', function(err) {
if (err) {
return console.error(err);
}
console.log("文件删除成功!");
});
node test.js
准备删除文件!
文件删除成功
9. 创建目录
fs.mkdir(path[, options], callback)
参数说明
1. path
文件路径。
2. options 参数可以是:
recursive - 是否以递归的方式创建目录,默认为 false。
mode - 设置目录权限,默认为 0777。
3. callback
回调函数,没有参数。
- 例1
test.js
var fs = require("fs");
// src目录必须存在
console.log("创建目录 src/test/");
fs.mkdir("src/test",function(err){
if (err) {
return console.error(err);
}
console.log("目录创建成功。");
});
node test.js(运行成功后在src目录下创建了test目录)
创建目录 src/test/
目录创建成功。
10. 读取目录
fs.readdir(path, callback)
参数说明
1. path
文件路径。
2. callback
回调函数,回调函数带有两个参数err, files,
err 为错误信息,files 为 目录下的文件数组列表。
- 例1
var fs = require("fs");
console.log("查看 src 目录");
fs.readdir("src/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
node test.js
查看 src 目录
test
11. 删除目录
fs.rmdir(path, callback)
参数说明
1. path
文件路径
2. callback
回调函数
- 例1
test.js
var fs = require("fs");
// 执行前创建一个空的 src/test 目录
console.log("准备删除目录 /tmp/test");
fs.rmdir("src/test",function(err){
if (err) {
return console.error(err);
}
console.log("读取 src 目录");
fs.readdir("src/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
});
node test.js
准备删除目录 /tmp/test
读取 src 目录
方法 | 异步/同步 | 说明 |
---|---|---|
fs.rename(oldPath, newPath, callback) | 异步 | rename().回调函数没有参数,但可能抛出异常。 |
fs.ftruncate(fd, len, callback) | 异步 | ftruncate().回调函数没有参数,但可能抛出异常。 |
fs.ftruncateSync(fd, len) | 同步 | ftruncate() |
fs.truncate(path, len, callback) | 异步 | truncate().回调函数没有参数,但可能抛出异常。 |
fs.truncateSync(path, len) | 同步 | truncate() |
fs.chown(path, uid, gid, callback) | 异步 | chown().回调函数没有参数,但可能抛出异常。 |
fs.chownSync(path, uid, gid) | 同步 | chown() |
fs.fchown(fd, uid, gid, callback) | 异步 | fchown().回调函数没有参数,但可能抛出异常。 |
fs.fchownSync(fd, uid, gid) | 同步 | fchown() |
fs.lchown(path, uid, gid, callback) | 异步 | lchown().回调函数没有参数,但可能抛出异常。 |
fs.lchownSync(path, uid, gid) | 同步 | lchown() |
fs.chmod(path, mode, callback) | 异步 | chmod().回调函数没有参数,但可能抛出异常。 |
fs.chmodSync(path, mode) | 同步 | chmod(). |
fs.fchmod(fd, mode, callback) | 异步 | fchmod().回调函数没有参数,但可能抛出异常。 |
fs.fchmodSync(fd, mode) | 同步 | fchmod(). |
fs.lchmod(path, mode, callback) | 异步 | lchmod().回调函数没有参数,但可能抛出异常。Only available on Mac OS X. |
fs.lchmodSync(path, mode) | 同步 | lchmod(). |
fs.stat(path, callback) | 异步 | stat(). 回调函数有两个参数 err, stats,stats 是 fs.Stats 对象。 |
fs.lstat(path, callback) | 异步 | lstat(). 回调函数有两个参数 err, stats,stats 是 fs.Stats 对象。 |
fs.fstat(fd, callback) | 异步 | fstat(). 回调函数有两个参数 err, stats,stats 是 fs.Stats 对象。 |
fs.statSync(path) | 同步 | stat(). 返回 fs.Stats 的实例。 |
fs.lstatSync(path) | 同步 | lstat(). 返回 fs.Stats 的实例。 |
fs.fstatSync(fd) | 同步 | fstat(). 返回 fs.Stats 的实例。 |
fs.link(srcpath, dstpath, callback) | 异步 | link().回调函数没有参数,但可能抛出异常。 |
fs.linkSync(srcpath, dstpath) | 同步 | link(). |
fs.symlink(srcpath, dstpath[, type], callback) | 异步 | symlink().回调函数没有参数,但可能抛出异常。 type 参数可以设置为 'dir', 'file', 或 'junction' (默认为 'file') 。 |
fs.symlinkSync(srcpath, dstpath[, type]) | 同步 | symlink(). |
fs.readlink(path, callback) | 异步 | readlink(). 回调函数有两个参数 err, linkString。 |
fs.realpath(path[, cache], callback) | 异步 | realpath(). 回调函数有两个参数 err, resolvedPath。 |
fs.realpathSync(path[, cache]) | 同步 | realpath()。返回绝对路径。 |
fs.unlink(path, callback) | 异步 | unlink().回调函数没有参数,但可能抛出异常。 |
fs.unlinkSync(path) | 同步 | unlink(). |
fs.rmdir(path, callback) | 异步 | rmdir().回调函数没有参数,但可能抛出异常。 |
fs.rmdirSync(path) | 同步 | rmdir(). |
fs.mkdir(path[, mode], callback) | 异步 | mkdir(2).回调函数没有参数,但可能抛出异常。 访问权限默认为 0777。 |
fs.mkdirSync(path[, mode]) | 同步 | mkdir(). |
fs.readdir(path, callback) | 异步 | readdir(3). 读取目录的内容。 |
fs.readdirSync(path) | 同步 | readdir().返回文件数组列表。 |
fs.close(fd, callback) | 异步 | close().回调函数没有参数,但可能抛出异常。 |
fs.closeSync(fd) | 同步 | close(). |
fs.open(path, flags[, mode], callback) | 异步 | 打开文件。 |
fs.openSync(path, flags[, mode]) | 同步 | version of fs.open(). |
fs.utimes(path, atime, mtime, callback) | 异步 | |
fs.utimesSync(path, atime, mtime) | 同步 | 修改文件时间戳,文件通过指定的文件路径。 |
fs.futimes(fd, atime, mtime, callback) | 异步 | |
fs.futimesSync(fd, atime, mtime) | 同步 | 修改文件时间戳,通过文件描述符指定。 |
fs.fsync(fd, callback) | 异步 | fsync.回调函数没有参数,但可能抛出异常。 |
fs.fsyncSync(fd) | 同步 | fsync. |
fs.write(fd, buffer, offset, length[, position], callback) | 异步 | 将缓冲区内容写入到通过文件描述符指定的文件。 |
fs.write(fd, data[, position[, encoding]], callback) | 异步 | 通过文件描述符 fd 写入文件内容。 |
fs.writeSync(fd, buffer, offset, length[, position]) | 同步 | fs.write()。 |
fs.writeSync(fd, data[, position[, encoding]]) | 同步 | fs.write(). |
fs.read(fd, buffer, offset, length, position, callback) | 异步 | 通过文件描述符 fd 读取文件内容。 |
fs.readSync(fd, buffer, offset, length, position) | 同步 | fs.read. |
fs.readFile(filename[, options], callback) | 异步 | 读取文件内容。 |
fs.readFileSync(filename[, options]) | 同步 | |
fs.writeFile(filename, data[, options], callback) | 异步 | 写入文件内容。 |
fs.writeFileSync(filename, data[, options]) | 同步 | fs.writeFile。 |
fs.appendFile(filename, data[, options], callback) | 异步 | 追加文件内容。 |
fs.appendFileSync(filename, data[, options]) | 同步 | version of fs.appendFile. |
fs.watchFile(filename[, options], listener) | 查看文件的修改。 | |
fs.unwatchFile(filename[, listener]) | 停止查看 filename 的修改。 | |
fs.watch(filename[, options][, listener]) | 查看 filename 的修改,filename 可以是文件或目录。返回 fs.FSWatcher 对象。 | |
fs.exists(path, callback) | 检测给定的路径是否存在。 | |
fs.existsSync(path) | 同步 | fs.exists. |
fs.access(path[, mode], callback) | 测试指定路径用户权限。 | |
fs.accessSync(path[, mode]) | 同步版的 fs.access。 | |
fs.createReadStream(path[, options]) | 返回ReadStream 对象。 | |
fs.createWriteStream(path[, options]) | 返回 WriteStream 对象。 | |
fs.symlink(srcpath, dstpath[, type], callback) | 异步 | symlink().回调函数没有参数,但可能抛出异常。 |
12. Stream(流)
Stream 是一个抽象接口,Node 中有很多对象实现了这个接口。
例如,对http服务器发起请求的request对象就是一个Stream,还有stdout(标准输出)。
四种流类型:
1. Readable
可读操作。
2. Writable
可写操作。
3. Duplex
可读可写操作.
4. Transform
写入数据,然后读出结果
所有的 Stream 对象都是 EventEmitter 的实例。
常用的事件有:
1. data
当有数据可读时触发。
2. end
没有更多的数据可读时触发。
3. error
发生错误时(接收和写入过程中)触发。
4. finish
结束时(所有数据已被写入到底层系统)触发。
- 例1(读取数据)
test.js
var fs = require("fs");
var data = '';
// 创建可读流
var readerStream = fs.createReadStream('input.txt');
// 设置编码为 utf8。
readerStream.setEncoding('UTF8');
// 处理流事件 --> data, end, and error
readerStream.on('data', function(chunk) {
data += chunk;
});
readerStream.on('end',function(){
console.log(data);
});
readerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
node test.js
程序执行完毕
Hello World!
Hello cx,,,
- 例2(写入数据)
test.js
var fs = require("fs");
var data = 'hello world。hello cx,,,';
// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');
// 标记文件末尾
writerStream.end();
// 处理流事件 --> data, end, and error
writerStream.on('finish', function() {
console.log("写入完成。");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
node test.js(会生成output.txt文件)
程序执行完毕
写入完成。
- 管道流
管道提供了一个输出流到输入流的机制。
通常我们用于从一个流中获取数据并将数据传递到另外一个流中。
例1
var fs = require("fs");
// 创建一个可读流
var readerStream = fs.createReadStream('input.txt');
// 创建一个可写流
var writerStream = fs.createWriteStream('output.txt');
// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中
readerStream.pipe(writerStream);
console.log("程序执行完毕");
===================== 会将input.txt的内容复制到output.txt
程序执行完毕
- 链式流
链式是通过连接输出流到另外一个流并创建多个流操作链的机制。
链式流一般用于管道操作。
var fs = require("fs");
var zlib = require('zlib');
// 压缩 input.txt 文件为 input.txt.gz
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log("文件压缩完成。");
=====================会生成一个 input.txt.gz压缩文件
文件压缩完成。
var fs = require("fs");
var zlib = require('zlib');
// 解压 input.txt.gz 文件为 input.txt
fs.createReadStream('input.txt.gz')
.pipe(zlib.createGunzip())
.pipe(fs.createWriteStream('fs.txt'));
console.log("文件解压完成。");
=====================会生成一个fs.txt文件
文件解压完成。