Pobranie i kasowanie linii z pliku

dział ogólny

Pobranie i kasowanie linii z pliku

Nowy postprzez husky83 » niedziela, 15 listopada 2009, 13:27

Witam :)
Mój problem jest na pewno beznadziejnie prosty do rozwiazania :)ale chodzi o sposób najmniej obciążający i spowalniający pracę programu...

Z dużego pliku tekstowego (powiedzmy między 5 a 10 MB) muszę pobrać jedną linię (póki co tylko pierwszą) a następnie ją wykasować..

Na początku podszedłem do tego bardzo dookoła, wczytywałem całość do TStrings*, bo tam można bez problemów wczytywać i zapisywać do pliku, oraz usuwać linie. Problem pojawia się przy dużych plikach - program pracuje niczym żółw.. kombinuje z getline (póki co jakoś bez rezultatu), ale jak potem wykasować linie? Przypominam że chodzi o najszybszy sposób :)
Biorąc pod uwagę to, że pobieram i kasuję linie (między jednym a drugim są dodatkowe operacje) aż do ostatniej linii teoretycznie mógłbym wciągnąć cały plik do pamięci i tam działać, jednak chodzi o to że program bedzie można w dowolnym momencie zawiesić czy też wyłączyć, a po ponownym włączeniu program będzie działał od momentu na którym skończył... Myślę też nad ewentualnym zapisywaniem pliku tylko co np. 100 wierszy, jednak nie jest to do końca to, o co mi chodzi ;)
Avatar użytkownika
husky83
Bladawiec
Bladawiec
 
Posty: 31
Dołączył(a): czwartek, 26 marca 2009, 11:06
Podziękował : 2
Otrzymał podziękowań: 0
Kompilator: C++ Builder
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez Cyfrowy Baron » niedziela, 15 listopada 2009, 17:47

Tego chyba nie da się zrobić. Dokonani zmian w pliku wymaga przetworzenia tego pliku. Możesz wczytać tylko fragment pliku, ale wczytać, żeby zapisać zmiany trzeba przetworzyć to co znajduje się przed i po wczytanym fragmencie, więc cały plik trzeba wczytać do pamięci, tam przetworzyć i zapisać zmiany.

Z drugiej jednak strony pewien nie jestem, wszak Windows operuje na pliku wymiany, zakładam więc, że czyta ten plik i modyfikuje tylko we fragmentach, nie przetwarza go całego. W przypadku pliku wymiany wykorzystywany jest jednak chyba inny mechanizm, więc nie da się tego przeprowadzić na plikach tekstowych.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez polymorphism » poniedziałek, 16 listopada 2009, 14:16

teoretycznie mógłbym wciągnąć cały plik do pamięci i tam działać, jednak chodzi o to że program bedzie można w dowolnym momencie zawiesić czy też wyłączyć, a po ponownym włączeniu program będzie działał od momentu na którym skończył...

No ale co to ma do rzeczy, że plik lub dane będziesz miał w pamięci? Przy wyłączeniu aplikacji zapisujesz to co masz w pamięci do pliku i tyle. Gdzie tu problem?

W sumie to niewiele napisałeś na temat tego, czym to "usuwanie linii" w zasadzie jest, jaką to pełni rolę w twojej aplikacji. Nie da się zaproponować jakiegoś optymalnego rozwiązania opierając się tylko na ogólnikach.

Z drugiej jednak strony pewien nie jestem, wszak Windows operuje na pliku wymiany, zakładam więc, że czyta ten plik i modyfikuje tylko we fragmentach, nie przetwarza go całego.

Tylko co ma plik wymiany do czytania pliku po fragmentach tudzież jego przetwarzania?
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez Cyfrowy Baron » poniedziałek, 16 listopada 2009, 14:28

Tylko co ma plik wymiany do czytania pliku po fragmentach tudzież jego przetwarzania?


Autorowi wątku chodzi o to by bez wczytywania pliku do pamięci usunąć z niego wybrany fragment, czyli program wczytuje sobie tylko wybrany fragment z pliku i usuwa ten fragment z tegoż pliku, a plik zapamiętuje zmiany. Czy możliwie jest wogóle zmodyfikowanie zawartości pliku bez wczytania całej jego zawartości, tylko wybranego fragmentu. Podałem przykład pliku wymiany, gdyż wydaje mi się, że system nie przetwarza całego pliku, a tylko jego fragmenty. Plik wymiany nie jest w całości wczytywany do pamięci RAM, gdyż sam jest obszarem pamięci dodatkowej, więc nie może być przetwarzany w całości, a tylko we fragmentach.

