2012-03-28 17 views
11

Występuje problem, którego nie widziałem nikogo na spotkaniu StackOverflow, a nawet google.Python nie odczytuje całego pliku tekstowego

Moim głównym celem jest możliwość zamiany wystąpień ciągu znaków w pliku na inny ciąg. Czy istnieje sposób, aby móc uzyskać dostęp do wszystkich linii w pliku.

Problem polega na tym, że gdy próbuję czytać duży tekst (1-2 gb) tekstu, python odczytuje tylko jego podzestaw.

Na przykład, zrobię to naprawdę po prostu polecenia takie jak:

newfile = open("newfile.txt","w") 
f = open("filename.txt","r") 
for line in f: 
    replaced = line.replace("string1", "string2") 
    newfile.write(replaced) 

I to pisze tylko pierwsze 382 MB oryginalnego pliku. Czy ktoś wcześniej napotkał ten problem?

Próbowałem kilka różnych rozwiązań, takich jak zastosowanie:

import fileinput 
for i, line in enumerate(fileinput.input("filename.txt", inplace=1) 
    sys.stdout.write(line.replace("string1", "string2") 

Ale ma ten sam efekt. Ani nie czyta plik w kawałkach takich jak korzystanie

mam zawężony go głównie prawdopodobne jest odczyt w błąd i nie jest to problem, bo pisanie to dzieje się po prostu drukowanie linii. Wiem, że jest więcej linii. Kiedy otwieram go w edytorze pełnego tekstu, takim jak Vim, widzę, jaki powinien być ostatni wiersz, i nie jest to ostatni wiersz, który wypisuje python.

Czy ktoś może zaoferować porady lub rzeczy do wypróbowania?

obecnie używam wersji 32-bitowej wersji systemu Windows XP z 3,25 GB pamięci RAM i systemem Pythona 2.7

* Edycja Rozwiązanie Found (Dzięki Lattyware). Korzystanie iterator

def read_in_chunks(file, chunk_size=1000): 
    while True: 
     data = file.read(chunk_size) 
     if not data: break 
     yield data 
+1

Czytanie linii po linii z iteratorem powinno być operacją leniwą, więc powinno działać niezależnie od wielkości pliku. Chociaż nie powinno to wpłynąć na twoją sytuację, będziesz również chciał użyć '' with'' podczas otwierania plików - jest to dobra praktyka niż obsługuje zamykanie pod wyjątkami poprawnie. –

+0

To zadziałało świetnie! Dzięki wielkie. * edit: Próbowałem opublikować tutaj kod iteratora, ale nie sformatowałbym go, więc dodałem go do oryginalnego postu. – user1297872

+0

Czy próbowałeś z innym dużym plikiem tekstowym? Czy jest coś dziwnego w pliku 382mb - dziwna postać, która jest traktowana jako koniec pliku? – neil

Odpowiedz

1

Jeśli używasz plik tak:

with open("filename.txt") as f: 
    for line in f: 
     newfile.write(line.replace("string1", "string2")) 

Warto przeczytać tylko jedną linię w pamięci na raz, chyba że zachować odniesienie do tej linii w pamięci.
Po przeczytaniu każdego wiersza, będzie można go pozbyć się od śmieciarka pytonów. Spróbuj tego i sprawdzić, czy to działa dla ciebie :)

22

Spróbuj:

f = open("filename.txt", "rb") 

na Windows, rb oznacza otwarty plik w trybie binarnym. Zgodnie z dokumentami tryb tekstowy a tryb binarny ma wpływ tylko na znaki końca wiersza. Ale (jeśli dobrze pamiętam), wierzę, że otwieranie plików w trybie tekstowym w Windowsie również robi coś z EOF (hex 1A).

Można także określić tryb podczas korzystania fileinput:

fileinput.input("filename.txt", inplace=1, mode="rb") 
+0

To też działa! Najbardziej lubię to rozwiązanie, bo jak łatwo zmienić istniejący kod. – user1297872

+0

Jak działa "to również działa"? To wyraźnie twój problem. Jakie inne podejście również zadziałało? Ah, widzę w komentarzach, określając długość bajtów do przeczytania, zamiast używać "readline" – jsbueno

+0

niesamowicie, zadziałało dla mnie – Stoyan

2

Czy jesteś pewien, że problem jest z czytaniem, a nie wypisywanie? Czy zamykasz plik, do którego zapisano, jawnie newfile.close() lub używasz konstruktu with?

Brak zamykania pliku wyjściowego jest często źródłem takich problemów, gdy buforowanie odbywa się gdzieś. Jeśli tak jest również w twoim ustawieniu, zamknięcie powinno naprawić początkowe rozwiązania.

Powiązane problemy