:文件系统(fs 模块))
一、fs 模块概述Node.js 的文件系统模块fs 模块提供了丰富的 API用于读取、写入、删除文件以及执行其他文件系统操作。fs 模块既支持同步方法也支持异步方法使得开发者可以根据具体需求选择合适的方式来处理文件操作。二、导入 fs 模块var fs require(fs);三、异步和同步Node.js 文件系统fs 模块模块中的方法均有异步和同步版本例如读取文件内容的函数有异步的fs.readFile()和同步的fs.readFileSync()。异步的方法函数最后一个参数为回调函数回调函数的第一个参数包含了错误信息error。建议使用异步方法比起同步异步方法性能更高速度更快而且没有阻塞。四、基本文件操作文件读取创建example.txt文件内容如下地址www.chenmbyte.com创建file.js文件var fs require(fs); // 异步读取 fs.readFile(example.txt, function(err, data) { if (err) { return console.error(err); } console.log(异步读取: data.toString()); }); // 同步读取 var data fs.readFileSync(example.txt); console.log(同步读取: data.toString()); console.log(程序执行完毕。);执行结果$ node file.js 同步读取: 地址www.chenmbyte.com 程序执行完毕。 异步读取: 地址www.chenmbyte.com写入文件异步写入fs.writeFile(example.txt, Hello, World!, (err) { if (err) { console.error(Error writing file:, err); return; } console.log(File written successfully); });同步写入try { fs.writeFileSync(example.txt, Hello, World!); console.log(File written successfully); } catch (err) { console.error(Error writing file:, err); }追加内容到文件异步追加fs.appendFile(example.txt, \nAppending some text, (err) { if (err) { console.error(Error appending to file:, err); return; } console.log(Text appended successfully); });同步追加try { fs.appendFileSync(example.txt, \nAppending some text); console.log(Text appended successfully); } catch (err) { console.error(Error appending to file:, err); }删除文件异步删除fs.unlink(example.txt, (err) { if (err) { console.error(Error deleting file:, err); return; } console.log(File deleted successfully); });同步删除try { fs.unlinkSync(example.txt); console.log(File deleted successfully); } catch (err) { console.error(Error deleting file:, err); }五、目录操作创建目录异步创建fs.mkdir(new_directory, (err) { if (err) { console.error(Error creating directory:, err); return; } console.log(Directory created successfully); });同步创建try { fs.mkdirSync(new_directory); console.log(Directory created successfully); } catch (err) { console.error(Error creating directory:, err); }递归创建目录fs.mkdir(/tmp/a/apple, { recursive: true }, (err) { if (err) throw err; console.log(Directory created recursively); });读取目录内容异步读取fs.readdir(new_directory, (err, files) { if (err) { console.error(Error reading directory:, err); return; } console.log(Directory contents:, files); });同步读取try { const files fs.readdirSync(new_directory); console.log(Directory contents:, files); } catch (err) { console.error(Error reading directory:, err); }删除目录fs.rmdir(/tmp/test, (err) { if (err) { return console.error(err); } console.log(Directory deleted successfully); });六、检查文件或目录是否存在异步检查fs.access(example.txt, fs.constants.F_OK, (err) { if (err) { console.log(File does not exist); } else { console.log(File exists); } });同步检查try { fs.accessSync(example.txt, fs.constants.F_OK); console.log(File exists); } catch (err) { console.log(File does not exist); }七、文件流文件流可以用于高效地读取和写入大文件而不会一次性将整个文件加载到内存中。读取文件流const fs require(fs); const readableStream fs.createReadStream(large_file.txt, utf8); readableStream.on(data, (chunk) { console.log(Received chunk:, chunk); }); readableStream.on(end, () { console.log(No more data.); });写入文件流const fs require(fs); const writableStream fs.createWriteStream(output.txt); writableStream.write(Hello, ); writableStream.write(World!\n); writableStream.end(); writableStream.on(finish, () { console.log(All writes are now complete.); });八、获取文件统计信息可以使用fs.stat或fs.lstat获取文件或目录的统计信息。异步获取统计信息fs.stat(example.txt, (err, stats) { if (err) { console.error(Error getting stats:, err); return; } console.log(Is file?, stats.isFile()); console.log(Is directory?, stats.isDirectory()); console.log(Size:, stats.size); });同步获取统计信息try { const stats fs.statSync(example.txt); console.log(Is file?, stats.isFile()); console.log(Is directory?, stats.isDirectory()); console.log(Size:, stats.size); } catch (err) { console.error(Error getting stats:, err); }stats 类方法方法描述stats.isFile()如果是文件返回true否则返回falsestats.isDirectory()如果是目录返回true否则返回falsestats.isBlockDevice()如果是块设备返回true否则返回falsestats.isCharacterDevice()如果是字符设备返回true否则返回falsestats.isSymbolicLink()如果是软链接返回true否则返回falsestats.isFIFO()如果是 FIFO 返回true否则返回falsestats.isSocket()如果是 Socket 返回true否则返回false示例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()); });九、打开、读取和关闭文件低级操作打开文件var fs require(fs); console.log(准备打开文件); fs.open(input.txt, r, function(err, fd) { if (err) { return console.error(err); } console.log(文件打开成功); });flags 参数说明Flag描述r以只读模式打开文件文件必须存在r以读写模式打开文件文件必须存在w以只写模式打开文件不存在则创建存在则截断w以读写模式打开文件不存在则创建存在则截断a以追加模式打开文件不存在则创建a以读取和追加模式打开文件不存在则创建读取文件使用文件描述符var fs require(fs); var buf 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()); } }); });关闭文件fs.close(fd, function(err) { if (err) { console.log(err); } console.log(文件关闭成功); });十、截取文件var fs require(fs); 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(文件关闭成功); }); }); }); });十一、文件模块方法参考手册序号方法 描述1fs.rename(oldPath, newPath, callback)- 重命名文件2fs.ftruncate(fd, len, callback)- 截取文件3fs.truncate(path, len, callback)- 截取文件4fs.chown(path, uid, gid, callback)- 更改文件所有权5fs.fchown(fd, uid, gid, callback)- 通过文件描述符更改所有权6fs.lchown(path, uid, gid, callback)- 更改符号链接的所有权7fs.chmod(path, mode, callback)- 更改文件权限8fs.fchmod(fd, mode, callback)- 通过文件描述符更改权限9fs.lchmod(path, mode, callback)- 更改符号链接权限10fs.stat(path, callback)- 获取文件统计信息11fs.lstat(path, callback)- 获取符号链接统计信息12fs.fstat(fd, callback)- 通过文件描述符获取统计信息13fs.link(srcpath, dstpath, callback)- 创建硬链接14fs.symlink(srcpath, dstpath[, type], callback)- 创建符号链接15fs.readlink(path, callback)- 读取符号链接16fs.realpath(path[, cache], callback)- 获取绝对路径17fs.unlink(path, callback)- 删除文件18fs.rmdir(path, callback)- 删除目录19fs.mkdir(path[, mode], callback)- 创建目录20fs.readdir(path, callback)- 读取目录内容21fs.close(fd, callback)- 关闭文件22fs.open(path, flags[, mode], callback)- 打开文件23fs.utimes(path, atime, mtime, callback)- 修改文件时间戳24fs.futimes(fd, atime, mtime, callback)- 通过文件描述符修改时间戳25fs.fsync(fd, callback)- 同步文件数据到磁盘26fs.write(fd, buffer, offset, length[, position], callback)- 写入缓冲区到文件27fs.write(fd, data[, position[, encoding]], callback)- 写入数据到文件28fs.read(fd, buffer, offset, length, position, callback)- 从文件读取数据29fs.readFile(filename[, options], callback)- 异步读取文件内容30fs.writeFile(filename, data[, options], callback)- 异步写入文件内容31fs.appendFile(filename, data[, options], callback)- 异步追加文件内容32fs.watchFile(filename[, options], listener)- 监听文件修改33fs.unwatchFile(filename[, listener])- 停止监听文件修改34fs.watch(filename[, options][, listener])- 监听文件或目录修改35fs.exists(path, callback)- 检测路径是否存在已废弃36fs.access(path[, mode], callback)- 测试用户权限37fs.createReadStream(path[, options])- 创建可读流38fs.createWriteStream(path[, options])- 创建可写流十二、本章小结操作异步方法同步方法读取文件fs.readFile()fs.readFileSync()写入文件fs.writeFile()fs.writeFileSync()追加文件fs.appendFile()fs.appendFileSync()删除文件fs.unlink()fs.unlinkSync()创建目录fs.mkdir()fs.mkdirSync()读取目录fs.readdir()fs.readdirSync()删除目录fs.rmdir()fs.rmdirSync()获取状态fs.stat()fs.statSync()检查存在fs.access()fs.accessSync()文件流fs.createReadStream()/fs.createWriteStream()-提示在实际开发中推荐使用异步方法以避免阻塞事件循环。对于大文件处理应优先使用流Stream来减少内存占用。fs.promisesAPI 提供了基于 Promise 的异步方法可以与async/await配合使用使代码更加清晰。