引言
今天带来的是狗屁不通文章生成器第一部分,即输入一个文章题目,和相应的字数,便自动生成一篇对应字数的文章。
如上图
那么这么好玩的文章生成器是怎么制作的,接下来带大家制作这个文章生成器
准备
首先创建一个文件夹article,然后切换到article目录下,调出cmd,执行如下代码完成项目的初始化
npm init -y
它会在项目目录下生成一个 pacakge.json 文件,我们用ide打开这个文件夹,可以看到文件夹中有一个package.json的文件,文件中内容如下
模块管理
众所周知,在模块管理上,Node.js有CommonJS和ES Modules两种标准,这里我采用ES Modules标准来撰写项目。但是默认初始化的node项目采取了CommonJS的模式,所以我们要在package.json进行配置
在package.json中 加入"type"="moudle"
最终package.json配置文件内容如下:
{
"name": "article",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module"
}
准备工作告一段落,接下来进入下一阶段
fs模块进行读取文件
文章生成器的核心功能的实现其实是通过读取后台的语料库,读取功能我们可以通过fs模块来实现
fs的导入
fs是node的一个内置的模块,我们不需要通过npm来下载,我们这个项目采取的是ES Modules标准,所以我们通过import导入fs模块
import fs from 'fs'
完成对fs模块的导入
接下来我们尝试运用fs模块进行文件的读写。
fs读取文件
我们首先在项目目录中创建ceshi.txt,并在其中随便放置一些文字。
然后在项目中创建src目录,并在src目录下创建一个index.js的js文件
文件目录如下:
接下来我们开始编辑index.js文件,在首行导入fs模块(ES Modules)
fs读取文件可以通过fs.readFile()来进行
代码如下
import fs from 'fs';
fs.readFile('../ceshi.txt',(err,dataStr)=>{
if(err){
console.log(err);
}
else{
console.log(dataStr);
}
})
这几行代码很好理解,因为我们采取ES Modules标准,所以我们通过import来导入所需的fs模块
然后调用fs.readFile()函数,第一个函数填写要读取的路径,我这里采用相对路径的方式,通过../找到src的上一级,再找到ceshi.txt文件,完成读取。
第二个参数我写了一个函数,分别有err和dataStr两个参数,如果读取的时候出现了error,那么error非空则会打印出错误信息,否则没有error,error=null,不会触发打印错误,而是打印读取的dataStr。
接下来我们在控制台,从article目录切换到下一级的src目录,在控制台执行cd src
,然后通过node index.js执行代码,完成读取。一定要切换,否则会报出找不到文件的error,解决方案和问题下面再说。
可以看到,读出来的并不是我们期望的“让我们试一下fs模块好不好用。”而是一大堆字节。那么我们如何解决这个问题呢?这里提供了四种解决方案。
方案一
隐式调用转换字符,将原本的console.log(dataStr);
改为console.log(dataStr+"");
成功打印出所期望的文件内容
方案二
显式调用toString()方法
在打印之前,调用toString()函数,完成字节到字符串的转换
else{
dataStr = dataStr.toString();
console.log(dataStr);
}
成功打印出期望字符。
方案三
通过String()的强制类型转换,完成字节到字符的转换
else{
dataStr = String(dataStr);
console.log(dataStr);
}
也是可以成功解决
方案四
直接指定读取文件时的编码,来直接读取字符串
import fs from 'fs';
fs.readFile('../ceshi.txt',{encoding:"utf-8"},(err,dataStr)=>{
if(err){
console.log(err);
}
else{
console.log(dataStr);
}
})
此时读出的dataStr就是我们期望的字符串了
fs读取文件的路径问题及解决方案
上面说过,我们要启动src目录下的index.js必须要先切换到src目录下,再使用node index.js来启动index.js文件,而不能直接执行node src/index.js。
那么这是为什么呢?
原来fs的读文件是针对于当前目录,受启动的环境位置影响。我们在article目录下直接启动
node src/index.js
虽然同样能找到 article/src/index.js,但此时../的路径是相对于article的上一级,所以无法找到ceshi.txt,那么有没有什么解决方案,让我能在任意地方启动js并且还能读取到文件呢?
解决方案一
将readFile中的路径参数由相对路径改为绝对路径。(不推荐)
解决方案二
通过import,meta.url获取一下文件
获取到的结果是: file:///D:/VScodefile3/article/src/index.js
接下来在导入中引入 fileURLToPath 函数
import {fileURLToPath} from 'url';
通过impoort.meta.url获取的路径并不能直接使用,我们使用fileURLToPath()函数进行处理
const pathURL = fileURLToPath(fileURL);
打印一下,结果是D:\VScodefile3\article\src\index.js
接下来我们导入path模块处理
import path from path;
const dirname = path.resolve(pathURL,"../");
通过resolve可以拼接路径并自动处理,上述的dirname的结果是D:\VScodefile3\article\src
已经找到了index.js的所在目录,接下来我们可以继续定位到dirname的上一级,从而找到article目录,继而找到article目录下的ceshi.txt
import fs from 'fs';
import {fileURLToPath} from 'url';
import path from 'path';
const fileURL = import.meta.url;
const pathURL = fileURLToPath(fileURL);
const dirname = path.resolve(pathURL,"../");
const filePath = path.resolve(dirname,"../","ceshi.txt");
fs.readFile(filePath,{encoding:"utf-8"},(err,dataStr)=>{
if(err){
console.log(err);
}
else{
console.log(dataStr);
}
})
最终解决版本如上,下面我们在任意目录中启动index.js都可以找到要读取的ceshi.txt。
第一部分完成,下一文章继续更新这个文章生成器。