7zip stdout坏了吗?有没有办法捕获nodejs的进度? [视窗]

时间:2014-09-06 03:28:22

标签: node.js 7zip

我正在尝试获取7zip的stdout,当它处理文件并获得nodeJs中的百分比时,但它没有按预期运行。 7zip在执行结束之前不会向stdout 输出任何内容。哪个不是很有用..尤其是当我压缩大文件并且很长时间没有显示反馈时。

我正在使用的代码(简化):

// 7zip test, place the 7z.exe in the same dir, if it's not on %PATH%
var cp = require('child_process');
var inputFile = process.argv[2]; if(inputFile==null) return;
var regProgress = /(\d{1,3})%\s*$/; //get the last percentage of the string, 3 digits
var proc = cp.spawn("7z.exe",["a","-t7z" ,"-y" ,inputFile + ".7z",inputFile]);
proc.stdout.setEncoding("utf8");
proc.stdout.on("data",function(data){
    if(regProgress.test(data))
    console.log("Progress = " + regProgress.exec(data)[1] + "%");
});
proc.once("exit",function(exit,sig){ console.log("Complete"); });

我已经使用相同的代码来成功获得WinRar的百分比,我开始认为 7zip可能是错误的?或者我做错了?我可以用计时器强行读取进程的标准输出吗?

上面的相同代码,除了替换的以下行,与WinRar一样正常工作。

var proc = cp.spawn("Rar.exe",["a","-s","-ma5","-o+",inputFile+".rar",inputFile]);

如果有人知道为什么会这样,如果可以解决,我将不胜感激! : - )

P.S。我已经尝试了7zip的命令行版本7za.exe,还有稳定版,beta版和alpha版,它们都有相同的问题

2 个答案:

答案 0 :(得分:1)

7-zip仅在stdout为终端时输出进度。

要欺骗7-zip,您需要npm install pty.js(需要Visual Studio或VS Express与Windows SDK),然后使用以下代码:

var pty = require('pty');

var inputFile = process.argv[2],
    pathTo7zip = 'c:\\Program Files\\7-Zip\\7z.exe';

if (inputFile == null)
  return;

var term = pty.spawn(process.env.ComSpec, [], {
  name: 'ansi',
  cols: 200,
  rows: 30,
  cwd: process.env.HOME,
  env: process.env
});

var rePrg = /(\d{1,3})%\r\n?/g,
    reEsc = /\u001b\[\w{2}/g,
    reCwd = new RegExp('^' + process.cwd().replace(/\\/g, '\\\\'), 'm');
    prompts = 0,
    buffer = '';

term.on('data', function(data) {
  var m, idx;

  buffer += data;

  // remove terminal escape sequences
  buffer = buffer.replace(reEsc, '');

  // check for multiple progress indicators in the current buffer
  while (m = rePrg.exec(buffer)) {
    idx = m.index + m[0].length;
    console.log(m[1] + ' percent done!');
  }

  // check for the cmd.exe prompt
  if (m = reCwd.exec(buffer)) {
    if (++prompts === 2) {
      // command is done
      return term.kill();
    } else {
      // first prompt is before we started the actual 7-zip process
      if (idx === undefined) {
        // we didn't see a progress indicator, so make sure to truncate the
        // prompt from our buffer so that we don't accidentally detect the same
        // prompt twice
        buffer = buffer.substring(m.index + m[0].length);
        return;
      }
    }
  }

  // truncate the part of our buffer that we're done processing
  if (idx !== undefined)
    buffer = buffer.substring(idx);
});
term.write('"'
           + pathTo7zip
           + '" a -t7z -y "'
           + inputFile
           + '.7z" "'
           + inputFile
           + '"\r');

应该注意的是,7-zip并不总是在结束时输出100%。如果文件快速压缩,您可能只看到一个57%例如,因此您必须按照自己的意愿处理。

答案 1 :(得分:1)

不再需要使用像pty.js这样的终端模拟器,您可以将-bsp1传递给7z以强制将进度输出到标准输出。