Nie, plik nie jest automatycznie wczytywany do pamięci przez jego otwarcie. To byłoby okropnie nieefektywne. sed
, na przykład, czyta swoje wejście wiersz po wierszu, podobnie jak wiele innych narzędzi uniksowych. Rzadko musi utrzymywać w pamięci więcej niż bieżący wiersz.
Z awk
tym samym. Odczytuje rekord naraz, który domyślnie jest linią. Jeśli przechowujesz części danych wejściowych w zmiennych, będzie to dodatkowe, oczywiście 1 .
Niektórzy ludzie mają zwyczaj robienia takich rzeczy
for line in $(cat file); do ...; done
Ponieważ powłoka będzie musiała $(cat file)
całkowicie rozszerzyć podstawianie poleceń przed uruchomieniem nawet pierwszej iteracji for
pętli, spowoduje to odczytanie całej file
pamięci (do pamięci używanej przez powłokę wykonującą for
pętlę). To jest trochę głupie, a także nieeleganckie. Zamiast tego należy zrobić
while IFS= read -r line; do ...; done <file
Spowoduje to przetworzenie file
linia po linii (ale należy przeczytać Zrozumienie „IFS = czytaj -r linia” ).
Przetwarzanie plików wiersz po wierszu w powłoce jest jednak rzadko potrzebne, ponieważ większość narzędzi i tak jest zorientowana liniowo (zobacz Dlaczego używanie pętli powłoki do przetwarzania tekstu jest uważane za złą praktykę? ).
Pracuję w bioinformatyce, a kiedy przetwarzam ogromne ilości danych genomowych, nie byłbym w stanie wiele zrobić, chyba że zachowałem tylko te fragmenty danych, które były absolutnie niezbędne w pamięci. Na przykład, gdy muszę usunąć fragmenty danych, które mogłyby zostać wykorzystane do identyfikacji osób z 1-terabajtowego zestawu danych zawierającego warianty DNA w pliku VCF (ponieważ tego typu danych nie można upublicznić), wykonuję wiersz po wierszu przetwarzanie za pomocą prostego awk
programu (jest to możliwe, ponieważ format VCF jest zorientowany liniowo). I nie odczytać pliku do pamięci, przetworzyć go tam, i ponownie je zapisze się ponownie! Gdyby plik został skompresowany, przekazałbym go zcat
lub gzip -d -c
, ponieważ ponieważ gzip
przetwarza przetwarzanie danych w strumieniu, również nie odczytałby całego pliku do pamięci.
Nawet w przypadku formatów plików, które nie są zorientowane liniowo, takich jak JSON lub XML, istnieją parsery strumieniowe, które umożliwiają przetwarzanie dużych plików bez przechowywania ich w pamięci RAM.
W przypadku plików wykonywalnych jest to nieco bardziej skomplikowane, ponieważ biblioteki współdzielone mogą być ładowane na żądanie i / lub dzielone między procesami ( na przykład Ładowanie bibliotek współdzielonych i użycie pamięci RAM ).
Buforowanie to coś, o czym tu nie wspomniałem. Jest to działanie polegające na użyciu pamięci RAM do przechowywania często używanych fragmentów danych. Mniejsze pliki (na przykład pliki wykonywalne) mogą być buforowane przez system operacyjny w nadziei, że użytkownik dokona wielu odwołań do nich. Oprócz pierwszego odczytu pliku, kolejne dostępy będą miały miejsce w pamięci RAM, a nie na dysku. Buforowanie, podobnie jak buforowanie danych wejściowych i wyjściowych, jest zwykle w dużej mierze przezroczyste dla użytkownika, a ilość pamięci używanej do buforowania rzeczy może się dynamicznie zmieniać w zależności od ilości pamięci RAM przydzielonej przez aplikacje itp.
1 Technicznie rzecz biorąc, większość programów prawdopodobnie odczytuje fragment danych wejściowych naraz, albo za pomocą buforowania jawnego, albo pośrednio przez buforowanie, które robią standardowe biblioteki we / wy, a następnie przedstawia ten fragment linia po linii do kodu użytkownika. O wiele bardziej efektywne jest odczytywanie wielokrotności rozmiaru bloku dysku niż np. Znak na raz. Jednak ten rozmiar fragmentu rzadko jest większy niż garść kilobajtów.