Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Jak działa TextField od zaplecza?

Ostatnio zmodyfikowano 2023-02-13 17:18
Autor Wiadomość
befejak
Temat założony przez niniejszego użytkownika
Jak działa TextField od zaplecza?
» 2023-02-13 15:39:53
Witam ponownie.
 Jakiś czas temu próbowałem uruchomić bardzo duży plik tekstowy w Notepad++
 Nie pamiętam ile dokładnie to było ale domyślam się że ok kilku GB.

Napisałem program który generuje wszystkie możliwe kombinacje liter używając alfabetu angielskiego
 a następnie eksportuje te słowa do pliku tekstowego, ale plik zawierający 6 literowe kombinacje był
 kilka GB duży, mój RAM pozwalał na uruchomienie takiego pliku ale N++ wyświetlił komunikat że za duży.

Pomyślałem że spróbowałbym napisać mój własny "edytor tekstu"


Mój pierwszy pomysł był dość prosty,
 zarejestrować 1024 sloty pamięci typu Char i w każdym trzymać znak -> Text = new char[1024];
 W chwili gdybym potrzebował więcej przestrzeni mógłbym po prostu powiększyć tablicę.

Ale tu pojawia się problem, gdybym miał tekst:
 "To jest mój program do edycji tekstu"

A chciałbym zamienić tekst do:
 "To jest mój <super> program do edycji tekstu"

W tym przypadku musiałbym przesunąć sporo literek w prawo, oczywiście dla krótkiego tekstu nie jest to problemem,
 Ale chciałbym aby program z perspektywy logicznej działał dla dużych i małych tekstów.


Mój drugi pomysł opierał się na podobnej logice,
 ale w tym przypadku użyłem czegoś na wzór LinkedList, podzieliłem tekst na klastry o wielkości 256 znaków
 I każdy klaster posiadał wskaźnik do następnego i poprzedniego klastra.

W ten sposób chcąc dodać coś pomiędzy nie, nawet jeśli byłby to bardzo bardzo długi tekst to dodanie nowego klastra
 I przestawienie wskaźników nie byłoby problemem.

Ale pojawia się inny problem, mianowicie jeśli mój tekst miałby długość w obecnym klastrze 255 znaków i chciałbym dopisać
 kilna nowych słów wtedy musiał bym utworzyć nowy klaster w którym umieszczone będą słowa niemieszczące się w obecnym,
 Jednak jeśli później chciałbym zedytować słowo będące częścią dwóch tych klastrów na jakieś dłuższe to wtedy musiałbym
 znów przesuwać bardzo wiele literek lub dowawać małe klastry tylko po to aby zmieścić te 2/3 ekstra literki.


Moje pytanie więc jest jak w tytule,
 Jak działają od zaplecza wszystkie edytory tekstowe.

Tzn. jak przechowują długie treści które można edytować w dowolnym miejscu bez przestawiania ogromnych ilości Mb teksu.
P-179959
DejaVu
» 2023-02-13 15:53:15
Dobry edytor plików tekstowych nie wczytywałby całego pliku do pamięci. Ustaliłby po prostu rozmiar pliku na podstawie którego wiedziałby jak długi scroll powinien być. Scrollując ustalałby pozycję od której mniej więcej trzeba wczytać dane i tyle. Opcjonalnie mógłby:
- przeczytać strumieniowo cały plik, aby ustalić pozycje w których występują przejścia do nowego wiersza
- w RAM trzymać pozycje w których zaczynają się konkretne linijki (np. std::vector<uint64_t> pozycjeNowychWierszyWpliku)
- doczytywałby te linijki, które są 'widoczne' na ekranie
- trzymałby w RAM te linijki, które uległy zmianie (std::map<size_t, std::wstring> zmienioneLinijki;, gdzie klucz to numer wiersza, a wartość to zmieniony tekst)
- po kliknięciu 'zapisz' tworzyłby plik tymczasowy przepisując zawartość oryginalnego pliku dla linijek niezmienionych + zapisywał zawartość linijek zmienionych z RAM
- następnie plik oryginalny plik się rename-uje 'old file' i po czym robisz rename pliku tymczasowego aby nosił nazwę pliku docelowego. Old usuwasz (lub nie) w zależności od Twojej polityki.

Struktury musisz dopracować np. pod kątem dopisywania nowych linii oraz usuwania istniejących linii, abyś wiedział, że np. 'między 9, a 10 oryginalnego pliku ma się pojawić 15 nowych wierszy z tekstem'.

