一、node文件讀寫
Node.js讀取文件函數(shù)語法如下:
?
1. 異步讀文件
fs.readFile(filename,[encoding],[callback(err,data)])
- filename(必選),表示要讀取的文件名。
- encoding(可選),表示文件的字符編碼。
- callback 是回調(diào)函數(shù),用于接收文件的內(nèi)容。
示例:
var fs=require('fs');
fs.readFile('./data/result.txt', 'utf-8', function (err, stdout) {
if (err) {
console.log('文件讀取失敗');
} else {
console.log('文件讀取成功');
res.render('index', {
input: description,
content: stdout,
})
console.log('stdout:', stdout);
stdout = '';
}
});
?
PS:read和readFile比較
read 是不斷地將文件中的一小塊內(nèi)容讀入緩存區(qū),最后從該緩存區(qū)中讀取文件內(nèi)容,
而readFile 則是將文件一次性讀取完畢,如果文件較大,則會(huì)出現(xiàn)"爆倉"。
?
2.異步寫文件
fs.writeFile(filename,data,[options],callback)
- filename:要寫入的文件
- data:寫入文件的數(shù)據(jù)可以是字符串,可以是buffer
- options:flag:對(duì)寫入文件的操作默認(rèn)為w,encoding:編碼,mode:權(quán)限
- callback:回調(diào)函數(shù)
?
以下介紹下常見的文件的操作 flag, 詳細(xì)文件操作區(qū)別請(qǐng)看這篇文章
? flag: w -- 新建只寫(以 w 方式打開,不能讀出,w+ 可讀寫)
? ? ? ? ? ? ? a -- 附加寫方式?(a:附加寫方式打開,不可讀;a+:?附加讀寫方式打開)
? 如果文件不存在會(huì)創(chuàng)建新文件的打開方式:a,a+,w,w+,而? r 和 U 要求文件必須存在
?
示例:
// 引入fs
var fs = require("fs");
// 獲取用戶提交的內(nèi)容
var description = req.body.description;
// 寫入文件
fs.writeFile('./data/text.txt', description, {
flag: 'w',
encoding: 'utf-8',
mode: '0666'
}, function (err) {
if (err) {
console.log("文件寫入失敗")
} else {
console.log("文件寫入成功");
}
});
3.同步讀寫文件
var date = fs.readFileSync('log.txt','utf-8');
fs.writeFileSync('output.txt', JSON.stringify(obj, null, '\t'));
?
4.同步與異步讀寫的區(qū)別
? 同步會(huì)阻塞,阻塞時(shí),代碼不能做其它的事情,需要等待當(dāng)前代碼執(zhí)行完畢, 而異步則無需等待當(dāng)前代碼執(zhí)行完畢。
?
二、node執(zhí)行python文件
?
1.?child_process介紹
Node.js 是以單線程的模式運(yùn)行的,但它使用的是事件驅(qū)動(dòng)來處理并發(fā)。這樣有助于我們?cè)诙嗪?cpu 的系統(tǒng)上創(chuàng)建多個(gè)子進(jìn)程,并使用主進(jìn)程和子進(jìn)程之間實(shí)現(xiàn)通信,從而提高性能。
每個(gè)子進(jìn)程總是帶有三個(gè)流對(duì)象:child.stdin, child.stdout 和child.stderr。他們可能會(huì)共享父進(jìn)程的 stdio 流,或者也可以是獨(dú)立的被導(dǎo)流的流對(duì)象。
Node
提供了?child_process
?模塊來創(chuàng)建子進(jìn)程。
?
2. 創(chuàng)建子進(jìn)程方法
-
exec-child_process.exec? ? ? ? ?
使用子進(jìn)程執(zhí)行命令,緩存子進(jìn)程的輸出,并將子進(jìn)程的輸出以回調(diào)函數(shù)的形式返回。
示例:
var child_process = require('child_process');
var workerProcess = child_process.exec('python3 test.py '+i, function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
});
workerProcess.on('exit', function (code) {
console.log('子進(jìn)程已退出,退出碼 '+code);
});
?
-
spawn-child_process.spawn? ?
使用指定的命令行參數(shù)創(chuàng)建進(jìn)程。
示例:
var child_process = require('child_process');
var workerProcess = child_process.spawn('python3', ['test.py']);
workerProcess.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
workerProcess.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
workerProcess.on('close', function (code) {
console.log('子進(jìn)程已退出,退出碼 ' + code);
});
?
-
fork-child_process.fork? ? ? ? ? ? ?
是spawn()的特殊形式,用于在子進(jìn)程中運(yùn)行模塊,與spawn方法不同的是,fork會(huì)在父進(jìn)程與子進(jìn)程之間,建立一個(gè)通信管道,用于進(jìn)程之間的通信。
暫無示例
?
3. 比較exec和spawn
- exec將子進(jìn)程輸出結(jié)果暫放在buffer中,在結(jié)果完全返回后,再將輸出一次性的以回調(diào)函數(shù)返回。如果exec的buffer體積設(shè)置的不夠大,它將會(huì)以一個(gè)“maxBuffer exceeded”錯(cuò)誤失敗告終。而spawn在子進(jìn)程開始執(zhí)行后,就不斷的將數(shù)據(jù)從子進(jìn)程返回給主進(jìn)程,它沒有回調(diào)函數(shù),它通過流的方式發(fā)數(shù)據(jù)傳給主進(jìn)程,從而實(shí)現(xiàn)了多進(jìn)程之間的數(shù)據(jù)交換。
-
書寫上,exec更方便一些,將整個(gè)命令放在第一個(gè)參數(shù)中,而spqwn需要拆分。
child_process.spawn('python3', ['test.py', i])
child_process.exec('python3 test.py '+i, callback)
- exec比spawn多了一些默認(rèn)的option
?
4.解決 Error: maxBuffer exceeded
?
問題描述:
在使用子進(jìn)程期間遇到了問題?Error: stderr maxBuffer exceeded ,然后 子進(jìn)程掛掉。
?
原因:
讓我們從源碼上解釋子進(jìn)程為什么子進(jìn)程會(huì)掛掉?
child.stderr.addListener('data', function(chunk) {
stderrLen += chunk.length;
if (stderrLen > options.maxBuffer) {
ex = new Error('stderr maxBuffer exceeded.');
kill();
} else {
if (!encoding)
_stderr.push(chunk);
else
_stderr += chunk;
}
});
以上代碼邏輯:
記錄子進(jìn)程的log大小,一旦超過
maxBuffer
就
kill
掉子進(jìn)程。
而當(dāng)我們?cè)谑褂?
exec
時(shí),不知道設(shè)置
maxBuffer
,默認(rèn)的
maxBuffer
是200K,當(dāng)我們子進(jìn)程日志達(dá)到200K時(shí),自動(dòng)
kill()
掉了。
// exec 默認(rèn)的參數(shù)
var options = {
encoding: 'utf8',
timeout: 0,
maxBuffer: 200 * 1024,
killSignal: 'SIGTERM',
cwd: null,
env: null
};
?
解決方案
知道上面原因了,解決方案就有幾個(gè)了:
- 子進(jìn)程的系統(tǒng),不再輸出日志
- maxBuffer這個(gè)傳一個(gè)足夠大的參數(shù)
- 直接使用spawn,放棄使用exec
我這里采用的是第三種直接使用
spawn
,解除
maxBuffer
的限制,個(gè)人覺得最優(yōu)的方案。因?yàn)閑xec本身就是
?
結(jié)束
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
