Uważaj na pliki „slurping”. Wtedy od razu odczytujesz cały plik do pamięci.
Problem polega na tym, że nie skaluje się dobrze. Możesz opracowywać kod z plikiem o rozsądnych rozmiarach, a następnie wprowadzić go do produkcji i nagle odkryć, że próbujesz odczytać pliki mierzone w gigabajtach, a Twój host zawiesza się, gdy próbuje odczytać i przydzielić pamięć.
Line-by-I / O jest bardzo szybki i prawie zawsze tak samo skuteczny jak slurping. W rzeczywistości jest zaskakująco szybki.
Lubię używać:
IO.foreach("testfile"){|x| print "GOT ", x }
lub
File.foreach('testfile'){|x| print "GOT", x }
Plik dziedziczy z IO i foreachjest w IO, więc możesz użyć jednego z nich.
Wreszcie możesz to zrobić bez bloku, na przykład podczas przetwarzania wielu plików jednocześnie. W takim przypadku plik musi zostać jawnie zamknięty (poprawiony zgodnie z komentarzem @antinome):
begin
f =File.open 'file.txt'while line = f.gets
puts lineendensure
f.closeend
Zwykle używam edytora Sublime Text z wtyczką RubyMarkers, kiedy dokumentuję kod, który ma być użyty w odpowiedziach tutaj. Ułatwia to wyświetlanie wyników pośrednich, podobnie jak w przypadku IRB. Również wtyczka Seeing Is Believing do Sublime Text 2 jest naprawdę potężna.
Świetna odpowiedź. W ostatnim przykładzie mogę zasugerować użycie whilezamiast loopi użycie, ensureaby upewnić się, że plik zostanie zamknięty, nawet jeśli zostanie zgłoszony wyjątek. Tak (zastąpienia średników z nowej linii) begin; f = File.open('testfile'); while line = f.gets; puts line; end; ensure; f.close; end.
Podobnie jak w przypadku readdowolnego wariantu spowoduje to wciągnięcie całego pliku do pamięci, co może powodować poważne problemy, jeśli plik jest większy niż dostępna pamięć. Ponadto, ponieważ jest to tablica, Ruby musi ją utworzyć, co dodatkowo spowalnia proces.
Jeszcze bardziej wydajnym sposobem jest przesyłanie strumieniowe, prosząc jądro systemu operacyjnego o otwarcie pliku, a następnie odczytanie z niego bajtów po kawałku. Podczas odczytywania pliku w wierszu w języku Ruby dane są pobierane z pliku 512 bajtów naraz i dzielone na „linie”.
Dzięki buforowaniu zawartości pliku zmniejsza się liczba wywołań We / Wy, dzieląc plik na logiczne części.
Przykład:
Dodaj tę klasę do swojej aplikacji jako obiekt usługi:
Myślę, że wstawienie „block.call (@buffer)” przed „@ io.close” odbierze brakującą niekompletną linię. Jednak grałem z Ruby tylko jeden dzień, więc mogłem się mylić. Działa w mojej aplikacji :)
Po przeczytaniu postu AppSignal wydaje się, że nastąpiło tutaj małe nieporozumienie. Kod skopiowany z tego postu, który wykonuje buforowane operacje we / wy, jest przykładową implementacją tego, co Ruby faktycznie robi z File.foreach lub IO.foreach (które są tą samą metodą). Powinny być używane i nie trzeba ich ponownie wprowadzać w ten sposób.
@ PeterH.Boling Jestem również za mentalnością używania i nie reimplementacji przez większość czasu. Ale rubin pozwala nam otwierać rzeczy i szturchać ich wnętrze bez wstydu, to jedna z jego zalet. Nie ma prawdziwego „powinien” lub „nie powinien”, szczególnie w rubinach / szynach. Tak długo, jak wiesz, co robisz, i piszesz na to testy.
Przydatna sztuczka, ale wzywanie do powłoki ma wiele pułapek, w tym 1) polecenia mogą się różnić w różnych systemach operacyjnych, 2) może być konieczne wstawienie spacji w nazwie pliku. Jesteś o wiele lepiej wyłączyć za pomocą Ruby wbudowanych funkcji, na przykładcontent = File.read(filename)
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.