/edit:
Trochę statystyki:
Jeżeli miałbyś 1mln wierszy to musiałbyś użyć 8MB ramu na zindeksowanie wierszy (1mln * 8bajtów).
Jeżeli każdy wiersz miałby średnio 200 znaków, to znaczyłoby, że plik z 1mln wierszy waży 200-400MB w zależności od kodowania pliku.
Czyli... uzyskujesz kompresję struktury pliku w pamięci z 400MB do 8MB. Co oznacza, że 40GB plik wciągnąłby Ci 800MB RAM, co brzmi raczej bardzo korzystnie jeżeli w ogóle chcesz pracować z tak ogromnym plikiem.

Reszta to otoczka związana z tym ile danych w pliku masz zmodyfikowanych, które trzeba trzymać w pamięci do momentu ich zapisania na dysku.
P-179960
pekfos
» 2023-02-13 17:18:41
Mój pierwszy pomysł był dość prosty,
 zarejestrować 1024 sloty pamięci typu Char i w każdym trzymać znak -> Text = new char[1024];
 W chwili gdybym potrzebował więcej przestrzeni mógłbym po prostu powiększyć tablicę.

Ale tu pojawia się problem, gdybym miał tekst:
 "To jest mój program do edycji tekstu"

A chciałbym zamienić tekst do:
 "To jest mój <super> program do edycji tekstu"

W tym przypadku musiałbym przesunąć sporo literek w prawo, oczywiście dla krótkiego tekstu nie jest to problemem,
 Ale chciałbym aby program z perspektywy logicznej działał dla dużych i małych tekstów.
To nie zakładaj że fragmenty są stałej długości. Logika się skomplikuje, ale wstawianie czy usuwanie będzie przesuwać w najgorszym razie rozmiar fragmentu, a nie całego pliku.

 ale w tym przypadku użyłem czegoś na wzór LinkedList, podzieliłem tekst na klastry o wielkości 256 znaków
 I każdy klaster posiadał wskaźnik do następnego i poprzedniego klastra.
Co masz z takimi małymi porcjami danych? 2 wskaźniki 64bit to już narzut 5%. Nie ma sensu robić fragmentów mniejszych niż kilkadziesiąt kilobajtów.

- trzymałby w RAM te linijki, które uległy zmianie (std::map<size_t, std::wstring> zmienioneLinijki;, gdzie klucz to numer wiersza, a wartość to zmieniony tekst)
- po kliknięciu 'zapisz' tworzyłby plik tymczasowy przepisując zawartość oryginalnego pliku dla linijek niezmienionych + zapisywał zawartość linijek zmienionych z RAM
Brakuje mi tu opisu jak obsługiwać wstawianie i usuwanie linii, ale jest większy problem: find & replace potencjalnie zmieni wszystkie linie w pliku, więc wyskoczysz z RAMu. Gdy dane nie mieszczą się w RAMie, to patrzymy na algorytmy na taśmach. Ten rejestr zmian powinien być przede wszystkim trzymany w pliku, a struktury w RAMie można dodać później w roli optymalizacji.
Jeśli np zmieni się wszystko, rejestr będzie wielokrotnie większy niż sama treść pliku, więc pewnie trzeba by wykrywać taką sytuację i zapisywać do tempa cały wynikowy plik i liczyć zmiany od niego. No i jeszcze użytkownicy lubią mieć undo/redo na kilka kroków..
Pomijając techniczną możliwość/niemożliwość, jeśli chcesz edytować plik tekstowy 100GB "notatnikiem", to coś poszło mocno w krzaki już na etapie planowania.

Jak działają od zaplecza wszystkie edytory tekstowe.
W większości trzymają dane w RAMie, bo to daje responsywność której oczekuje się od aplikacji GUI. Wielkie dane przetwarza się strumieniowo w terminalu, albo edytorami nieformatowanymi (hex edytorami typowo).

kilka GB duży, mój RAM pozwalał na uruchomienie takiego pliku ale N++ wyświetlił komunikat że za duży.
Z mojego szybkiego eksperymentu wychodzi że użycie RAMu przez N++ to coś między 6x a 8x rozmiar pliku. 6x dla pliku złożonego z samych \n, 8x dla pliku z jedną linią.
P-179961
« 1 »
  Strona 1 z 1