Node系列 · Node基础:文件 I/O
Node系列 · Node基础文件 I/ONode 的文件 I/O 几乎全靠fs模块。它同一份能力提供三套 API同步 / 异步回调 / Promise混用会产生事件循环被阻塞或回调金字塔问题。理解三者的取舍就能写好所有 Node 文件操作。一、fs 模块的三套 API同一个操作readFilefs提供三种写法风格函数返回阻塞主线程同步fs.readFileSync()数据 / 抛异常✅ 阻塞异步回调fs.readFile(cb)undefined / 通过 cb(err, data) 返回❌ 非阻塞Promisefs.promises.readFile()Promisedata / reject(err)❌ 非阻塞1.1 同步 APIconst fs require(node:fs); try { const data fs.readFileSync(./config.json, utf-8); console.log(JSON.parse(data)); } catch (err) { console.error(读取失败:, err.message); }1.2 异步回调 APIconst fs require(node:fs); fs.readFile(./config.json, utf-8, (err, data) { if (err) { console.error(读取失败:, err.message); return; } console.log(JSON.parse(data)); });回调第一个参数永远是err这是 Node 的错误优先回调约定。1.3 Promise API推荐const fs require(node:fs/promises); async function loadConfig() { try { const data await fs.readFile(./config.json, utf-8); return JSON.parse(data); } catch (err) { console.error(读取失败:, err.message); throw err; } } loadConfig().then((cfg) console.log(cfg));::: tip默认用 Promise 版本。它和 async/await 配合最自然错误用 try/catch 捕获与同步代码视觉上接近。同步版本只适合启动期必须串行的场景如读取配置文件初始化回调风格已基本被淘汰。:::二、读写文件2.1readFile完整签名// 异步 Promise 版 const buf await fs.readFile(path, options); // options 可以是 // string → utf-8 / hex / base64 / latin1 / ascii // object → { encoding, flag } // 省略 → 返回 Buffer不自动转字符串 const text await fs.readFile(./README.md, utf-8); // string const bytes await fs.readFile(./image.png); // Buffer2.2writeFile完整签名await fs.writeFile(file, data, options); // data 可以是 // string → 按 encoding 写入 // Buffer → 字节写入 // TypedArray / DataView → 字节写入 await fs.writeFile(./out.txt, hello\n, utf-8); await fs.writeFile(./out.bin, Buffer.from([0xff, 0xfe]));writeFile默认覆盖整个文件。要追加内容用appendFileawait fs.appendFile(./access.log, ${new Date().toISOString()} GET /\n);::: warningwriteFile不存在会创建存在会覆盖。对重要文件先用fs.access检查或直接用追加模式aflag更安全。:::2.3 常用 flag 一览flag含义r只读默认w写入不存在则创建存在则清空a追加不存在则创建r读写不存在则报错w读写不存在则创建存在则清空ax追加文件已存在则失败用于独占创建场景避免并发覆盖三、文件描述符File Descriptoropen/read/close三个底层调用组合出打开文件 → 读 N 字节 → 关闭的精细控制const fs require(node:fs/promises); const fd await fs.open(./big.txt, r); try { const buf Buffer.alloc(1024); // 1KB 缓冲区 let pos 0; while (true) { const { bytesRead } await fd.read(buf, 0, 1024, pos); if (bytesRead 0) break; process.stdout.write(buf.subarray(0, bytesRead)); pos bytesRead; } } finally { await fd.close(); }什么时候用 fd 而不是readFile场景推荐整个文件能装入内存readFile简洁大文件GB 级别流式处理createReadStream第 7 章部分读取读头 1KB 看 magic numberfd.read(buf, 0, len, position)频繁读小块 需要 seekfd四、文件信息查询查询文件元信息大小、时间戳、类型用fs.statconst fs require(node:fs/promises); const stats await fs.stat(./config.json); stats.isFile(); // 是否普通文件 stats.isDirectory(); // 是否目录 stats.size; // 字节数 stats.atime; // 上次访问 stats.mtime; // 上次修改内容 stats.ctime; // 上次修改元数据权限等 stats.birthtime; // 创建时间不保证可用 stats.atimeMs; // 毫秒时间戳用于计算fs.stat跟随符号链接要查链接本身用fs.lstat。五、目录操作目录的创建、读取、重命名、删除由一组 API 承担const fs require(node:fs/promises); // 创建recursive: true 等价于 mkdir -p await fs.mkdir(./a/b/c, { recursive: true }); // 读取目录条目 const entries await fs.readdir(./src); // entries 是 string[]Node 20 可加 { withFileTypes: true } 拿到 Dirent[] // 删除recursive: true 才能删非空目录Node 14.14 await fs.rm(./a, { recursive: true, force: true }); // 重命名 / 移动 await fs.rename(./old.txt, ./new.txt); // 读目录 过滤 const jsFiles (await fs.readdir(./src)) .filter((f) f.endsWith(.js));六、文件路径处理文件 I/O 几乎总要配合path模块避免字符串拼接const fs require(node:fs/promises); const path require(node:path); // ❌ 错误直接拼 const filePath __dirname /config/ filename; // ✅ 正确path.join const filePath path.join(__dirname, config, filename); // ✅ 跨平台os.homedir() path.join const userConfig path.join(os.homedir(), .myapp, config.json); // ✅ 读取 package.json 同目录的相对路径文件 const pkgDir path.dirname(require.resolve(./package.json));七、错误处理文件操作的错误类型固定可枚举常见的err.codecode含义ENOENT文件 / 目录不存在EACCES权限不足EISDIR当成文件打开目录ENOTDIR当成目录进入文件EEXIST文件已存在创建时EMFILE打开的文件描述符过多const fs require(node:fs/promises); async function readConfig() { try { return await fs.readFile(./config.json, utf-8); } catch (err) { if (err.code ENOENT) { // 配置文件不存在是预期情况用默认值 return {}; } if (err.code EACCES) { throw new Error(配置目录无读取权限); } throw err; // 其他错误继续上抛 } }::: tip不要吞掉错误码就 throw 一个字符串。保留err.code方便上游根据类型决策如ENOENT走默认配置EACCES走错误提示。:::八、并发读写同一文件多个fs调用并发操作同一文件Node 不保证原子性。例如两个writeFile并发后写的覆盖先写的且中间状态可能损坏文件// ❌ 危险两个 writeFile 并发 await Promise.all([ fs.writeFile(log.txt, A), fs.writeFile(log.txt, B), ]); // 结果不可预测可能是 A、B也可能是 BA 或损坏 // ✅ 方案 1用 appendFile追加模式POSIX 保证原子 await Promise.all([ fs.appendFile(log.txt, A), fs.appendFile(log.txt, B), ]); // ✅ 方案 2串行必要时 await fs.writeFile(log.txt, A); await fs.writeFile(log.txt, B);对大文件或频繁更新的场景文件 I/O 也不适合用 SQLite / Redis / 专门的日志库pino 日志聚合替代。九、文件锁Node没有内置文件锁。需要互斥时场景方案单进程内await串行调用 /fs.promises的串行队列多进程间proper-lockfile包分布式Redis / Zookeeper / etcd十、性能与最佳实践场景推荐反例启动期读配置readFileSync必须阻塞到读完才能继续用异步版本然后.then启动请求处理中读文件fs.promises.readFilereadFileSync阻塞事件循环大文件createReadStream见第 7 章readFile一次性读入内存批量小文件Promise.all([...])并发串行 await延迟叠加错误处理按err.code分支catch (e) { /* 静默 */ }路径拼接path.join字符串十一、小结fs提供同步 / 异步回调 / Promise 三套 API默认用 PromisereadFile/writeFile是最简单的读写大文件用createReadStream写文件注意 flagw覆盖、a追加、ax独占创建错误处理按err.code分支ENOENT/EACCES/EMFILE等并发写同一文件无原子保证要串行或用追加模式路径处理永远走path模块不要直接拼字符串

