Na Pulpicie mam plik pl.dic. Plik (UTF-8) jest słownikiem języka polskiego, który ma 51,3 MB i 3 638 108 linii. Każda linia to jedno słowo.
Słownik służy mi w IntelliJ do sprawdzania pisowni w komentarzach i javadocs
. Konieczne jest stałe dodawanie nowych słów.
Powstaje problem, który można rozłożyć na kilka zagadnień:
- Jak najłatwiej dodać słowa do pliku?
- Jak sprawdzić czy dodane słowa nie są duplikatami słów w pliku?
- Jak posortować słowa w pliku uwzględniając porządek alfabetu języka polskiego z założeniem, że duże litery nie wpływają na położenie słowa?
- Jak zrobić to bezpiecznie – bez ryzyka utraty danych?
Jak najłatwiej dodać słowa do pliku?
Można dopisac słowa otwierając plik w edytorze Notepad++ (W Notatniku plik otwiera się znacznie dłużej).
Dopisanie do arraylisty
Jesteśmy programistami. Nowe słowa dopisujemy do arraylisty. Potem uruchamiamy klasę AddText
i dodajemy słowa z arraylisty do słownika. Słownik wymaga posortowania
Klasa AddText
package filesorting; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; public class AddText { public static void main(String[] args){ Path plik = Paths.get("C:/Users/Jacek/Desktop/pl.dic"); Charset charset = StandardCharsets.UTF_8; ArrayList<String> words = new ArrayList<>(); words.add("B\u00E9zier"); //---- try { Files.write(plik, words, charset, StandardOpenOption.APPEND); } catch (IOException e) { e.printStackTrace(); } } }
Dopisanie do pliku tekstowego
Na Pulpicie mamy dodatkowy pusty plik words.txt UTF-8.
Do pliku dopisujemy słowa. Uruchamiamy klase AddTextFromFile
, która:
- Wczytuje linie z pliku words.txt do arraylisty
- Zapisuje słowa z arraylisty do pliku pl.dic
- Zeruje plik words.txt
Plik słownika wymaga posortowania
Klasa AddTextFromFile
package filesorting; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.text.Collator; import java.time.Duration; import java.time.Instant; import java.util.*; public class AddTextFromFile { public static void main(String[] args) { Instant start = Instant.now(); Path dicpath1 = Paths.get("C:/Users/Jacek/Desktop/words.txt"); Path dicpath2 = Paths.get("C:/Users/Jacek/Desktop/pl.dic"); Charset charset = StandardCharsets.UTF_8; try { List<String> list = Files.readAllLines(dicpath1, charset); Files.write(dicpath2, list, charset, StandardOpenOption.APPEND); Files.writeString(dicpath1, "", StandardOpenOption.TRUNCATE_EXISTING); } catch (IOException e) { e.printStackTrace(); } Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println(millis); } }
Sortowanie bez sprawdzanie duplikatów
Do posortowania pliku użyjemy klasy SortFile
Klasa kolejno:
- Tworzy ścieżki do pliku słownika i pliku pomocniczego
- Wczytuje zawartość pliku słownika do arraylisty
- Tworzy polski kolator
- Ustawia siłę kolatora (spośób sortowania)
- Sortuje arraylistę przy użyciu kolatora
- Zapisuje zawartość arraylisty do pliku rezerwowego
- Usuwa plik słownika
- Zmienia nazwę pliku rezerwowego na nazwę słownika
Klasa SortFile
Uwaga. Uzycie kolatora powoduje drastyczne przedłużenie czasu sortowania. Sortowanie trwa przeciętnie ok.
70 sek. Przy sortowaniu bez kolatora czas jest rzedu 500 ms.
package filesorting; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.text.Collator; import java.time.Duration; import java.time.Instant; import java.util.*; //Nie weryfikuje czy dodawane słowo jest duplikatem public class SortFile { public static void main(String[] args) { Instant start = Instant.now(); Path dicpath1 = Paths.get("C:/Users/Jacek/Desktop/pl.dic"); Path dicpath2 = Paths.get("C:/Users/Jacek/Desktop/pl1.dic"); Charset charset = StandardCharsets.UTF_8; try { List<String> list = Files.readAllLines(dicpath1, charset); Collator col = Collator.getInstance(new Locale("pl", "PL")); col.setStrength(Collator.SECONDARY); Objects.requireNonNull(list).sort(col); Files.write(dicpath2, list, charset, StandardOpenOption.CREATE_NEW); Files.deleteIfExists(dicpath1); Files.move(dicpath2, dicpath2.resolveSibling("pl.dic")); } catch (IOException e) { e.printStackTrace(); } Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println(millis); } }
Sortowanie ze sprawdzaniem duplikatów
Do posortowania użyjemy klasy SortFileFull
Klasa kolejno
- Tworzy ścieżki do pliku słownika i pliku pomocniczego
- Wczytuje zawartość pliku słownika do arraylisty
- Wczytuje arraylistę do zbioru
TreeSet
. Duplikaty są automatycznie pomijane. - Przepisuje zbiór z powrotem do arraylisty.
- Tworzy polski kolator
- Ustawia siłę kolatora (spośób sortowania)
- Sortuje arraylistę przy użyciu kolatora
- Zapisuje zawartość arraylisty do pliku rezerwowego. Plik jest tworzony i nie powinien wcześniej istnieć.
- Usuwa plik słownika
- Zmienia nazwę pliku rezerwowego na nazwę słownika
Klasa SortFileFull
Uwaga. Użycie kolatora powoduje drastyczne przedłużenie czasu sortowania.
Przpisywanie arraylisty do zbioru i zbioru do arraylisty również przedłuża czas sortowania.
Oczekiwanie na posortowanie pliku trwa 90 – 100 s.
package filesorting; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.text.Collator; import java.time.Duration; import java.time.Instant; import java.util.*; public class SortFileFull { //Odrzuca ewentualne duplikaty public static void main(String[] args) { Instant start = Instant.now(); Path dicpath1 = Paths.get("C:/Users/Jacek/Desktop/pl.dic"); Path dicpath2 = Paths.get("C:/Users/Jacek/Desktop/pl1.dic"); Charset charset = StandardCharsets.UTF_8; try { List<String> list = Files.readAllLines(dicpath1, charset); TreeSet<String> ts = new TreeSet<>(Objects.requireNonNull(list)); ArrayList<String> al = new ArrayList<>(ts); Collator col = Collator.getInstance(new Locale("pl", "PL")); col.setStrength(Collator.SECONDARY); al.sort(col); Files.write(dicpath2, al, charset, StandardOpenOption.CREATE_NEW); Files.deleteIfExists(dicpath1); Files.move(dicpath2, dicpath2.resolveSibling("pl.dic")); } catch (IOException e) { e.printStackTrace(); } Instant end = Instant.now(); long millis = Duration.between(start, end).toMillis(); System.out.println(millis); } }