W sumie to niewiele napisałeś na temat tego, czym to "usuwanie linii" w zasadzie jest, jaką to pełni rolę w twojej aplikacji.


Jak sądzę autorowi wątku chodzi o to, że plik jest duży i jego wczytanie zajmuje dużo czasu, więc chciałby wczytać tylko fragment tego pliku i ten fragment z niego usunąć, w ten sposób nie musiałby przetwarzać całego pliku, czyli nie wczytywałby go całego, co przyspieszyłoby modyfikacje zawartości pliku.

Mi osobiście wydaje się niemożliwe dokonanie modyfikacji zawartości pliku bez uprzedniego wczytania go w całości do pamięci. Bo o ile można wczytać tylko fragment pliku, o tyle przy zapisywaniu trzeba przetworzyć całą zawartość pliku.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez polymorphism » poniedziałek, 16 listopada 2009, 14:50

Jak sądzę autorowi wątku chodzi o to, że plik jest duży i jego wczytanie zajmuje dużo czasu, więc chciałby wczytać tylko fragment tego pliku i ten fragment z niego usunąć, w ten sposób nie musiałby przetwarzać całego pliku, czyli nie wczytywałby go całego, co przyspieszyłoby modyfikacje zawartości pliku.

No tyle to i ja zrozumiałem, tylko jeśli mu 10MB plik za wolno wczytuje, to albo za często wczytuje, albo wybrał zły kontener, albo coś tam coś tam... Na ogólnikach nie da się zrobić porządnej optymalizacji, a takie niestety podał husky83. Z drugiej strony pliki tekstowe z natury nie są zbyt przyjemne w parsowaniu, szczególnie jeśli mówimy o szybkości.

Mi osobiście wydaje się niemożliwe dokonanie modyfikacji zawartości pliku bez uprzedniego wczytania go w całości do pamięci.

Jak najbardziej jest to możliwe, weź chociażby edytory audio czy video. Choć i tak na końcu wiąże się to z przepisaniem całego pliku na nowo. No ale do tego nie trzeba ładować całego pliku do pamięci.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez Darek_C++ » poniedziałek, 16 listopada 2009, 14:59

Jeśli problemem jest zawieszanie programu podczas wczytywania do TStringList operację przenieś do wątku do tego zmiana ikony na klepsydrę informującą o przetwarzaniu danych i będzie OK. W końcu jest dużo operacji wymagających pewnego czasu które w ten sposób się rozwiązuje np. kopiowanie, kasowanie kosza itd...
Avatar użytkownika
Darek_C++
Elektrowied
Elektrowied
 
Posty: 454
Dołączył(a): piątek, 25 lipca 2008, 14:33
Podziękował : 66
Otrzymał podziękowań: 4
System operacyjny: Windows XP Pro SP2
Kompilator: Turbo Explorer C++
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez Cyfrowy Baron » poniedziałek, 16 listopada 2009, 15:13

Jak najbardziej jest to możliwe, weź chociażby edytory audio czy video. Choć i tak na końcu wiąże się to z przepisaniem całego pliku na nowo. No ale do tego nie trzeba ładować całego pliku do pamięci.


Z tego akurat sobie zdaje sprawę, niemniej jednak wciąż wymagane jest przetworzenie całego pliku, gdyż musi być przepisany cały. Podczas gdy w przypadku pliku wymiany działa inny mechanizm modyfikowana jest zawartość konkretnych sektorów na dysku bez przepisywania.

Jeżeli wykonujesz operacje odczytu i zapisu na pliku o rozmiarach np. 100 MB, to na jego przetworzenie potrzeba czasu niezależnie czy wczytasz go w całości do pamięci, czy tylko wczytasz fragment a potem przepiszesz dopisując fragment. Pytanie jakie ja sobie stawiam i być może autor wątku to jak zmodyfikować tylko wybrany fragment pliku bez przetwarzania całego pliku. To o czym Ty piszesz to przepisywanie pliku w kawałkach, czyli też wczytywanie pliku w częściach do pamięci i łączenie ich w całość, w efekcie cały plik zostaje przetworzony w pamięci, tyle że po kawałku nie cały od razu.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez polymorphism » poniedziałek, 16 listopada 2009, 16:11