相关新闻

降重总失败?2026年老学长总结的降重正确姿势

降重总失败?2026年老学长总结的降重正确姿势

「改了三天,查重率从 42% 降到 39%」——如果你也有过这种崩溃经历,说明降重方法从根上就错了。降重不是文字游戏,不是把「的」改成「之」、把主动句换被动句就能糊弄的。2026 年的查重算法早已进化到语义层面,浅层改写基本无效。…

2026/8/17 3:03:04 阅读更多 →
华为凌霄子母路由Q7深度解析:WiFi7+星闪技术如何实现全屋无缝覆盖

华为凌霄子母路由Q7深度解析:WiFi7+星闪技术如何实现全屋无缝覆盖

这次我们来看一套面向全屋覆盖的WiFi7分布式路由系统——华为凌霄子母路由Q7。它被定位为Q6的升级版,核心卖点在于集成了最新的WiFi7技术、凌霄子母分布式架构、无感ACAP管理,并创新性地引入了星闪(NearLink)技术作为蓝牙家庭网关…

2026/8/18 8:49:44 阅读更多 →
Nginx三种安装方式详解:源码、包管理、Docker

Nginx三种安装方式详解:源码、包管理、Docker

1. Nginx安装方式全景解读作为全球使用率排名第三的Web服务器,Nginx的安装部署是每个运维人员和开发者的必修课。我在实际生产环境中部署过上百次Nginx,遇到过各种环境下的安装问题。今天就来系统梳理三种主流安装方式的特点和适用场景,帮你避…

