style change attribute javascript node.js file-io

javascript - change - title css



¿Cómo NO dejar de leer el archivo al reunirse con EOF? (3)

No he examinado las partes internas de las secuencias de lectura de los archivos, pero es posible que no admitan la espera de que un archivo tenga más datos escritos. Sin embargo, el paquete fs definitivamente lo admite con su funcionalidad más básica.

Para explicar cómo funcionaría el seguimiento, he escrito una función tail algo hacky que leerá un archivo completo e invocará una devolución de llamada para cada línea (separada por /n solamente) y luego esperará a que el archivo tenga más líneas escritas. Tenga en cuenta que una forma más eficiente de hacer esto sería tener un buffer de línea de tamaño fijo y simplemente mezclar bytes en él (con un caso especial para líneas extremadamente largas), en lugar de modificar cadenas de JavaScript.

var fs = require(''fs''); function tail(path, callback) { var descriptor, bytes = 0, buffer = new Buffer(256), line = ''''; function parse(err, bytesRead, buffer) { if (err) { callback(err, null); return; } // Keep track of the bytes we have consumed already. bytes += bytesRead; // Combine the buffered line with the new string data. line += buffer.toString(''utf-8'', 0, bytesRead); var i = 0, j; while ((j = line.indexOf(''/n'', i)) != -1) { // Callback with a single line at a time. callback(null, line.substring(i, j)); // Skip the newline character. i = j + 1; } // Only keep the unparsed string contents for next iteration. line = line.substr(i); // Keep reading in the next tick (avoids CPU hogging). process.nextTick(read); } function read() { var stat = fs.fstatSync(descriptor); if (stat.size <= bytes) { // We''re currently at the end of the file. Check again in 500 ms. setTimeout(read, 500); return; } fs.read(descriptor, buffer, 0, buffer.length, bytes, parse); } fs.open(path, ''r'', function (err, fd) { if (err) { callback(err, null); } else { descriptor = fd; read(); } }); return {close: function close(callback) { fs.close(descriptor, callback); }}; } // This will tail the system log on a Mac. var t = tail(''/var/log/system.log'', function (err, line) { console.log(err, line); }); // Unceremoniously close the file handle after one minute. setTimeout(t.close, 60000);

Dicho todo esto, también deberías tratar de aprovechar la comunidad de NPM. Con algunas búsquedas, encontré el paquete tail-stream , que podría hacer lo que quiera, con streams.

Estoy tratando de implementar una rutina para Node.js que permitiría abrir un archivo, que se agrega a otro proceso en este momento, y luego devolver fragmentos de datos inmediatamente cuando se anexen al archivo. Se puede pensar que es similar al comando tail -f UNIX, pero actúa inmediatamente cuando hay fragmentos disponibles, en lugar de sondear los cambios a lo largo del tiempo. Alternativamente, uno puede pensar en esto como en trabajar con archivos como lo hace con socket - esperando que on(''data'') active de vez en cuando hasta que el archivo se cierre explícitamente.

En C land, si tuviera que implementar esto, simplemente abriría el archivo, alimentaría su descriptor de archivo para select() (o cualquier función alternativa con designación similar), y luego simplemente leería los fragmentos ya que el descriptor de archivo está marcado como "legible". Entonces, cuando no hay nada que leer, no será legible, y cuando algo se anexa al archivo, es legible de nuevo.

De alguna manera esperaba este tipo de comportamiento para el siguiente ejemplo de código en Javascript:

function readThatFile(filename) { const stream = fs.createReadStream(filename, { flags: ''r'', encoding: ''utf8'', autoClose: false // I thought this would prevent file closing on EOF too }); stream.on(''error'', function(err) { // handle error }); stream.on(''open'', function(fd) { // save fd, so I can close it later }); stream.on(''data'', function(chunk) { // process chunk // fs.close() if I no longer need this file }); }

Sin embargo, este ejemplo de código simplemente rescata cuando se encuentra EOF, por lo que no puedo esperar a que llegue un nuevo fragmento. Por supuesto, podría fs.open fs.read esto usando fs.open y fs.read , pero eso en cierto modo Node.js propósito de Node.js Alternativamente, podría fs.watch() archivo para cambios, pero no funcionará en la red, y no me gusta la idea de volver a abrir el archivo todo el tiempo en lugar de mantenerlo abierto.

Intenté hacer esto:

const fd = fs.openSync(filename, ''r''); // sync for readability'' sake const stream = net.Socket({ fd: fd, readable: true, writable: false });

Pero no tuvo suerte - net.Socket no está contento y lanza TypeError: Unsupported fd type: FILE .

Entonces, ¿alguna solución?


Las respuestas anteriores han mencionado el enfoque de tail-stream , que utiliza fs.watch, fs.read y fs.stat juntos para crear el efecto de transmitir el contenido del archivo. Puedes ver ese código en acción aquí .

Otro enfoque, quizás más hackier, podría ser simplemente usar cola al generar un proceso secundario con ella. Esto, por supuesto, viene con la limitación de que la cola debe existir en la plataforma objetivo, pero una de las fortalezas del nodo es usarla para hacer un desarrollo asíncrono de sistemas vía spawn e incluso en Windows, puede ejecutar un nodo en un shell alternativo como msysgit o cygwin para obtener acceso a la utilidad de cola.

El código para esto:

var spawn = require(''child_process'').spawn; var child = spawn(''tail'', [''-f'', ''my.log'']); child.stdout.on(''data'', function (data) { console.log(''tail output: '' + data); } ); child.stderr.on(''data'', function (data) { console.log(''err data: '' + data); } );


Lo que estás tratando de hacer es un archivo FIFO (acrónimo de First In First Out), que como dijiste funciona como un socket.

Hay un módulo node.js que le permite trabajar con archivos fifo .

No sé para qué quieres eso, pero hay mejores formas de trabajar con sockets en node.js. Pruebe socket.io en su lugar.

También podría echarle un vistazo a esta pregunta anterior: leer un archivo en tiempo real usando Node.js

Actualización 1

No estoy familiarizado con ningún módulo que pueda hacer lo que quiera con un archivo normal, en lugar de hacerlo con un socket de tipo uno. Pero como dijiste, podrías usar tail -f para hacer el truco:

// filename must exist at the time of running the script var filename = ''somefile.txt''; var spawn = require(''child_process'').spawn; var tail = spawn(''tail'', [''-f'', filename]); tail.stdout.on(''data'', function (data) { data = data.toString().replace(/^[/s]+/i,'''').replace(/[/s]+$/i,''''); console.log(data); });

Luego, desde la línea de comandos, pruebe echo someline > somefile.txt y mire en la consola.

También es posible que desee echar un vistazo a esto: https://github.com/layerssss/node-tailer