如何学习 Node.js I/O、文件和路径
在Twitter上关注我,很高兴接受您对主题或改进的建议/Chris
如果您对 Node.js 完全陌生,或者您刚刚在 Node.js 中启动了一个 Express 应用程序,但几乎不了解 Node 的其他任何内容 - 那么本系列的第一部分适合您。
在本部分中我们将讨论:
- 使用文件路径,在处理文件和目录时,了解如何使用路径非常重要。在定位文件和解析表达式方面,有很多事情可能出错,但 Node.js 凭借其内置变量和强大的核心库,能够很好地帮助你保持正轨。
- Node.js 中几乎所有操作文件和目录的操作都带有异步和同步的风格。理解为什么我们应该选择其中一种,以及它们在调用方式上的区别非常重要。
- 演示,最后我们将构建一些演示来演示这些功能
文件系统
文件系统是许多应用程序的重要组成部分。这意味着它不仅要处理文件、目录,还要处理不同的访问级别和路径。
在 Node.js 中,文件处理可以分为同步和异步两种。Node.js 是单线程的,这意味着如果我们需要并行执行,就需要一种支持并行执行的方法。这种方法就是回调模式。
参考
- Node.js 文档 - 文件系统这是文件系统的官方文档页面
- fs 模块概述
fs
很好的概述,显示了模块上可用的方法 - 读取文件显示有关读取文件所需了解的所有内容
- 写入文件文档页面显示如何写入文件
- 使用文件夹显示如何使用文件夹
- 文件统计如果您需要有关文件或目录的具体信息,如创建日期、大小等,可以在此页面了解更多信息。
- 路径使用路径可能很棘手,但这个模块使这变得非常容易。
- 在 Azure 上创建 Node.js 应用程序想知道如何将您的 Node.js 应用程序带到云端吗?
- 使用 Node.js 以编程方式登录 Azure这将教您如何使用 Node.js 以编程方式连接到 Azure 资源
路径
文件路径表示目录或文件在文件系统中的位置。它看起来像这样:
/path/to/file.txt
根据我们处理的是基于 Linux 还是 Windows 的操作系统,路径看起来会有所不同。在 Windows 上,相同的路径可能如下所示:
C:\path\to\file.txt
我们在开发应用程序时需要考虑到这一点。
为此,我们有内置模块path
,可以像这样使用:
const path = require("path");
该模块path
可以帮助我们执行以下操作:
- 信息,它可以从我们的路径中提取有关父目录、文件名和文件扩展名等信息
- 加入,我们可以获得连接两个路径的帮助,这样我们就不必担心我们的代码在哪个操作系统上运行
- 绝对路径,我们可以得到计算绝对路径的帮助
- 规范化,可以帮助我们计算两条路径之间的相对距离。
演示 - 文件路径
准备步骤
- 为您的应用创建目录
- 导航到您的目录
cd <name of dir>
- 创建应用程序文件,现在创建一个包含您的代码的 JavaScript 文件,建议是
app.js
- 创建我们可以打开的文件,在同一目录中创建一个文件
info.txt
,并根据需要为其提供一些示例数据
信息
将以下代码添加到您创建的应用程序文件中。
const path = require("path");
const filePath = '/path/to/file.txt';
console.log(`Base name ${path.basename(filePath)}`);
console.log(`Dir name ${path.dirname(filePath)}`);
console.log(`Extension name ${path.extname(filePath)}`);
现在使用以下命令运行此代码:
node <name of your app file>.js
这应该产生以下输出
Base name file.txt
Dir name /path/to
Extension name .txt
上面我们可以看到方法basename()
,dirname()
和如何extname()
帮助我们检查路径以给我们提供不同的信息。
连接路径
在这里我们将研究连接路径的不同方式。
将以下代码添加到您现有的应用程序文件中:
const join = '/path';
const joinArg = '/to/my/file.txt';
console.log(`Joined ${path.join(join, joinArg)}`);
console.log(`Concat ${path.join(join, 'user','files','file.txt')}`)
上面我们连接了变量中包含的路径join
,joinArg
但在最后一个例子中,我们还测试了仅使用目录名和文件名进行连接:
console.log(`Concat ${path.join(join, 'user','files','file.txt')}`)
现在使用以下命令运行
node <name of your app file>.js
这应该给出以下输出:
Joined /path/to/my/file.txt
Concat /path/user/files/file.txt
这里的要点是,我们可以用该join()
方法连接不同的路径。但是,由于我们不知道我们的应用是否会在 Linux 或 Windows 主机上运行,因此我们最好只使用目录和文件名来构造路径,如下所示:
console.log(`Concat ${path.join(join, 'user','files','file.txt')}`)
绝对路径
将以下内容添加到我们的应用程序文件中:
console.log(`Abs path ${path.resolve(joinArg)}`);
console.log(`Abs path ${path.resolve("info.txt")}`);
现在使用以下命令运行
node <name of your app file>.js
这应该给出以下输出:
Abs path /to/my/file.txt
Abs path <this is specific to your system>/info.txt
请注意,在第二个示例中,我们如何在运行代码时对位于同一目录中resolve()
的文件使用该方法:info.txt
console.log(`Abs path ${path.resolve("info.txt")}`);
上述操作将尝试解析文件的绝对路径。
规范化路径
有时我们的路径中会包含像./
或这样的字符../
。该方法normalize()
可以帮助我们计算最终路径。将以下代码添加到我们的应用程序文件中:
console.log(`Normalize ${path.normalize('/path/to/file/../')}`)
现在使用以下命令运行
node <name of your app file>.js
这应该给出以下输出:
Normalize /path/to/
使用文件和目录
与文件系统交互时您可以做很多事情,例如:
- 读/写文件和目录
- 读取文件统计信息
- 使用权限
你可以使用内置模块与文件系统交互fs
。要使用它,请导入它,如下所示:
const fs = require('fs')
I/O操作
以下是您可以对模块上存在的文件/目录执行的一系列操作fs
。
readFile()
,异步读取文件内容appendFile()
,如果文件存在,则将数据添加到文件,如果不存在,则先创建文件copyFile()
,复制文件readdir()
,读取目录的内容mkdir()
,创建一个新目录,rename()
,重命名文件或文件夹,stat()
返回文件的统计信息,例如文件创建时间、文件大小(以字节为单位)以及其他信息,access()
,检查文件是否存在以及是否可以访问
以上所有方法也都存在同步版本。您只需要在Sync
末尾附加 即可,例如readFileSync()
。
异步/同步
所有操作都以同步和异步形式存在。Node.js 是单线程的。因此,运行同步操作的后果是,我们会阻止其他任何操作的发生。这会导致吞吐量远低于以异步方式编写的应用程序。
同步操作
在同步操作中,你实际上阻止了其他任何操作的发生,这可能会降低程序的响应速度。同步文件操作应该将sync作为操作名称的一部分,如下所示:
const fileContent = fs.readFileSync('/path/to/file/file.txt', 'utf8');
console.log(fileContent);
异步操作
异步操作是非阻塞的。Node.js 处理异步操作的方式是使用回调模型。本质上,Node.js 不会等待操作完成。您可以提供一个回调函数,该函数将在操作完成后被调用。这就产生了所谓的回调模式。
下面是打开文件的示例:
const fs = require('fs');
fs.open('/path/to/file/file.txt', 'r', (err, fileContent) => {
if (err) throw err;
fs.close(fd, (err) => {
if (err) throw err;
});
});
上面我们看到了如何提供一个函数作为第三个参数。该函数本身将错误err
作为第一个参数。第二个参数通常是操作结果的数据,在本例中是文件内容。
演示 - 文件和目录
在本练习中,我们将学习如何使用模块fs
来执行以下操作:
- 读/写文件,我们将学习如何以异步和同步的方式进行操作
- 列出统计数据,我们将学习如何列出文件的统计信息
- 打开目录,这里我们将学习如何打开目录并列出其文件内容
准备步骤
- 为您的应用创建目录
- 导航到您的目录
cd <name of dir>
- 创建应用程序文件,现在创建一个包含代码的 JavaScript 文件,建议
app.js
- 示例文件,在同一目录中创建一个文件,
info.txt
并根据需要为其提供一些示例数据 - 创建一个包含内容的子目录,在同一目录中创建一个文件夹
sub
并在其中创建文件a.txt
,b.txt
现在c.txt
您的目录结构应如下所示:
app.js
info.txt
sub -|
---| a.txt
---| b.txt
---| c.txt
读/写文件
app.js
首先,在文件顶部添加以下内容:
const fs = require('fs');
const path = require('path');
现在我们将主要使用模块fs
,但在后面的练习中我们将需要模块path
来帮助我们构建路径。
现在,将以下内容添加到app.js
:
try {
const fileContent = fs.readFileSync('info.txt', {
encoding: 'utf8'
});
console.log(`Sync Content: ${fileContent}`);
} catch (exception) {
console.error(`Sync Err: ${exception.message}`);
}
console.log('After sync call');
上面我们使用了同步版本来打开文件。我们可以通过使用以sync结尾的方法来实现这一点。
接下来添加异步版本,如下所示:
fs.readFile('info.txt', (err, data) => {
if (err) {
console.log(`Async Error: ${err.message}`);
} else {
console.log(`Async Content: ${data}`);
}
})
console.log('After async call');
现在使用以下命令运行此代码:
node <name of your app file>.js
这应该产生以下输出
Sync Content: info
After sync call
After async call
Async Content: info
请注意,上面的文本After sync call
是如何在同步调用中列出文件内容之后立即打印的。另外,请注意文本是如何在之前After async call
打印的。这意味着任何异步操作都是最后发生的。这是关于异步操作的一个重要认识,它们可能是非阻塞的,但它们不会立即完成。因此,如果顺序很重要,你应该考虑像 Promises 和 Async/await 这样的结构。 Async Content: info
列出统计数据
出于各种原因,您可能希望列出特定文件/目录的详细信息。为此,我们提供了stat()
方法。该方法也提供异步/同步版本。
要使用它,请添加以下代码:
fs.stat('info.txt', (err, stats) => {
if (err) {
console.error(`Err ${err.message} `);
} else {
const { size, mode, mtime } = stats;
console.log(`Size ${size}`);
console.log(`Mode ${mode}`);
console.log(`MTime ${mtime}`);
console.log(`Is directory ${stats.isDirectory()}`);
console.log(`Is file ${stats.isFile()}`);
}
})
现在使用以下命令运行此代码:
node <name of your app file>.js
这应该产生以下输出
Size 4
Mode 33188
MTime Mon Mar 16 2020 19:04:31 GMT+0100 (Central European Standard Time)
Is directory false
Is file true
上述结果可能会有所不同,具体取决于文件中的内容info.txt
以及创建时间。
打开目录
最后,我们将使用方法打开一个目录readdir()
。这将生成指定目录中包含的文件/目录数组:
fs.readdir(path.join(__dirname, 'sub'), (err, files) => {
if (err) {
console.error(`Err: ${err.message}`)
} else {
files.forEach(file => {
console.log(`Open dir, File ${file}`);
})
}
})
join()
上面我们使用模块中的方法构建目录路径path
,如下所示:
path.join(__dirname, 'sub')
__dirname
是一个内置变量,表示执行目录。该方法调用意味着我们将查看sub
相对于代码执行位置的目录。
现在使用以下命令运行此代码:
node <name of your app file>.js
这应该产生以下输出
Open dir, File a.txt
Open dir, File b.txt
Open dir, File c.txt
概括
总的来说,我们涵盖了以下领域:
- 路径,我们已经了解了如何使用内置
path
模块处理路径 - 文件和目录,我们已经了解了如何使用
fs
模块来创建、更新、删除、移动等文件和目录。
这个领域还有很多东西需要学习,我强烈建议您查看本文的参考部分以了解更多信息。
文章来源:https://dev.to/itnext/how-you-can-learn-node-js-io-files-and-paths-2473