Z tego akurat sobie zdaje sprawę, niemniej jednak wciąż wymagane jest przetworzenie całego pliku, gdyż musi być przepisany cały.
Napisałeś, że nie można zmodyfikować pliku "bez uprzedniego wczytania go w całości do pamięci". Ja rozumiem to tak: żeby poddać plik edycji trzeba go najpierw wczytać w całości do pamięci - a to prawdą nie jest.

Pytanie jakie ja sobie stawiam i być może autor wątku to jak zmodyfikować tylko wybrany fragment pliku bez przetwarzania całego pliku

Jeśli modyfikacja zmienia rozmiar pliku, a mówimy o modyfikacji na początku lub w środku pliku, lub narusza jakoś jego strukturę, to nie jest to możliwe.

To o czym Ty piszesz to przepisywanie pliku w kawałkach, czyli też wczytywanie pliku w częściach do pamięci i łączenie ich w całość,
No tak, przecież tworzę nowy plik na bazie starego i z uwzględnieniem zmian.

w efekcie cały plik zostaje przetworzony w pamięci, tyle że po kawałku nie cały od razu.

A znasz jakiś algorytm, który w jakikolwiek sposób modyfikuje plik bez użycia pamięci? Bo ja takiego nie znam i nie sądzę, żeby taki był 8-)
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez Cyfrowy Baron » poniedziałek, 16 listopada 2009, 16:25

A znasz jakiś algorytm, który w jakikolwiek sposób modyfikuje plik bez użycia pamięci? Bo ja takiego nie znam i nie sądzę, żeby taki był


No i jesteśmy w punkcie wyjścia. To, że pisałem o tym, że trzeba wczytać plik w całości, żeby go przetworzyć, sprowadza się w do tego, że niezależnie od tego jak go wczytujesz, w kawałkach czy w całości i tak przetwarzasz w efekcie cały plik, czyli wczytujesz go w całości, tylko nie jednorazowo. Pisząc tamto nie rozważałem co prawda kwestii wczytywania pliku w kawałkach, gdyż nie brałem pod uwagę takiego rozwiązania, ponieważ nie rozwiązuje to problemu.

Co do modyfikacji pliku bez udziału pamięci to jest to oczywiście niemożliwe, ale mi raczej chodzi o sposób, który jest wykorzystywany w pliku wymiany. Ten plik nie jest przetwarzany w całości, gdy coś się zmienia system modyfikuje tylko fragment pliku, bez przepisywania całego pliku.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez polymorphism » poniedziałek, 16 listopada 2009, 17:56

To, że pisałem o tym, że trzeba wczytać plik w całości, żeby go przetworzyć, sprowadza się w do tego, że niezależnie od tego jak go wczytujesz, w kawałkach czy w całości i tak przetwarzasz w efekcie cały plik, czyli wczytujesz go w całości,

Nie no tutaj to odwracasz kota ogonem. Wczytać w całości plik do pamięci, nawet czytając fragmentami, to znaczy tyle, że cała zawartość tego pliku znajduje się w pamięci (w tym samym czasie). Ale żeby już nie drążyć tego tematu założę, że tamto zdanie po prostu niefortunnie sformułowałeś.

[...] ale mi raczej chodzi o sposób, który jest wykorzystywany w pliku wymiany. Ten plik nie jest przetwarzany w całości, gdy coś się zmienia system modyfikuje tylko fragment pliku

Zapewne plik ten podzielony jest na bloki/rekordy/regiony/strony o stałej wielkości, które są w użyciu lub nie. Te bloki są "zmapowane" przez managera pamięci na odpowiednie adresy pamięci wirtualnej. To trochę tak jak klastry w systemie plików, które nie muszą przechowywać pliku w jednym ciągu, mogą być porozrzucane po całym dysku. No właśnie, lepszym przykładem byłby tu system plików, gdzie dysk to plik, a system plików to format takiego pliku, który umożliwia dodawanie/usuwanie/zmienianie zawartości bez konieczności przepisywania/przesuwania pozostałych danych. Bodajże niektóre bazy danych wykorzystują wirtualny system plików do przechowywania rekordów.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez husky83 » wtorek, 17 listopada 2009, 14:56

