2009-07-20 12 views
15

Chcę usunąć określone linie w pliku i wstawić określone wiersze w tym samym pliku w zależności od tego, czy określone części wiersza pasują do określonego ciągu. Czy istnieje sposób robienia tego bez użycia pliku tymczasowego do skopiowania zawartości i tak dalej?Usuwanie linii z pliku w języku C

Odpowiedz

27

Problem polega na tym, że plik jest (w zasadzie) tablicą bajtów na dysku (lub innym nośniku fizycznym, ale w każdym razie bajtów!), A "linia" może przyjmować różną liczbę bajtów; więc wstawianie lub usuwanie linii (chyba że zawsze rygorystycznie zastępujesz linię inną linią o dokładnie tej samej długości w bajtach) wymagałoby "przesunięcia" całej reszty pliku "w górę" lub "w dół" o różnicę w bajtach ... co może być niezwykle uciążliwą operacją (ponieważ reszta pliku może być gigabajtem, nawet jeśli zmienisz długość jednej linii o 1 bajt w kierunku początku pliku).

Tak więc takie operacje mogą być niezwykle uciążliwe i dlatego zazwyczaj nigdy nie są oferowane jako prymitywy w DOWOLNYM języku obsługującym pliki o zmiennej długości linii (C, Python, Java, C++, Ruby lub KAŻDY inny taki język). Jest bardzo mało prawdopodobne, że naprawdę trzeba zapłacić tak potencjalnie niezwiązany koszt w wydajności ORAZ ryzyko (awaria systemu lub dysku podczas "zmiany" GB lub danych w górę lub w dół może zniszczyć użyteczność całego, ogromnego pliku), gdy idealnie prosta, odpowiednia, szybka, bezpieczna i rozsądna technika, której próbujesz uniknąć, ma w zasadzie ZERO wady (więc nie jest to oczywiste DLACZEGO próbujesz tego uniknąć?).

Użyj pliku wynikowego innego niż plik źródłowy, kiedy wykonasz mv plik wynikowy przez plik źródłowy (operacja atomowa na większości systemów, jeśli jesteś w tym samym systemie plików), i naprawdę masz najlepszy ze wszystkich możliwych światów.

3

Nie można łatwo "wyciąć" fragmentu pliku na miejscu. Zawsze gdzieś robisz tymczasową kopię. To nie jest rzecz C; Dotyczy to dowolnego języka.

Możesz pobrać plik w postaci mmap, a po znalezieniu linii, którą chcesz skasować, możesz zapisać wszystko po niej w miejscu, w którym znajduje się początek linii. Zastanawiałbym się, jak efektywne byłoby to; plik tymczasowy może być szybszy.

+0

The plik tymczasowy jest dużo * bezpieczniejszy *. – RBerteig

+0

To prawda, nie byłby to mój pierwszy wybór ... ani nawet żaden wybór. Jest to jedyna rzecz, o której mogę pomyśleć, która może zaspokoić tę prośbę. To podejście jest prawdopodobnie bezpieczniejsze (nie ma problemów z uprawnieniami do plików tymczasowych), ale zgadzam się, że plik zostanie uszkodzony w przypadku awarii. –

0

Jeśli plik nie jest wystarczająco duży do przetwarzania w pamięci RAM, możesz użyć Połączonej listy ciągów, gdzie każdy węzeł reprezentuje Linię, czyli węzeł połączonej listy jest tworzony na podstawie znaku "\ n" a następnie możesz wykonać operacje wstawiania i usuwanie operacji na połączonej liście, jeśli to konieczne, a następnie możesz zastąpić ten sam plik przy użyciu połączonej listy.

Na przykład, mytext.txt

Ten plik jest badanie

Linia musi być dodana powyżej

Linia ta musi być usunięta

Teraz po utworzeniu połączonej listy z powyższego pliku, Byłoby to jak

[To jest plik testowy] -> [Należy dodać linię powyżej] -> [Ta linia musi być usunięty] -> [NULL]

Insert Operacja zmieni połączonej listy do

[Ten plik jest test] -> [Jest to nowa linia] -> [A linia musi być dodana powyżej] -> [linia ta musi być usunięty] -> [NULL]

Usuń Operacja zmieni połączonej listy do

[Ten plik jest test] - > [Thi s to nowa linia] -> [Linia musi być dodana powyżej] -> [NULL]

Teraz można napisać połączonej listy do pliku mytext.txt z „\ n” postać w końcu każdego węzła.

Ostateczna pliku byłoby mytext.txt

Ten plik jest badanie

Jest to nowa linia

Linia musi być dodana powyżej