为什么要使用流?
当读取/写入一个很大文件的时候,会占用很大的内存。为了节约内存降低开销,我们引入流让数据像水流一样一点一点写入
如何使用流?
Stream流
const fs = require('fs')
const stream = fs.createWriteStream('./big_file.txt')
for(let i=0; i<=10000; i++){
stream.write(`这是第 ${i} 行内容,我们有一堆内容!!!`)
}
stream.end() // 别忘了关掉 stream
console.log('done')
pipe管道
stream1.pipe(stream2)
a.pipe(b).pipe(c) // 链式操作,等价于下面
a.pipe(b)
b.pipe(c)
Stream分类
名称 | 特点 |
---|---|
Readable | 可读 |
Writable | 可写 |
Duplex | 可读可写(双向) |
Transform | 可读可写(变化) |
Nodejs中的Stream
子进程 child_process
断点
node --inspect-brk 4.js // 设置断点
随便打开一个网页后等到出现这个标志,点开后设置断点并运行
const fs = require('fs')
function writeOneMillionTimes(writer, data) {
let i = 10000;
write();
function write() {
let ok = true;
do {
i--;
if (i === 0) {
writer.write(data);
} else {
ok = writer.write(data);
if (ok === false) {
console.log('不能在写了')
}
}
} while (i > 0 && ok);
if (i > 0) {
writer.once('drain', () => {
console.log('干涸了')
write()
});
}
}
}
const writer = fs.createWriteStream('./big_file.txt')
writeOneMillionTimes(writer, 'hellow world')
exec(cmd, options, fn) 【一般不允许用,因为容易让用户输入不合适的命令导致出错(注入风险)】
const child_process = require('child_process')
const { exec } = child_process
exec('ls ../', (error, stdout, stderr) => {
console.log(error)
console.log(stdout)
console.log(stderr)
})
流
const child_process = require('child_process')
const { exec } = child_process
const streams = exec('ls -l ../')
streams.stdout.on('data', (chunk) => {
console.log(chunk)
})
streams.stdout.on('data')
Promise
const util = require("util")
const child_process = require('child_process')
const { exec } = child_process
const exec2 = util.promisify(exec)
exec2('ls ../').then((data) => {
console.log(data.stdout)
})
漏洞
const util = require("util")
const child_process = require('child_process')
const { exec } = child_process
const exec2 = util.promisify(exec)
const useInput = '. && rm -f /'
exec2(`ls ${userInput}`).then((data) => {
console.log(data.stdout)
})
execFile 【比较推荐使用】
const child_process = require('child_process')
const { execFile } = child_process
const useInput = "."
execFile("ls", ["-la", useInput], (error, stdout) => {
console.log(stdout)
})
options
spawn 【推荐使用,能用这个就不用execFile】
可以创建一个进程并获取结果,只支持流的形式获取结果
const child_process = require('child_process')
const { spawn } = child_process
const useInput = "."
const streams = spawn("ls", ["-la", useInput], {
cwd: 'C:\\',
env: { NODE_ENV: 'development' }
})
streams.stdout.on('data', (chunk) => {
console.log(chunk.toString())
})