cóż za dyskusja się wywiązała w czasie, gdy byłem nieobecny :)

Faktycznie, poradziłem sobie inaczej, zapisując zmodyfikowany plik co jakiś czas.

Cyfrowy Baron napisał(a):Jak sądzę autorowi wątku chodzi o to, że plik jest duży i jego wczytanie zajmuje dużo czasu, więc chciałby wczytać tylko fragment tego pliku i ten fragment z niego usunąć, w ten sposób nie musiałby przetwarzać całego pliku, czyli nie wczytywałby go całego, co przyspieszyłoby modyfikacje zawartości pliku.

dokładnie o to chodziło :)

polymorphism napisał(a):jeśli mu 10MB plik za wolno wczytuje, to albo za często wczytuje, albo wybrał zły kontener, albo coś tam coś tam...
Być może jedno i drugie, ale ograniczyłem to pierwsze (do 1 zapisu / 50 wierszy) i już jest znośnie :)
Czym program dokładnie jest, wydaje mi się że nie jest aż tak ważne, a o co chodzi z zapisem i odczytem - pisałem..
Program ma:
1. odczytac plik
2. Pobrać pierwszy wiersz
3. przetworzyć jego zawartość
4. Usunąć pierwszy wiersz (drugi wiersz staje się automatycznie pierwszym)
5. zapisać zmieniony plik
6. GOTO: 2 (i tak do ostatniego wiersza w pliku).

Obecnie punkt 5 występuje wyłącznie co 50 przetworzonych wierszy, gdy skończono przetwarzać ostatni wiersz oraz przy zamykaniu programu. Czyli ładnie i przyjemnie :)

Ale ciekawi mnie czy ktoś znajdzie sposób na zapis/odczyt tylko konkretnej części pliku ;)
Avatar użytkownika
husky83
Bladawiec
Bladawiec
 
Posty: 31
Dołączył(a): czwartek, 26 marca 2009, 11:06
Podziękował : 2
Otrzymał podziękowań: 0
Kompilator: C++ Builder
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez polymorphism » wtorek, 17 listopada 2009, 15:24

1. odczytac plik
2. Pobrać pierwszy wiersz
3. przetworzyć jego zawartość
4. Usunąć pierwszy wiersz (drugi wiersz staje się automatycznie pierwszym)
5. zapisać zmieniony plik
6. GOTO: 2 (i tak do ostatniego wiersza w pliku).

Obecnie punkt 5 występuje wyłącznie co 50 przetworzonych wierszy, gdy skończono przetwarzać ostatni wiersz oraz przy zamykaniu programu. Czyli ładnie i przyjemnie

Jak dla mnie to może wyglądać tak:

  1. otwierasz strumień (np. ifstream)
  2. ustawiasz wskaźnik odczytu (seekg) (patrz punkt 6b)
  3. czytasz wiersz
  4. zapisujesz wskaźnik odczytu (tellg) (wskazuje na następny wiersz)
  5. przetwarzasz wiersz
    1. goto punkt 3
    2. przy zamknięciu/przerwaniu procesu zapamiętujesz wskaźnik odczytu (patrz punkt 4), np. w pliku.
Plik zostaje nietknięty, przez co całość będzie szybciej działać.
Ostatnio edytowano wtorek, 17 listopada 2009, 16:59 przez polymorphism, łącznie edytowano 4 razy
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Pobranie i kasowanie linii z pliku

Nowy postprzez Cyfrowy Baron » wtorek, 17 listopada 2009, 15:45

Dla mnie zapisywanie co któryś tam wiersz wydaje się bez sensu, skoro to niczego nie zmienia, czyli mimo zapisu plik jest dalej przetwarzany jak był przed zapisem. Po co go zapisywać? Jedyne rozsądne rozwiązanie jakie mi się nasuwa to:

1. otworzyć plik do odczytu
2. Pobrać pierwszy wiersz
3. przetworzyć jego zawartość
4. Usunąć pierwszy wiersz (drugi wiersz staje się automatycznie pierwszym)
5. GOTO: 2 (i tak do ostatniego wiersza w pliku).
6. Po przetworzeniu wszystkich wierszy zapisać zmiany w pliku.

Tylko, że z wyliczeń wychodzi mi, ze po przetworzeniu wszystkich wierszy w pliku nic już nie zostanie, więc po co zapisywać pusty plik.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 0 gości