Jaki jest prosty i kanoniczny sposób wczytywania całego pliku do pamięci w Scali? (Idealnie, z kontrolą kodowania znaków.)
Najlepsze, co mogę wymyślić, to:
scala.io.Source.fromPath("file.txt").getLines.reduceLeft(_+_)
czy mam użyć jednego z okropnych idiomów Javy , z których najlepszym (bez użycia zewnętrznej biblioteki) wydaje się być:
import java.util.Scanner
import java.io.File
new Scanner(new File("file.txt")).useDelimiter("\\Z").next()
Z lektury dyskusji na temat list mailingowych nie jest dla mnie jasne, że scala.io.Source ma być nawet kanoniczną biblioteką I / O. Nie rozumiem dokładnie, jaki jest jego zamierzony cel.
... Chciałbym coś prostego i łatwego do zapamiętania. Na przykład w tych językach bardzo trudno zapomnieć o idiomie ...
Ruby open("file.txt").read
Ruby File.read("file.txt")
Python open("file.txt").read()
Odpowiedzi:
Nawiasem mówiąc, „
scala.
” nie jest tak naprawdę konieczne, ponieważ i tak zawsze ma zasięg, i możesz oczywiście zaimportować zawartość io, całkowicie lub częściowo, i unikać konieczności dodawania „io”. też.Powyższe pozostawia jednak plik otwarty. Aby uniknąć problemów, zamknij go w następujący sposób:
Innym problemem związanym z powyższym kodem jest to, że jest on strasznie wolny ze względu na jego charakter implementacyjny. W przypadku większych plików należy użyć:
źródło
Aby rozwinąć rozwiązanie Daniela, możesz ogromnie skrócić ten proces, wstawiając następujący import do dowolnego pliku wymagającego manipulacji:
Dzięki temu możesz teraz:
Byłbym ostrożny, czytając cały plik w jeden
String
. To bardzo zły nawyk, który gryzie cię wcześniej i mocniej niż myślisz.getLines
Metoda zwraca wartość typuIterator[String]
. W rzeczywistości jest to leniwy kursor w pliku, pozwalający na sprawdzenie tylko potrzebnych danych bez ryzyka nadmiaru pamięci.Aha, i aby odpowiedzieć na twoje dorozumiane pytanie dotyczące
Source
: tak, jest to kanoniczna biblioteka we / wy. Większość kodu używajava.io
ze względu na interfejs niższego poziomu i lepszą kompatybilność z istniejącymi frameworkami, ale każdy kod, który ma wybór, powinien używaćSource
, szczególnie do prostej manipulacji plikami.źródło
źródło
(EDYCJA: To nie działa w Scala 2.9 i może nie 2.8)
Użyj pnia:
źródło
slurp
”? Czy naprawdę porzuciliśmy oczywistą, intuicyjną nazwę? Problemslurp
polega na tym, że może to mieć sens dla kogoś, kto zna angielski jako pierwszy język, ale nigdy nie pomyślałbyś o tym!File
nie jest już w 2.8.0, prawda?slurp
jest fantastyczna! :) Był fantastyczny? Nie znajduję tego ; (Kontrola kodowania znaków i brak zasobów do czyszczenia. Również ewentualnie zoptymalizowany (np.
Files.readAllBytes
Alokując tablicę bajtów odpowiednią do rozmiaru pliku).źródło
Powiedziano mi, że Source.fromFile jest problematyczny. Osobiście miałem problemy z otwieraniem dużych plików za pomocą Source.fromFile i musiałem skorzystać z Java InputStreams.
Innym ciekawym rozwiązaniem jest użycie skalaksu. Oto przykład dobrze skomentowanego kodu, który otwiera plik dziennika za pomocą ManagedResource w celu otwarcia pliku za pomocą helperów: http://pastie.org/pastes/420714
źródło
Użycie getLines () na scala.io.Source odrzuca znaki, które zostały użyte dla terminatorów linii (\ n, \ r, \ r \ n itd.)
Poniższe powinny zachować znak po znaku i nie powodują nadmiernej konkatenacji ciągów (problemy z wydajnością):
źródło
Jeszcze jeden: https://github.com/pathikrit/better-files#streams-and-codecs
Różne sposoby usuwania pliku bez ładowania zawartości do pamięci:
Możesz także podać swój własny kodek do wszystkiego, co wykonuje odczyt / zapis (przyjmuje kod scala.io.Codec.default, jeśli go nie podasz):
źródło
Podobnie jak w Javie, używając biblioteki CommonsIO:
Wiele odpowiedzi tutaj zapomina o Charsecie. Lepiej zawsze podawać to wprost, bo inaczej pewnego dnia trafi.
źródło
Aby emulować składnię Rubiego (i przekazać semantykę) otwierania i czytania pliku, rozważ tę ukrytą klasę (Scala 2.10 i wyższa),
W ten sposób,
źródło
jak kilka osób wspomniało o scala.io.Source najlepiej unikać ze względu na wycieki z połączenia.
Prawdopodobnie scalax i czyste biblioteki Java, takie jak commons-io, są najlepszymi opcjami do czasu scalenia nowego projektu inkubatora (tj. Scala-io).
źródło
możesz także użyć Ścieżki od scala io do odczytu i przetwarzania plików.
Teraz możesz uzyskać ścieżkę do pliku, używając: -
Możesz także dołączyć terminatory, ale domyślnie jest ustawiony na false.
źródło
Aby przyspieszyć ogólny odczyt / przesyłanie (dużego) pliku, rozważ zwiększenie rozmiaru
bufferSize
(Source.DefaultBufSize
ustaw na2048
), na przykład w następujący sposób:Uwaga Source.scala . Dalsza dyskusja znajduje się w sekcji Szybki odczyt pliku tekstowego Scala i przesłanie do pamięci .
źródło
Nie musisz analizować każdej linii, a następnie ponownie łączyć je ...
Wolę użyć tego:
źródło
val content = source.mkString
Codec
. Mam błąd testu,sbt test
ponieważ nie mogę go ustawić, podczas gdy polecenie testowe Intellij zda wszystkie testy. I możeszdef using
z tego skorzystaćJeśli nie masz nic przeciwko zależności od innych firm, powinieneś rozważyć użycie mojej biblioteki OS-Lib . Dzięki temu odczytywanie / zapisywanie plików i praca z systemem plików jest bardzo wygodna:
z pomocnikami jednowierszowymi do odczytu bajtów , odczytu fragmentów , czytania linii i wielu innych przydatnych / typowych operacji
źródło
Oczywistym pytaniem jest „dlaczego chcesz przeczytać w całym pliku?” To oczywiście nie jest skalowalne rozwiązanie, jeśli twoje pliki stają się bardzo duże.
scala.io.Source
Daje grzbiecieIterator[String]
zgetLines
metody, która jest bardzo przydatna i zwięzły.Wymyślenie niejawnej konwersji przy użyciu podstawowych narzędzi IO Java do konwersji a
File
, aReader
lub aInputStream
naString
. Nie jest wielkim zadaniem . Myślę, że brak skalowalności oznacza, że słusznie nie dodają tego do standardowego interfejsu API.źródło
wypisz każdą linię, np. użyj Java BufferedReader przeczytaj każdą linię i wydrukuj:
odpowiednik:
źródło
w argumentach możesz podać ścieżkę do pliku, a to zwróci wszystkie wiersze
źródło