Node.js 提供了丰富的内置模块,帮助开发者高效处理各种常见任务。本文将详细介绍五个重要的工具模块:path (路径处理)、url (URL解析)、querystring (查询字符串)、util (工具函数)和 os(操作系统信息)。
一、path 模块:路径处理
path 模块提供了用于处理和转换文件路径的实用工具。它最大的优势是跨平台兼容性 ,能够自动处理不同操作系统的路径分隔符(Windows 使用 \,Unix/Linux/macOS 使用 /)。
1.1 引入模块
javascript
const path = require('path');
1.2 常用方法
path.join([...paths]) - 连接路径片段
将多个路径片段连接成一个完整的路径,自动处理路径分隔符和相对路径。
javascript
const path = require('path');
// 基本用法
console.log(path.join('/users', 'john', 'docs', 'file.txt'));
// Unix/Linux/macOS: /users/john/docs/file.txt
// Windows: 如果第一个参数是绝对路径,结果取决于平台
// 跨平台推荐用法(使用相对路径)
console.log(path.join('users', 'john', 'docs', 'file.txt'));
// 所有平台: users/john/docs/file.txt(相对路径)
// 使用 __dirname 构建绝对路径
console.log(path.join(__dirname, 'docs', 'file.txt'));
// 输出: 当前文件所在目录/docs/file.txt
// 处理相对路径
console.log(path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'));
// 输出: /foo/bar/baz/asdf
// 处理当前目录和父目录
console.log(path.join(__dirname, '..', 'config', 'app.json'));
// 输出: 当前目录的父目录下的 config/app.json
path.resolve([...paths]) - 解析为绝对路径
将路径或路径片段解析为绝对路径。如果所有路径片段都是相对路径,则相对于当前工作目录解析。
javascript
const path = require('path');
// 从右到左处理路径,直到构造出绝对路径
console.log(path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile'));
// 输出: /tmp/subfile
// 如果所有路径都是相对路径,则相对于当前工作目录
console.log(path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif'));
// 如果当前目录是 /home/myself/node,则输出:
// /home/myself/node/wwwroot/static_files/gif/image.gif
// 常用:解析相对于当前文件的路径
const configPath = path.resolve(__dirname, 'config.json');
path.basename(path[, ext]) - 获取文件名
返回路径的最后一部分(文件名)。可选的 ext 参数用于去除文件扩展名。
javascript
const path = require('path');
console.log(path.basename('/foo/bar/baz/asdf/quux.html'));
// 输出: 'quux.html'
console.log(path.basename('/foo/bar/baz/asdf/quux.html', '.html'));
// 输出: 'quux'
// Windows 示例
console.log(path.basename('C:\\temp\\myfile.html'));
// 输出: 'myfile.html'
path.dirname(path) - 获取目录名
返回路径的目录部分。
javascript
const path = require('path');
console.log(path.dirname('/foo/bar/baz/asdf/quux.html'));
// 输出: '/foo/bar/baz/asdf'
console.log(path.dirname('/foo/bar/baz/asdf/quux'));
// 输出: '/foo/bar/baz/asdf'
path.extname(path) - 获取扩展名
返回路径中文件的扩展名(包括点号)。
javascript
const path = require('path');
console.log(path.extname('index.html'));
// 输出: '.html'
console.log(path.extname('index.coffee.md'));
// 输出: '.md'
console.log(path.extname('index.'));
// 输出: '.'
console.log(path.extname('index'));
// 输出: ''
path.parse(path) - 解析路径对象
将路径字符串解析为一个对象,包含 root、dir、base、ext、name 等属性。
javascript
const path = require('path');
const parsed = path.parse('/home/user/dir/file.txt');
console.log(parsed);
// 输出:
// {
// root: '/',
// dir: '/home/user/dir',
// base: 'file.txt',
// ext: '.txt',
// name: 'file'
// }
// Windows 示例
const winParsed = path.parse('C:\\path\\dir\\file.txt');
console.log(winParsed);
// 输出:
// {
// root: 'C:\\',
// dir: 'C:\\path\\dir',
// base: 'file.txt',
// ext: '.txt',
// name: 'file'
// }
path.format(pathObject) - 格式化路径对象
与 path.parse() 相反,将路径对象格式化为路径字符串。
javascript
const path = require('path');
const pathObject = {
root: '/',
dir: '/home/user/dir',
base: 'file.txt',
ext: '.txt',
name: 'file'
};
console.log(path.format(pathObject));
// 输出: '/home/user/dir/file.txt'
path.normalize(path) - 规范化路径
规范化路径字符串,解析 . 和 .. 片段,并处理多余的路径分隔符。
javascript
const path = require('path');
console.log(path.normalize('/foo/bar//baz/asdf/quux/..'));
// 输出: '/foo/bar/baz/asdf'
console.log(path.normalize('C:\\temp\\\\foo\\bar\\..\\'));
// Windows 输出: 'C:\\temp\\foo\\'
path.isAbsolute(path) - 判断是否为绝对路径
判断路径是否为绝对路径。
javascript
const path = require('path');
console.log(path.isAbsolute('/foo/bar')); // true
console.log(path.isAbsolute('/baz/..')); // true
console.log(path.isAbsolute('qux/')); // false
console.log(path.isAbsolute('.')); // false
// Windows
console.log(path.isAbsolute('C:\\foo')); // true
console.log(path.isAbsolute('\\foo')); // true
path.relative(from, to) - 计算相对路径
计算从 from 到 to 的相对路径。
javascript
const path = require('path');
console.log(path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb'));
// 输出: '../../impl/bbb'
console.log(path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb'));
// Windows 输出: '..\\..\\impl\\bbb'
1.3 特殊变量
__dirname:当前模块的目录名(CommonJS)__filename:当前模块的文件名(CommonJS)
javascript
const path = require('path');
// 获取当前文件的目录
console.log(__dirname);
// 输出: /path/to/current/directory
// 获取当前文件的完整路径
console.log(__filename);
// 输出: /path/to/current/directory/file.js
// 构建相对于当前文件的路径
const configPath = path.join(__dirname, 'config', 'app.json');
1.4 实用示例
javascript
const path = require('path');
const fs = require('fs').promises;
// 示例1:安全地构建文件路径
async function readConfig() {
const configPath = path.join(__dirname, 'config', 'app.json');
const data = await fs.readFile(configPath, 'utf8');
return JSON.parse(data);
}
// 示例2:获取文件信息
function getFileInfo(filePath) {
return {
fullPath: path.resolve(filePath),
dirname: path.dirname(filePath),
basename: path.basename(filePath),
extname: path.extname(filePath),
name: path.basename(filePath, path.extname(filePath))
};
}
console.log(getFileInfo('/home/user/docs/report.pdf'));
// 输出:
// {
// fullPath: '/home/user/docs/report.pdf',
// dirname: '/home/user/docs',
// basename: 'report.pdf',
// extname: '.pdf',
// name: 'report'
// }
// 示例3:处理上传文件的扩展名
function isImageFile(filename) {
const ext = path.extname(filename).toLowerCase();
return ['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(ext);
}
console.log(isImageFile('photo.jpg')); // true
console.log(isImageFile('document.pdf')); // false
二、url 模块:URL 解析
url 模块提供了用于解析和格式化 URL 的实用工具。Node.js 推荐使用 WHATWG URL API。
2.1 引入模块
javascript
// WHATWG URL API(推荐)
const { URL, URLSearchParams } = require('url');
2.2 WHATWG URL API(推荐)
new URL(input[, base]) - 创建 URL 对象
javascript
const { URL } = require('url');
// 绝对 URL
const myURL = new URL('https://example.org:8080/p/a/t/h?query=string#hash');
console.log(myURL.href); // 'https://example.org:8080/p/a/t/h?query=string#hash'
console.log(myURL.protocol); // 'https:'
console.log(myURL.hostname); // 'example.org'
console.log(myURL.port); // '8080'
console.log(myURL.pathname); // '/p/a/t/h'
console.log(myURL.search); // '?query=string'
console.log(myURL.hash); // '#hash'
// 相对 URL(需要提供 base)
const baseURL = 'https://example.org/foo/bar';
const relativeURL = new URL('../baz', baseURL);
console.log(relativeURL.href); // 'https://example.org/foo/baz'
URL 对象属性
javascript
const { URL } = require('url');
const myURL = new URL('https://user:pass@sub.example.com:8080/p/a/t/h?query=string#hash');
console.log(myURL.protocol); // 'https:'
console.log(myURL.username); // 'user'
console.log(myURL.password); // 'pass'
console.log(myURL.host); // 'sub.example.com:8080'
console.log(myURL.hostname); // 'sub.example.com'
console.log(myURL.port); // '8080'
console.log(myURL.pathname); // '/p/a/t/h'
console.log(myURL.search); // '?query=string'
console.log(myURL.searchParams); // URLSearchParams 对象
console.log(myURL.hash); // '#hash'
console.log(myURL.origin); // 'https://sub.example.com:8080'
URLSearchParams - 查询参数处理
URLSearchParams 提供了强大的查询字符串操作方法。
javascript
const { URL, URLSearchParams } = require('url');
// 从 URL 对象获取查询参数
const myURL = new URL('https://example.com/?name=Kai&age=30&city=Beijing');
const params = myURL.searchParams;
// 获取参数值
console.log(params.get('name')); // 'Kai'
console.log(params.get('age')); // '30'
console.log(params.has('city')); // true
// 设置参数
params.set('age', '31');
params.set('email', 'kai@example.com');
// 追加参数
params.append('hobby', 'coding');
params.append('hobby', 'reading');
// 删除参数
params.delete('city');
// 获取所有值
console.log(params.getAll('hobby')); // ['coding', 'reading']
// 遍历参数
for (const [key, value] of params) {
console.log(`${key}: ${value}`);
}
// 转换为字符串
console.log(params.toString());
// 输出: 'name=Kai&age=31&email=kai%40example.com&hobby=coding&hobby=reading'
// 排序
params.sort();
console.log(params.toString());
独立使用 URLSearchParams
javascript
const { URLSearchParams } = require('url');
// 从字符串创建
const params1 = new URLSearchParams('foo=bar&abc=xyz&abc=123');
console.log(params1.get('foo')); // 'bar'
console.log(params1.getAll('abc')); // ['xyz', '123']
// 从对象创建
const params2 = new URLSearchParams({
user: 'admin',
password: 'secret123'
});
console.log(params2.toString()); // 'user=admin&password=secret123'
// 从 Map 创建
const map = new Map([
['name', 'John'],
['age', '30']
]);
const params3 = new URLSearchParams(map);
console.log(params3.toString()); // 'name=John&age=30'
2.3 实用示例
javascript
const { URL, URLSearchParams } = require('url');
// 示例1:构建带查询参数的 URL
function buildURL(baseURL, params) {
const url = new URL(baseURL);
Object.keys(params).forEach(key => {
url.searchParams.set(key, params[key]);
});
return url.href;
}
console.log(buildURL('https://api.example.com/users', {
page: '1',
limit: '10',
sort: 'name'
}));
// 输出: 'https://api.example.com/users?page=1&limit=10&sort=name'
// 示例2:解析和修改 URL
function updateURLPort(urlString, newPort) {
const url = new URL(urlString);
url.port = newPort;
return url.href;
}
console.log(updateURLPort('https://example.com:8080/path', '3000'));
// 输出: 'https://example.com:3000/path'
// 示例3:验证 URL
function isValidURL(str) {
try {
new URL(str);
return true;
} catch {
return false;
}
}
console.log(isValidURL('https://example.com')); // true
console.log(isValidURL('not-a-url')); // false
// 示例4:提取域名
function getDomain(urlString) {
const url = new URL(urlString);
return url.hostname;
}
console.log(getDomain('https://www.example.com:8080/path?query=1'));
// 输出: 'www.example.com'
三、querystring 模块:查询字符串处理
querystring 模块提供了用于解析和格式化 URL 查询字符串的实用工具。虽然 URLSearchParams 更现代,但 querystring 模块在处理自定义分隔符时仍然有用。
3.1 引入模块
javascript
const querystring = require('querystring');
3.2 常用方法
querystring.parse(str[, sep[, eq[, options]]]) - 解析查询字符串
将查询字符串解析为对象。
javascript
const querystring = require('querystring');
// 基本用法
const qs = 'year=2017&month=february&day=15';
const parsed = querystring.parse(qs);
console.log(parsed);
// 输出: { year: '2017', month: 'february', day: '15' }
console.log(parsed.year); // '2017'
console.log(parsed.month); // 'february'
// 自定义分隔符
const customQS = 'year:2017;month:february';
const parsed2 = querystring.parse(customQS, ';', ':');
console.log(parsed2);
// 输出: { year: '2017', month: 'february' }
// 解码选项
const encodedQS = 'name=John%20Doe&city=New%20York';
const parsed3 = querystring.parse(encodedQS);
console.log(parsed3);
// 输出: { name: 'John Doe', city: 'New York' }
querystring.stringify(obj[, sep[, eq[, options]]]) - 序列化为查询字符串
将对象序列化为查询字符串。
javascript
const querystring = require('querystring');
// 基本用法
const obj = {
year: 2017,
month: 'february',
day: 15
};
const qs = querystring.stringify(obj);
console.log(qs);
// 输出: 'year=2017&month=february&day=15'
// 自定义分隔符
const customQS = querystring.stringify(obj, ';', ':');
console.log(customQS);
// 输出: 'year:2017;month:february;day:15'
// 编码选项
const obj2 = {
name: 'John Doe',
city: 'New York'
};
const encodedQS = querystring.stringify(obj2);
console.log(encodedQS);
// 输出: 'name=John%20Doe&city=New%20York'
// 处理数组
const obj3 = {
tags: ['nodejs', 'javascript', 'web']
};
console.log(querystring.stringify(obj3));
// 输出: 'tags=nodejs&tags=javascript&tags=web'
querystring.escape(str) - URL 编码
对字符串进行 URL 编码(通常不需要直接调用,stringify 会自动处理)。
javascript
const querystring = require('querystring');
console.log(querystring.escape('hello world'));
// 输出: 'hello%20world'
console.log(querystring.escape('foo@bar.com'));
// 输出: 'foo%40bar.com'
querystring.unescape(str) - URL 解码
对字符串进行 URL 解码(通常不需要直接调用,parse 会自动处理)。
javascript
const querystring = require('querystring');
console.log(querystring.unescape('hello%20world'));
// 输出: 'hello world'
console.log(querystring.unescape('foo%40bar.com'));
// 输出: 'foo@bar.com'
3.3 实用示例
javascript
const querystring = require('querystring');
// 示例1:解析 URL 查询字符串
function parseQueryString(urlString) {
const queryString = urlString.split('?')[1] || '';
return querystring.parse(queryString);
}
const url = 'https://example.com/search?q=nodejs&page=1&limit=10';
const params = parseQueryString(url);
console.log(params);
// 输出: { q: 'nodejs', page: '1', limit: '10' }
// 示例2:构建查询字符串
function buildQueryString(params) {
return querystring.stringify(params);
}
const searchParams = {
q: 'nodejs tutorial',
page: 1,
sort: 'relevance'
};
console.log(buildQueryString(searchParams));
// 输出: 'q=nodejs%20tutorial&page=1&sort=relevance'
// 示例3:合并查询参数
function mergeQueryParams(baseParams, newParams) {
const merged = { ...baseParams, ...newParams };
return querystring.stringify(merged);
}
const base = { page: 1, limit: 10 };
const additional = { sort: 'name', order: 'asc' };
console.log(mergeQueryParams(base, additional));
// 输出: 'page=1&limit=10&sort=name&order=asc'
// 示例4:处理嵌套对象(需要自定义序列化)
function stringifyNested(obj, prefix = '') {
const pairs = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
const newKey = prefix ? `${prefix}[${key}]` : key;
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
pairs.push(...stringifyNested(value, newKey));
} else if (Array.isArray(value)) {
value.forEach((item, index) => {
pairs.push(`${newKey}[${index}]=${encodeURIComponent(item)}`);
});
} else {
pairs.push(`${newKey}=${encodeURIComponent(value)}`);
}
}
}
return pairs;
}
const nested = {
user: {
name: 'John',
age: 30
},
tags: ['nodejs', 'javascript']
};
console.log(stringifyNested(nested).join('&'));
// 输出: 'user[name]=John&user[age]=30&tags[0]=nodejs&tags[1]=javascript'
四、util 模块:工具函数
util 模块提供了多种实用工具函数,帮助开发者处理常见的编程任务,如类型检查、调试、Promise 转换等。
4.1 引入模块
javascript
const util = require('util');
4.2 常用方法
util.format(format[, ...args]) - 格式化字符串
返回格式化后的字符串,类似于 C 语言的 printf 函数。
javascript
const util = require('util');
// 基本用法
console.log(util.format('%s:%s', 'foo', 'bar'));
// 输出: 'foo:bar'
console.log(util.format('%d + %d = %d', 1, 2, 3));
// 输出: '1 + 2 = 3'
// 占位符
// %s - 字符串
// %d - 数字(整数或浮点数)
// %j - JSON
// %% - 百分号
console.log(util.format('Name: %s, Age: %d, Data: %j', 'John', 30, { city: 'NYC' }));
// 输出: 'Name: John, Age: 30, Data: {"city":"NYC"}'
// 如果没有提供格式字符串,则将所有参数用空格连接
console.log(util.format('Hello', 'World', 123));
// 输出: 'Hello World 123'
util.inspect(object[, options]) - 对象检查
返回对象的字符串表示,通常用于调试。这是 console.log 内部使用的方法。
javascript
const util = require('util');
const obj = {
name: 'John',
age: 30,
nested: {
city: 'NYC',
hobbies: ['coding', 'reading']
}
};
// 基本用法
console.log(util.inspect(obj));
// 输出: { name: 'John', age: 30, nested: { city: 'NYC', hobbies: [ 'coding', 'reading' ] } }
// 选项配置
console.log(util.inspect(obj, {
colors: true, // 使用颜色
depth: 2, // 最大递归深度
compact: false, // 每个属性一行
showHidden: true, // 显示不可枚举属性
breakLength: 80 // 换行长度
}));
// 自定义 inspect 方法
class CustomObject {
constructor(value) {
this.value = value;
}
[util.inspect.custom]() {
return `CustomObject(${this.value})`;
}
}
const custom = new CustomObject(42);
console.log(util.inspect(custom));
// 输出: 'CustomObject(42)'
util.promisify(original) - Promise 化
将遵循错误优先回调风格的函数转换为返回 Promise 的函数。
javascript
const util = require('util');
const fs = require('fs');
// 将回调函数转换为 Promise
const readFile = util.promisify(fs.readFile);
const writeFile = util.promisify(fs.writeFile);
// 使用 async/await
async function readConfig() {
try {
const data = await readFile('config.json', 'utf8');
return JSON.parse(data);
} catch (error) {
console.error('读取文件失败:', error);
throw error;
}
}
// 使用 .then()
readFile('data.txt', 'utf8')
.then(data => console.log(data))
.catch(err => console.error(err));
// 自定义 Promise 化函数
function customFunction(arg, callback) {
setTimeout(() => {
if (arg > 0) {
callback(null, arg * 2);
} else {
callback(new Error('参数必须大于0'));
}
}, 100);
}
const promisifiedCustom = util.promisify(customFunction);
promisifiedCustom(5)
.then(result => console.log(result)) // 输出: 10
.catch(err => console.error(err));
util.callbackify(original) - 回调化
与 promisify 相反,将返回 Promise 的函数转换为使用回调的函数。
javascript
const util = require('util');
const fs = require('fs').promises;
// 将 Promise 函数转换为回调函数
const readFileCallback = util.callbackify(fs.readFile);
readFileCallback('file.txt', 'utf8', (err, data) => {
if (err) {
console.error('错误:', err);
return;
}
console.log('数据:', data);
});
util.types - 类型检查
提供各种类型检查函数。
javascript
const util = require('util');
// 检查是否为数组
console.log(util.types.isArrayBuffer(new ArrayBuffer())); // true
console.log(util.types.isArrayBuffer([])); // false
// 检查是否为 Date 对象
console.log(util.types.isDate(new Date())); // true
console.log(util.types.isDate(Date.now())); // false
// 检查是否为 Map
console.log(util.types.isMap(new Map())); // true
// 检查是否为 Set
console.log(util.types.isSet(new Set())); // true
// 检查是否为 Promise
console.log(util.types.isPromise(Promise.resolve())); // true
// 检查是否为 RegExp
console.log(util.types.isRegExp(/abc/)); // true
// 检查是否为 String 对象
console.log(util.types.isStringObject(new String('foo'))); // true
console.log(util.types.isStringObject('foo')); // false
util.debuglog(section) - 调试日志
创建一个调试日志函数,仅在设置了 NODE_DEBUG 环境变量时才会输出日志。
javascript
const util = require('util');
const debuglog = util.debuglog('foo');
// 设置环境变量: NODE_DEBUG=foo node app.js
debuglog('Hello from foo [%d]', 123);
// 只有在设置了 NODE_DEBUG=foo 时才会输出
// 多个调试标签
const debug1 = util.debuglog('foo');
const debug2 = util.debuglog('bar');
debug1('这是 foo 的调试信息');
debug2('这是 bar 的调试信息');
// 运行: NODE_DEBUG=foo,bar node app.js
util.deprecate(fn, msg[, code]) - 标记为弃用
标记函数为已弃用,调用时会显示警告信息。
javascript
const util = require('util');
const deprecatedFunction = util.deprecate(() => {
console.log('这个函数已被弃用');
}, 'deprecatedFunction() 已弃用,请使用 newFunction() 代替');
deprecatedFunction();
// 输出警告: (node:12345) DeprecationWarning: deprecatedFunction() 已弃用,请使用 newFunction() 代替
4.3 实用示例
javascript
const util = require('util');
const fs = require('fs');
// 示例1:深度克隆对象(使用 JSON 序列化,有局限性)
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
// 注意:此方法无法克隆函数、undefined、Symbol、Date 对象等
// 更好的方式:使用结构化克隆(Node.js 17+)或库如 lodash.cloneDeep
// 示例2:格式化错误对象
function formatError(error) {
return util.inspect(error, {
colors: true,
depth: null
});
}
try {
throw new Error('Something went wrong');
} catch (err) {
console.log(formatError(err));
}
// 示例3:批量 Promise 化
function promisifyAll(obj) {
const promisified = {};
for (const key in obj) {
if (typeof obj[key] === 'function') {
promisified[key] = util.promisify(obj[key].bind(obj));
}
}
return promisified;
}
const fsPromises = promisifyAll(fs);
// 现在可以使用 fsPromises.readFile, fsPromises.writeFile 等
// 示例4:创建调试工具
function createDebugger(namespace) {
const debug = util.debuglog(namespace);
return {
log: (...args) => debug(util.format(...args)),
info: (...args) => debug(`[INFO] ${util.format(...args)}`),
error: (...args) => debug(`[ERROR] ${util.format(...args)}`)
};
}
const logger = createDebugger('app');
// 运行: NODE_DEBUG=app node app.js
logger.log('Application started');
logger.info('Processing request');
logger.error('An error occurred');
五、os 模块:操作系统信息
os 模块提供了与操作系统相关的信息和方法,允许开发者获取系统架构、平台、CPU 信息、内存使用情况、网络接口等。
5.1 引入模块
javascript
const os = require('os');
5.2 常用方法和属性
os.platform() - 获取操作系统平台
返回操作系统平台标识符。
javascript
const os = require('os');
console.log(os.platform());
// 可能的值:
// 'darwin' - macOS
// 'win32' - Windows
// 'linux' - Linux
// 'freebsd' - FreeBSD
// 'openbsd' - OpenBSD
os.arch() - 获取 CPU 架构
返回操作系统的 CPU 架构。
javascript
const os = require('os');
console.log(os.arch());
// 可能的值:
// 'x64' - 64位
// 'arm' - ARM
// 'arm64' - ARM 64位
// 'ia32' - 32位
os.cpus() - 获取 CPU 信息
返回每个逻辑 CPU 内核的信息数组。
javascript
const os = require('os');
const cpus = os.cpus();
console.log(`CPU 核心数: ${cpus.length}`);
cpus.forEach((cpu, index) => {
console.log(`CPU ${index}:`);
console.log(` 型号: ${cpu.model}`);
console.log(` 速度: ${cpu.speed} MHz`);
console.log(` 用户时间: ${cpu.times.user} ms`);
console.log(` 系统时间: ${cpu.times.sys} ms`);
console.log(` 空闲时间: ${cpu.times.idle} ms`);
});
// 计算 CPU 使用率
// 注意:此函数仅用于演示基本概念。实际应用中,CPU 使用率需要通过两次采样(间隔一段时间)来计算差值才能得到准确结果
function getCPUUsage() {
const cpus = os.cpus();
let totalIdle = 0;
let totalTick = 0;
cpus.forEach(cpu => {
const times = cpu.times;
totalIdle += times.idle;
totalTick += times.user + times.nice + times.sys + times.idle + times.irq;
});
const idle = totalIdle / cpus.length;
const total = totalTick / cpus.length;
const usage = 100 - ~~(100 * idle / total);
return usage;
}
os.totalmem() - 获取总内存
返回系统的总内存量(以字节为单位)。
javascript
const os = require('os');
const totalMem = os.totalmem();
console.log(`总内存: ${(totalMem / 1024 / 1024 / 1024).toFixed(2)} GB`);
os.freemem() - 获取空闲内存
返回系统的空闲内存量(以字节为单位)。
javascript
const os = require('os');
const freeMem = os.freemem();
console.log(`空闲内存: ${(freeMem / 1024 / 1024 / 1024).toFixed(2)} GB`);
// 计算内存使用率
function getMemoryUsage() {
const total = os.totalmem();
const free = os.freemem();
const used = total - free;
const usagePercent = (used / total * 100).toFixed(2);
return {
total: formatBytes(total),
used: formatBytes(used),
free: formatBytes(free),
usagePercent: `${usagePercent}%`
};
}
function formatBytes(bytes) {
return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
}
os.hostname() - 获取主机名
返回操作系统的主机名。
javascript
const os = require('os');
console.log(os.hostname());
// 输出: 'my-computer'
os.type() - 获取操作系统类型
返回操作系统的类型。
javascript
const os = require('os');
console.log(os.type());
// 可能的值:
// 'Linux' - Linux
// 'Darwin' - macOS
// 'Windows_NT' - Windows
os.release() - 获取操作系统版本
返回操作系统的版本号。
javascript
const os = require('os');
console.log(os.release());
// 输出: '5.4.0-74-generic' (Linux)
// 或: '20.6.0' (macOS)
// 或: '10.0.19043' (Windows)
os.uptime() - 获取系统运行时间
返回系统的运行时间(以秒为单位)。
javascript
const os = require('os');
const uptime = os.uptime();
const days = Math.floor(uptime / 86400);
const hours = Math.floor((uptime % 86400) / 3600);
const minutes = Math.floor((uptime % 3600) / 60);
const seconds = uptime % 60;
console.log(`系统运行时间: ${days}天 ${hours}小时 ${minutes}分钟 ${seconds}秒`);
os.homedir() - 获取用户主目录
返回当前用户的主目录路径。
javascript
const os = require('os');
console.log(os.homedir());
// Windows: 'C:\\Users\\username'
// Linux/macOS: '/home/username'
os.tmpdir() - 获取临时目录
返回操作系统的临时文件目录路径。
javascript
const os = require('os');
console.log(os.tmpdir());
// Windows: 'C:\\Users\\username\\AppData\\Local\\Temp'
// Linux: '/tmp'
// macOS: '/var/folders/...'
os.networkInterfaces() - 获取网络接口
返回网络接口信息对象。
javascript
const os = require('os');
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
console.log(`接口: ${name}`);
interfaces[name].forEach(iface => {
// 兼容不同 Node.js 版本:family 可能是 'IPv4' 或 4
const isIPv4 = iface.family === 'IPv4' || iface.family === 4;
if (isIPv4 && !iface.internal) {
console.log(` IPv4: ${iface.address}`);
console.log(` 子网掩码: ${iface.netmask}`);
}
});
}
// 获取本机 IP 地址
function getLocalIP() {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
// 兼容不同 Node.js 版本:family 可能是 'IPv4' 或 4
const isIPv4 = iface.family === 'IPv4' || iface.family === 4;
if (isIPv4 && !iface.internal) {
return iface.address;
}
}
}
return '127.0.0.1';
}
console.log(`本机 IP: ${getLocalIP()}`);
os.endianness() - 获取字节序
返回 CPU 的字节序。
javascript
const os = require('os');
console.log(os.endianness());
// 'BE' - 大端序
// 'LE' - 小端序(常见)
os.EOL - 行尾标识符
返回操作系统的行尾标识符。
javascript
const os = require('os');
console.log(os.EOL);
// Windows: '\r\n'
// Unix/Linux/macOS: '\n'
// 使用示例
const content = `第一行${os.EOL}第二行${os.EOL}第三行`;
5.3 实用示例
javascript
const os = require('os');
// 示例1:系统信息汇总
// 获取本机 IP 地址的辅助函数
function getLocalIP() {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
// 兼容不同 Node.js 版本:family 可能是 'IPv4' 或 4
const isIPv4 = iface.family === 'IPv4' || iface.family === 4;
if (isIPv4 && !iface.internal) {
return iface.address;
}
}
}
return '127.0.0.1';
}
function getSystemInfo() {
return {
platform: os.platform(),
arch: os.arch(),
hostname: os.hostname(),
type: os.type(),
release: os.release(),
uptime: formatUptime(os.uptime()),
cpus: {
count: os.cpus().length,
model: os.cpus()[0].model
},
memory: {
total: formatBytes(os.totalmem()),
free: formatBytes(os.freemem()),
used: formatBytes(os.totalmem() - os.freemem()),
usagePercent: ((os.totalmem() - os.freemem()) / os.totalmem() * 100).toFixed(2) + '%'
},
network: getLocalIP()
};
}
function formatBytes(bytes) {
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
if (bytes === 0) return '0 B';
const i = Math.floor(Math.log(bytes) / Math.log(1024));
return Math.round(bytes / Math.pow(1024, i) * 100) / 100 + ' ' + sizes[i];
}
function formatUptime(seconds) {
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${days}天 ${hours}小时 ${minutes}分钟`;
}
console.log(getSystemInfo());
// 示例2:监控系统资源
// 计算 CPU 使用率的辅助函数(简化版本,实际使用时建议使用两次采样)
function getCPUUsage() {
const cpus = os.cpus();
let totalIdle = 0;
let totalTick = 0;
cpus.forEach(cpu => {
const times = cpu.times;
totalIdle += times.idle;
totalTick += times.user + times.nice + times.sys + times.idle + times.irq;
});
const idle = totalIdle / cpus.length;
const total = totalTick / cpus.length;
const usage = 100 - ~~(100 * idle / total);
return usage;
}
function monitorSystem(interval = 5000) {
setInterval(() => {
const memUsage = (os.totalmem() - os.freemem()) / os.totalmem() * 100;
// 注意:getCPUUsage() 需要两次采样才能准确,这里仅作演示
const cpuUsage = getCPUUsage();
console.log(`内存使用率: ${memUsage.toFixed(2)}%`);
console.log(`CPU 使用率: ${cpuUsage}%`);
if (memUsage > 90) {
console.warn('警告: 内存使用率过高!');
}
if (cpuUsage > 90) {
console.warn('警告: CPU 使用率过高!');
}
}, interval);
}
// 示例3:根据平台选择不同的行为
function platformSpecificAction() {
switch (os.platform()) {
case 'win32':
console.log('Windows 特定操作');
// Windows 特定代码
break;
case 'darwin':
console.log('macOS 特定操作');
// macOS 特定代码
break;
case 'linux':
console.log('Linux 特定操作');
// Linux 特定代码
break;
default:
console.log('其他平台');
}
}
// 示例4:创建临时文件路径
const path = require('path');
function createTempFilePath(prefix = 'temp', suffix = '.txt') {
const tmpDir = os.tmpdir();
const timestamp = Date.now();
const random = Math.random().toString(36).substring(7);
return path.join(tmpDir, `${prefix}-${timestamp}-${random}${suffix}`);
}
// 示例5:检测系统负载
function getSystemLoad() {
const cpus = os.cpus();
const load = cpus.map(cpu => {
const total = Object.values(cpu.times).reduce((a, b) => a + b);
const usage = ((total - cpu.times.idle) / total * 100).toFixed(2);
return parseFloat(usage);
});
const avgLoad = (load.reduce((a, b) => a + b, 0) / load.length).toFixed(2);
return {
perCore: load,
average: parseFloat(avgLoad)
};
}
console.log('系统负载:', getSystemLoad());
总结
本文详细介绍了 Node.js 中五个重要的工具模块:
- path 模块:处理文件路径,提供跨平台兼容性
- url 模块:解析和格式化 URL,推荐使用 WHATWG URL API
- querystring 模块:处理查询字符串的解析和序列化
- util 模块:提供各种实用工具函数,如类型检查、Promise 转换、调试等
- os 模块:获取操作系统相关信息,如平台、CPU、内存等
这些模块都是 Node.js 的内置模块,无需安装即可使用。熟练掌握这些模块能够大大提高开发效率,让代码更加健壮和可维护。
最佳实践建议
- 路径处理 :始终使用
path.join()和path.resolve()而不是字符串拼接 - URL 处理 :使用 WHATWG URL API(
URL和URLSearchParams) - 查询字符串 :对于简单场景使用
querystring,复杂场景使用URLSearchParams - 异步转换 :使用
util.promisify()将回调函数转换为 Promise - 系统信息 :使用
os模块进行跨平台兼容性处理 - 继承 :使用 ES6 的
class和extends语法,而不是已弃用的util.inherits()
参考资源: