2016-07-22 24 views
6

Ist es möglich, CLI-Tools wie pdftotext, antiword, catdoc (Text Extractor Scripts) aufzurufen und statt einer Datei eine Zeichenfolge zu übergeben?Übergeben von im Speicher gespeicherten Zeichenfolgen an pdftotext, antiword, catdoc usw.

Derzeit lese ich PDF-Dateien mit dem Aufruf pdftotext mit child_process.spawn. Ich spawn einen neuen Prozess und speichern das Ergebnis in einer neuen Variablen. Alles funktioniert gut.

Ich möchte die binary von einem fs.readFile statt der Datei selbst zu übergeben:

fs.readFile('./my.pdf', (error, binary) => { 
    // Call pdftotext with child_process.spawn passing the binary. 
    let event = child_process.spawn('pdftotext', [ 
     // Args here! 
    ]); 
}); 

Wie kann ich das tun?

Antwort

2

Es ist definitiv möglich, wenn der Befehl Piped-Input verarbeiten kann.

spawn gibt ein Objekt ChildProcess zurück, Sie können die Zeichenfolge (oder Binärdatei) im Speicher an es übergeben, indem Sie an seine stdin schreiben. Die Zeichenfolge sollte zuerst converted zu einer ReadableStream werden, dann können Sie die Zeichenfolge stdin der CLI von pipe schreiben.

createReadStream erstellt eine ReadableStream aus einer Datei.

Im folgenden Beispiel laden Sie eine PDF-Datei herunter und leiten Sie den Inhalt an pdftotext, dann zeigen Sie die ersten paar Bytes des Ergebnisses.

const source = 'http://static.googleusercontent.com/media/research.google.com/en//archive/gfs-sosp2003.pdf' 
const http = require('http') 
const spawn = require('child_process').spawn 

download(source).then(pdftotext) 
.then(result => console.log(result.slice(0, 77))) 

function download(url) { 
    return new Promise(resolve => http.get(url, resolve)) 
} 

function pdftotext(binaryStream) { 
    //read input from stdin and write to stdout 
    const command = spawn('pdftotext', ['-', '-']) 
    binaryStream.pipe(command.stdin) 

    return new Promise(resolve => { 
    const result = [] 
    command.stdout.on('data', chunk => result.push(chunk.toString())) 
    command.stdout.on('end',() => resolve(result.join(''))) 
    }) 
} 

Für CLIs keine andere Wahl von stdin zu lesen, können Sie named pipes verwenden.

Bearbeiten: Fügen Sie ein weiteres Beispiel mit Named Pipes hinzu.

Sobald die Named Pipes erstellt sind, können Sie sie wie Dateien verwenden. Im folgenden Beispiel werden temporäre benannte Pipes erstellt, um Eingaben zu senden und Ausgaben zu erhalten. Außerdem werden die ersten paar Bytes des Ergebnisses angezeigt.

const fs = require('fs') 
const spawn = require('child_process').spawn 

pipeCommand({ 
    name: 'wvText', 
    input: fs.createReadStream('document.doc'), 
}).then(result => console.log(result.slice(0, 77))) 

function createPipe(name) { 
    return new Promise(resolve => 
    spawn('mkfifo', [name]).on('exit',() => resolve())) 
} 

function pipeCommand({name, input}) { 
    const inpipe = 'input.pipe' 
    const outpipe = 'output.pipe' 
    return Promise.all([inpipe, outpipe].map(createPipe)).then(() => { 
    const result = [] 
    fs.createReadStream(outpipe) 
    .on('data', chunk => result.push(chunk.toString())) 
    .on('error', console.log) 

    const command = spawn(name, [inpipe, outpipe]).on('error', console.log) 
    input.pipe(fs.createWriteStream(inpipe).on('error', console.log)) 
    return new Promise(resolve => 
     command.on('exit',() => { 
     [inpipe, outpipe].forEach(name => fs.unlink(name)) 
     resolve(result.join('')) 
     })) 
    }) 
} 
+0

Hei @DarkKnight, tranks viel !! Wenn ich nicht zu viel frage, können Sie ein Arbeitsbeispiel mit Named Pipes bereitstellen? Es stellt sich heraus, dass ich andere Skripte verwende, die die andere Methode nicht unterstützen. –

+0

Frage *, Beispiel * –

+0

Alle von Ihnen erwähnten Werkzeuge können 'stdin' durch Angabe von' -' akzeptieren. Ich habe trotzdem ein anderes Beispiel hinzugefügt. – DarkKnight