2026/8/18 3:22:56 阅读更多 →

最新新闻

3步上手免登录微博图片批量下载:weiboPicDownloader从入门到进阶完整指南

3步上手免登录微博图片批量下载:weiboPicDownloader从入门到进阶完整指南

3步上手免登录微博图片批量下载:weiboPicDownloader从入门到进阶完整指南 【免费下载链接】weiboPicDownloader Download weibo images without logging-in 项目地址: https://gitcode.com/gh_mirrors/we/weiboPicDownloader 凌晨一点,你刷到一位…

2026/8/18 14:58:23 阅读更多 →
ubuntu24安装xrdp并启用硬件加速

ubuntu24安装xrdp并启用硬件加速

下载xrdp安装脚本 https://www.c-nergy.be/products.html 前提条件 登录的用户需要具有video和render的用户组。 需要提前安装些组件: sudo apt install libgbm-dev sudo apt install libepoxy-dev 修改脚本 nvidia 显卡 需要先安装nvidia显卡驱动&#xff…

2026/8/18 14:58:23 阅读更多 →
TrajectoryCrafter 教程:3 步让随手拍的单目视频镜头飞起来

TrajectoryCrafter 教程:3 步让随手拍的单目视频镜头飞起来

TrajectoryCrafter 教程:3 步让随手拍的单目视频镜头飞起来 【免费下载链接】TrajectoryCrafter [ICCV 2025, Oral] TrajectoryCrafter: Redirecting Camera Trajectory for Monocular Videos via Diffusion Models 项目地址: https://gitcode.com/gh_mirrors/tr/…

2026/8/18 14:58:23 阅读更多 →
2026年openrouter国内平替平台推荐:企业生产环境下首选哪家?

2026年openrouter国内平替平台推荐:企业生产环境下首选哪家?

摘要 API聚合平台正在成为企业接入大模型能力的核心枢纽。随着模型生态的进一步成熟,企业不再仅仅关注“能不能调用某个模型”,而是开始聚焦核心生产需求:高并发稳定性、账务透明化、权限精细化管理、合规可落地。海外主流聚合平台OpenRouter…

2026/8/18 14:58:23 阅读更多 →
Mesa3D Windows 安装终极指南:一招解决 OpenGL 兼容性问题与 DLL 缺失报错

Mesa3D Windows 安装终极指南:一招解决 OpenGL 兼容性问题与 DLL 缺失报错

Mesa3D Windows 安装终极指南:一招解决 OpenGL 兼容性问题与 DLL 缺失报错 【免费下载链接】mesa-dist-win Pre-built Mesa3D drivers for Windows 项目地址: https://gitcode.com/gh_mirrors/me/mesa-dist-win 深夜十二点,你双击那款珍藏多年的老…

2026/8/18 14:58:23 阅读更多 →
W5500 9大应用场景

W5500 9大应用场景

W5500 是 WIZnet 公司推出的一款经典的硬件 TCP/IP 协议栈以太网控制器,内置 10/100M 以太网 PHY 和 MAC,通过高速 SPI 接口与主控 MCU(如 STM32、ESP32、51 单片机等)通信。 它的核心优势在于:将繁琐的 TCP/IP 协议处…

2026/8/18 14:57:22 阅读更多 →

日新闻

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 如果你还停留在"看网课 不停暂停 截图 …

2026/8/18 0:00:57 阅读更多 →
思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 你是不是也经历过这种时刻:设计稿里…

2026/8/18 0:00:58 阅读更多 →
华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, …

2026/8/18 0:00:59 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/18 9:15:35 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 9:06:28 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/18 9:04:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →