Muszę przeprowadzić analizę dużych (5–10 GB) plików dziennika w Javascript / Node.js (używam Cube).
Logline wygląda mniej więcej tak:
10:00:43.343423 I'm a friendly log message. There are 5 cats, and 7 dogs. We are in state "SUCCESS".
Musimy czytać każdą linię, zrobić kilka parsowania (np rozebrać się 5
, 7
a SUCCESS
), a następnie pompować te dane do Cube ( https://github.com/square/cube ), wykorzystując ich klient JS.
Po pierwsze, jaki jest kanoniczny sposób w Node, aby czytać plik, wiersz po wierszu?
Wydaje się, że jest to dość powszechne pytanie online:
- http://www.quora.com/What-is-the-best-way-to-read-a-file-line-by-line-in-node-js
- Czytać plik po jednym wierszu na raz w node.js?
Wiele odpowiedzi wydaje się wskazywać na kilka modułów innych firm:
- https://github.com/nickewing/line-reader
- https://github.com/jahewson/node-byline
- https://github.com/pkrumins/node-lazy
- https://github.com/Gagle/Node-BufferedReader
Wydaje się jednak, że jest to dość podstawowe zadanie - z pewnością w standardowej bibliotece standardowej jest prosty sposób, aby czytać w pliku tekstowym, wiersz po wierszu?
Po drugie, muszę następnie przetworzyć każdą linię (np. Przekonwertować znacznik czasu na obiekt Date i wyodrębnić przydatne pola).
Jaki jest najlepszy sposób, aby to zrobić, maksymalizując przepustowość? Czy jest jakiś sposób, który nie blokuje czytania w każdym wierszu lub wysyłania go do Cube?
Po trzecie - zgaduję, że używam podziałów ciągów, a odpowiednik zawiera w JS (IndexOf! = -1?) Będzie o wiele szybszy niż wyrażenia regularne? Czy ktoś miał duże doświadczenie w analizowaniu ogromnych ilości danych tekstowych w Node.js?
Pozdrawiam, Victor
źródło
Odpowiedzi:
Szukałem rozwiązania do analizowania bardzo dużych plików (gbs) wiersz po wierszu przy użyciu strumienia. Wszystkie biblioteki i przykłady innych firm nie odpowiadały moim potrzebom, ponieważ przetwarzały pliki, a nie wiersz po wierszu (np. 1, 2, 3, 4 ..) lub odczytywały cały plik do pamięci
Poniższe rozwiązanie może analizować bardzo duże pliki, wiersz po wierszu, używając strumienia i potoku. Do testów użyłem pliku 2.1 GB z 17.000.000 rekordów. Zużycie pamięci RAM nie przekraczało 60 MB.
Najpierw zainstaluj pakiet strumienia zdarzeń :
Następnie:
Daj mi znać, jak leci!
źródło
console.log(lineNr)
po ostatnim wierszu kodu, nie pokaże ostatecznej liczby wierszy, ponieważ plik jest odczytywany asynchronicznie.s.end();
readline
moduł jest uciążliwy. Nie zatrzymuje się i powoduje awarie za każdym razem po 40-50 mln. Zmarnowany dzień. Bardzo dziękuję za odpowiedź. Ten działa idealnieMożesz użyć wbudowanego
readline
pakietu, zobacz dokumentację tutaj . Używam strumienia, aby utworzyć nowy strumień wyjściowy.Przetwarzanie dużych plików zajmie trochę czasu. Powiedz, czy to działa.
źródło
readline
, czy można wstrzymać / wznowić strumień odczytu, aby wykonać akcje asynchroniczne w obszarze „do rzeczy”?readline
mi wiele problemów, gdy próbowałem wstrzymać / wznowić. Nie wstrzymuje prawidłowo transmisji, powodując wiele problemów, jeśli dalszy proces jest wolniejszyBardzo podobała mi się odpowiedź @gerard, która w rzeczywistości zasługuje na poprawną odpowiedź. Wprowadziłem kilka ulepszeń:
Oto kod:
Tak więc w zasadzie, oto jak z niego skorzystasz:
Przetestowałem to z plikiem CSV o pojemności 35 GB i zadziałało dla mnie i dlatego zdecydowałem się zbudować go na odpowiedzi @gerard , informacje zwrotne są mile widziane.
źródło
pause()
wezwania, prawda?Skorzystałem z https://www.npmjs.com/package/line-by-line do odczytania ponad 1 000 000 wierszy z pliku tekstowego. W tym przypadku zajmowana pojemność pamięci RAM wynosiła około 50-60 megabajtów.
źródło
lr.cancel()
metodzie. Odczytuje pierwsze 1000 wierszy pliku 5Gig w ciągu 1 ms. Niesamowite!!!!Oprócz czytania dużego pliku wiersz po wierszu, możesz także czytać go kawałek po kawałku. Więcej w tym artykule
źródło
if(bytesRead = chunkSize)
?Dokumentacja Node.js oferuje bardzo elegancki przykład użycia modułu Readline.
Przykład: Czytaj strumień plików wiersz po wierszu
źródło
Miałem jeszcze ten sam problem. Po porównaniu kilku modułów, które wydają się mieć tę funkcję, postanowiłem zrobić to sam, jest to prostsze niż myślałem.
streszczenie: https://gist.github.com/deemstone/8279565
Zakrywa plik otwarty w zamknięciu, który
fetchBlock()
zwrócony pobierze blok z pliku, zakończy podział na tablicę (zajmie się segmentem z ostatniego pobrania).Ustawiłem rozmiar bloku na 1024 dla każdej operacji odczytu. Może to mieć błędy, ale logika kodu jest oczywista, spróbuj sam.
źródło
node-byline używa strumieni, więc wolałbym ten jeden dla dużych plików.
do konwersji dat użyłbym momentu.js .
Aby zmaksymalizować przepustowość, możesz pomyśleć o użyciu klastra oprogramowania. jest kilka fajnych modułów, które całkiem dobrze opakowują natywny dla węzła moduł klastra. Lubię Cluster-Master od isaacs. np. możesz stworzyć klaster x pracowników, z których wszystkie obliczają plik.
do testów porównawczych podziałów i wyrażeń regularnych użyj benchmark.js . do tej pory nie testowałem tego. benchmark.js jest dostępny jako moduł węzła
źródło
Na podstawie odpowiedzi na te pytania zaimplementowałem klasę, za pomocą której można odczytać plik synchronicznie, wiersz po wierszu
fs.readSync()
. Możesz to „wstrzymać” i „wznowić”, używającQ
obietnicy (jQuery
wydaje się, że wymaga DOM, więc nie można go uruchomićnodejs
):źródło
źródło
Zrobiłem moduł węzła do asynchronicznego odczytu dużego pliku tekstowego lub JSON. Testowane na dużych plikach.
Po prostu zapisz plik jako file-reader.js i użyj go w następujący sposób:
źródło