Eu preciso fazer uma análise de arquivos de log grandes (5-10 Gb) em Javascript / Node.js (estou usando o Cube).
A linha de log se parece com:
10:00:43.343423 I'm a friendly log message. There are 5 cats, and 7 dogs. We are in state "SUCCESS".
Precisamos ler cada linha, fazer uma análise (por exemplo, retirar 5
, 7
e SUCCESS
) e, em seguida bombear esses dados em Cube ( https://github.com/square/cube ) usando seu cliente JS.
Primeiramente, qual é a maneira canônica no Node de ler um arquivo, linha por linha?
Parece ser uma pergunta bastante comum online:
- http://www.quora.com/What-is-the-best-way-to-read-a-file-line-by-line-in-node-js
- Ler um arquivo uma linha de cada vez no node.js?
Muitas das respostas parecem apontar para vários módulos de terceiros:
- https://github.com/nickewing/line-reader
- https://github.com/jahewson/node-byline
- https://github.com/pkrumins/node-lazy
- https://github.com/Gagle/Node-BufferedReader
No entanto, isso parece uma tarefa bastante básica - certamente, há uma maneira simples no stdlib de ler um arquivo de texto, linha por linha?
Em segundo lugar, preciso processar cada linha (por exemplo, converter o registro de data e hora em um objeto Date e extrair campos úteis).
Qual é a melhor maneira de fazer isso, maximizando a taxa de transferência? Existe alguma maneira de não bloquear a leitura em cada linha ou enviá-la para o Cube?
Em terceiro lugar - acho que usando divisões de string, e o equivalente JS de contains (IndexOf! = -1?) Será muito mais rápido que as expressões regulares? Alguém já teve muita experiência na análise de grandes quantidades de dados de texto no Node.js.
Cheers, Victor
fonte
Respostas:
Procurei uma solução para analisar arquivos muito grandes (gbs), linha por linha, usando um fluxo. Todas as bibliotecas e exemplos de terceiros não atenderam às minhas necessidades, pois processaram os arquivos não linha por linha (como 1, 2, 3, 4 ..) ou leram o arquivo inteiro na memória
A solução a seguir pode analisar arquivos muito grandes, linha por linha, usando stream & pipe. Para testar, usei um arquivo de 2,1 gb com 17.000.000 registros. O uso de RAM não excedeu 60 mb.
Primeiro, instale o pacote de fluxo de eventos :
Então:
Por favor, deixe-me saber como vai!
fonte
console.log(lineNr)
após a última linha do seu código, ele não mostrará a contagem final de linhas porque o arquivo é lido de forma assíncrona.s.end();
readline
módulo é uma dor. Ele não pausa e estava causando falhas todas as vezes após 40-50 milhões. Desperdiçou um dia. Muito obrigado pela resposta. Este funciona perfeitamenteVocê pode usar o
readline
pacote embutido , consulte a documentação aqui . Eu uso o fluxo para criar um novo fluxo de saída.Arquivos grandes levarão algum tempo para serem processados. Diga se funciona.
fonte
readline
, é possível pausar / retomar o fluxo de leitura para executar ações assíncronas na área "fazer coisas"?readline
estava me dando muitos problemas quando tentei pausar / retomar. Ele não interromper o fluxo de criar corretamente um monte de problema se o processo a jusante é mais lentoEu realmente gostei da resposta @gerard, que realmente merece ser a resposta correta aqui. Fiz algumas melhorias:
Aqui está o código:
Então, basicamente, aqui está como você o usará:
Eu testei isso com um arquivo CSV de 35GB e funcionou para mim, e foi por isso que escolhi construí-lo com base na resposta da @gerard . Os feedbacks são bem-vindos.
fonte
pause()
ligação, não é?Usei https://www.npmjs.com/package/line-by-line para ler mais de 1 000 000 linhas de um arquivo de texto. Nesse caso, uma capacidade ocupada de RAM era de cerca de 50 a 60 megabytes.
fonte
lr.cancel()
método. Lê as primeiras 1000 linhas de um arquivo 5Gig em 1ms. Impressionante!!!!Além de ler o grande arquivo linha por linha, você também pode lê-lo pedaço por pedaço. Para mais informações, consulte este artigo
fonte
if(bytesRead = chunkSize)
:?A documentação do Node.js. oferece um exemplo muito elegante usando o módulo Readline.
Exemplo: Ler fluxo de arquivos linha por linha
fonte
Eu ainda tinha o mesmo problema. Depois de comparar vários módulos que parecem ter esse recurso, eu decidi fazer isso sozinho, é mais simples do que eu pensava.
gist: https://gist.github.com/deemstone/8279565
Ele cobre o arquivo aberto em um fechamento, que
fetchBlock()
retornou buscará um bloco do arquivo, terminará dividido em matriz (tratará o segmento da última busca).Eu configurei o tamanho do bloco para 1024 para cada operação de leitura. Isso pode ter erros, mas a lógica do código é óbvia, tente você mesmo.
fonte
node-byline usa fluxos, então eu preferiria aquele para seus arquivos enormes.
para suas conversões de data, eu usaria o moment.js .
para maximizar seu rendimento, você pode pensar em usar um cluster de software. existem alguns módulos agradáveis que envolvem muito bem o módulo de cluster nativo do nó. eu gosto do cluster-master do isaacs. por exemplo, você pode criar um cluster de x workers que calculam todos os arquivos.
para comparações de divisões versus regexes, use benchmark.js . Eu não testei até agora. benchmark.js está disponível como um módulo de nó
fonte
Com base nessas perguntas, respondi que implementei uma classe que você pode usar para ler um arquivo de forma síncrona, linha por linha
fs.readSync()
. Você pode fazer essa "pausa" e "retomar" usando umaQ
promessa (jQuery
parece exigir um DOM, portanto não é possível executá-lonodejs
):fonte
fonte
Eu criei um módulo de nó para ler arquivos grandes de forma assíncrona ou JSON. Testado em arquivos grandes.
Apenas salve o arquivo como file-reader.js e use-o assim:
fonte