在接觸 Node.js 的 fs
(File System)模組之前,對電腦中檔案操作的理解,就只停留在右鍵新增,右鍵刪除,所以在發現到可以借由程式碼去操控檔案滿有趣的,也理解了一些更底層的原理。
fs
模組提供了與檔案系統互動的 API,讓我們能夠讀取、寫入、修改和刪除檔案,以及操作目錄。這是 Node.js 的核心模組之一,不需要額外安裝即可使用。
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 使用 ES 模組語法
import * as fs from 'node:fs';
import * as fsPromises from 'node:fs/promises';
// 或者
import { readFile, writeFile } from 'node:fs';
import { readFile as readFileAsync, writeFile as writeFileAsync } from 'node:fs/promises';
fs
模組提供了同步和非同步兩種版本的 API:
const fs = require('node:fs');
// 非同步讀取檔案
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error('讀取檔案時發生錯誤:', err);
return;
}
console.log('檔案內容:', data);
});
console.log('這行會先執行,不會等待檔案讀取完成');
const fs = require('node:fs');
try {
// 同步讀取檔案
const data = fs.readFileSync('example.txt', 'utf8');
console.log('檔案內容:', data);
} catch (err) {
console.error('讀取檔案時發生錯誤:', err);
}
console.log('這行會等待檔案讀取完成後才執行');
const fsPromises = require('node:fs/promises');
// 或使用 ES 模組語法
// import * as fsPromises from 'node:fs/promises';
async function readMyFile() {
try {
const data = await fsPromises.readFile('example.txt', 'utf8');
console.log('檔案內容:', data);
} catch (err) {
console.error('讀取檔案時發生錯誤:', err);
}
}
readMyFile();
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 回調方式
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// Promise 方式
fsPromises.readFile('example.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));
// 同步方式
const data = fs.readFileSync('example.txt', 'utf8');
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 回調方式
fs.writeFile('output.txt', '這是新內容', 'utf8', (err) => {
if (err) throw err;
console.log('檔案已被保存');
});
// Promise 方式
fsPromises.writeFile('output.txt', '這是新內容', 'utf8')
.then(() => console.log('檔案已被保存'))
.catch(err => console.error(err));
// 同步方式
fs.writeFileSync('output.txt', '這是新內容', 'utf8');
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 回調方式
fs.appendFile('log.txt', '新的日誌條目\n', (err) => {
if (err) throw err;
console.log('數據已附加到檔案');
});
// Promise 方式
fsPromises.appendFile('log.txt', '新的日誌條目\n')
.then(() => console.log('數據已附加到檔案'))
.catch(err => console.error(err));
// 同步方式
fs.appendFileSync('log.txt', '新的日誌條目\n');
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 推薦方法:使用 access 檢查檔案存在性
fs.access('example.txt', fs.constants.F_OK, (err) => {
console.log(err ? '檔案不存在' : '檔案存在');
});
// Promise 方式
fsPromises.access('example.txt', fs.constants.F_OK)
.then(() => console.log('檔案存在'))
.catch(() => console.log('檔案不存在'));
// 同步方式
try {
fs.accessSync('example.txt', fs.constants.F_OK);
console.log('檔案存在');
} catch (err) {
console.log('檔案不存在');
}
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 回調方式
fs.unlink('unnecessary.txt', (err) => {
if (err) throw err;
console.log('檔案已刪除');
});
// Promise 方式
fsPromises.unlink('unnecessary.txt')
.then(() => console.log('檔案已刪除'))
.catch(err => console.error(err));
// 同步方式
fs.unlinkSync('unnecessary.txt');
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 回調方式
fs.mkdir('newDir', { recursive: true }, (err) => {
if (err) throw err;
console.log('目錄已創建');
});
// Promise 方式
fsPromises.mkdir('newDir', { recursive: true })
.then(() => console.log('目錄已創建'))
.catch(err => console.error(err));
// 同步方式
fs.mkdirSync('newDir', { recursive: true });
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 回調方式
fs.readdir('myDir', (err, files) => {
if (err) throw err;
console.log('目錄內容:', files);
});
// Promise 方式
fsPromises.readdir('myDir')
.then(files => console.log('目錄內容:', files))
.catch(err => console.error(err));
// 同步方式
const files = fs.readdirSync('myDir');
console.log('目錄內容:', files);
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
fs.rm('dirWithContent', { recursive: true, force: true }, (err) => {
if (err) throw err;
console.log('目錄及其內容已刪除');
});
// Promise 方式
fsPromises.rm('dirWithContent', { recursive: true, force: true })
.then(() => console.log('目錄及其內容已刪除'))
.catch(err => console.error(err));
// 同步方式
fs.rmSync('dirWithContent', { recursive: true, force: true });
// 舊方法 (僅用於刪除空目錄)
fs.rmdir('emptyDir', (err) => {
if (err) throw err;
console.log('空目錄已刪除');
});
const fs = require('node:fs');
const fsPromises = require('node:fs/promises');
// 獲取檔案詳細資訊
fs.stat('example.txt', (err, stats) => {
if (err) throw err;
console.log('檔案大小:', stats.size, '位元組');
console.log('是否為檔案:', stats.isFile());
console.log('是否為目錄:', stats.isDirectory());
console.log('最後修改時間:', stats.mtime);
console.log('創建時間:', stats.birthtime);
});
// Promise 方式
fsPromises.stat('example.txt')
.then(stats => {
console.log('檔案大小:', stats.size, '位元組');
console.log('是否為檔案:', stats.isFile());
console.log('是否為符號連結:', stats.isSymbolicLink());
})
.catch(err => console.error(err));
// 同步方式
try {
const stats = fs.statSync('example.txt');
console.log('檔案資訊:', stats);
} catch (err) {
console.error('獲取檔案資訊時發生錯誤:', err);
}
適用於處理大檔案時避免記憶體溢出:
const fs = require('node:fs');
const { pipeline } = require('node:stream/promises');
// 創建讀取串流
const readStream = fs.createReadStream('largeFile.txt', 'utf8');
// 創建寫入串流
const writeStream = fs.createWriteStream('output.txt');
// 串流事件處理
readStream.on('data', (chunk) => {
console.log(`接收到 ${chunk.length} 位元組的數據`);
});
readStream.on('end', () => {
console.log('已完成讀取');
});
readStream.on('error', (err) => {
console.error('讀取錯誤:', err);
});
// 使用 pipeline 進行串流導向
async function copyFile() {
try {
await pipeline(readStream, writeStream);
console.log('檔案複製完成');
} catch (err) {
console.error('管道錯誤:', err);
}
}
copyFile();
// 使用 pipe
readStream.pipe(writeStream);
其他還有很多,有興趣可以再去官網尋找