Node-文件操作(下)- 文件监视、markdown转换器

监视

文件监视 API fs.watchFile()

  • 回调函数中需要接收两个参数
  • 第一个是当前文件的最新状态 stat,
  • 第二个是变化之前的 stat
1
2
3
4
5
6
const fs = require('fs');
// 监视文件的修改时间
fs.watchFile('./node.md', (curr, prev) => {
console.log(curr.mtime.getHours() + ':' + curr.mtime.getMinutes() + ':' +curr.mtime.getSeconds());
console.log(prev.mtime.getHours() + ':' + prev.mtime.getMinutes() + ':' +prev.mtime.getSeconds());
});

使用模板引擎时需要注意的地方

1
2
3
4
5
6
7
8
9
10
11
const template = require('art-template');
// 1. 调用 template.compile 方法,传入一个模板字符串,得到一个渲染函数
// # 表示不编码输出
const render = template.compile(`
<h1>{{# title }}</h1>
`);
// 防止用户恶意注入 JavaScript 代码
const result = render({
title: '<span>hello</span>'
});
console.log(result);

在 node 中使用模板引擎

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const template = require('art-template');
// 这是 art-template 的简洁语法
const render = template.compile(`
<h1>{{title}}</h1>
<ul>
{{each list as value i}}
<li>索引{{i}}:{{value}}</li>
{{/each}}
</ul>
`);
const result = render({
title: 'node 中使用模板引擎',
list: [
'a', 'b', 'c'
]
});
console.log(result);

以上这段代码的模板是手写到代码中的,我们可以通过文件读取的方式获得模板

正真想用原生语法,就需要加载另一个native 文件,修改的入口文件: art-tempalte 文件下的package.json, main:”./node/template-native.js”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const template = require('art-template');
// 这是 art-template 的原生语法
const render = template.compile(`
<h1><%= title %></h1>
<ul>
</ul>
`);
const result = render({
title: 'node 中使用模板引擎',
list: [
'a', 'b', 'c'
]
});
console.log(result);

模板字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type=""></style>
</head>
<body>
<h1>{{ title }}</h1>
<article class="markdown-body">
{{# body }}
</article>
</body>
</html>

markdown 文件自动生成 HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const fs = require('fs');
const marked = require('marked');
const template = require('art-template');
// { persistent: true, interval: 1000 } 修改间隔时间
fs.watchFile('./node.md', { persistent: true, interval: 1000 }, (curr, prev) => {
fs.readFile('./node.md', (err, md) => {
if (err) {
throw err;
}
// 拿到文件数据,将 Markdown 格式字符串转换为 HTML 格式字符串
const htmlStr = marked(md.toString());
fs.readFile('./template.html', 'utf8', (err, tmp) => {
if (err) {
throw err;
}
// 使用 art-template 模板引擎编译解析
const result = template.compile(tmp)({
textTitle: 'node 学习',
title: 'node 学习',
body: htmlStr,
});
// 写入要生成的文件中
fs.writeFile('./node.html', result, err => {
if (err) {
throw err;
}
console.log('translate success');
});
});
});
});

最后, art-template 模板既可以在浏览器中使用还可以在 node 中使用,注意:

  • node 中使用时,看 node-modules 文件下 art-template 文件下的 package.json 文件,该文件中的 main 属性就是 node 使用 art-template 模板所使用包的路径。
  • 在浏览器中使用时,引入的 art-template 包是 dist 目录下的 art-template.js 文件。

读 execl 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const parseXlsx = require('excel');
const moment = require('moment');
parseXlsx('./data/课表.xlsx', (err, data) => {
if (err) {
throw err;
}
// 解析 excel 表格日期
// var date = new Date((42628 - (25567 + 1)) * 86400 * 1000)
// // 在原有日期 - 1 天
// date = moment(date).add(-1, 'days').format('YYYY-MM-DD'))
for (let day of data) {
if (day[1].trim().length > 0) {
if (day[1].includes('周淑刚')) {
console.log(moment(new Date((parseInt(day[0]) - (25567 + 1)) * 86400 * 1000)).add(-1, 'days').format('YYYY-MM-DD'), day[1])
}
}
}
})

文件流

读取大文件,使用流的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const fs= require('fs');
const src = '';
const des = '';
// 创建一个可读流
// 2. 创建一个可写流
// 3. 更新可毒瘤对象的 data 事件
// 只要流对象已经过创建成功,先一瓢一瓢的读取数据
// 当读取到一定数据的时候,触发 data 事件, 同时将数据传递给回调函数
// 只要度去掉一个点数据,就调用可写流对象的 write 方法,将数据写入到可写流中
// 4. 监听可读流对象的 end 事件
// 当以流的形式读取数据之后,会触发可读流对象的 end 事件
// 使用可写流的 end 方法将可写流关闭
const readStream = fs.createReadStream(src);
const writeStream = fs.createWriteStream(des);
// 获取要读取文件的总字节大小
const totalSize = fs.statSync(src).size;
// 用来统计最新读取到的数据字节数
const currentSize = 0;
readStream.on('data', data => {
console.log(`${((currentSize += data.length) / totalSize * 100).toFixed(2)}%10`);
writeStream.write(data);
});
readStream.on('end', () => {
console.log('复制文结束');
writeStream.end();
});

使用管道方法读写大文件;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const readStream = fs.createReadStrean(src);
const writeStream = fs.createWriteStream(des);
const fs= require('fs');
const src = '';
const des = '';
// 获取要读取文件的总字节大小
const totalSize = fs.statSync(src).size;
// 用来统计最新读取到的数据字节数
const currentSize = 0;
readStream.on('data', data => {
console.log(`${((currentSize += data.length) / totalSize * 100).toFixed(2)}%10`);
writeStream.write(data);
});
// 将可读流通过 pipe 方法,数据自动流入指定的可写流中
readStream.pipe(writeStream);

涉及的包

  • moment:时间处理
  • fs-extra:扩展了原生 fs 模块的功能,例如删除一个非空目录,递归遍历无极目录等
  • marked:Markdown转换
  • art-template:模板引擎
  • excel:读取excel表格文件数据
  • nodemon: 监听文件变化,自动重启
    • npm install -g nodemon
    • nodemon server.js
    • 该工具会监听文件的变化,使用 node 重新执行对应的脚本文件
感谢您的支持!