ASCII to plik TEXT, więc możesz go użyć Readersdo czytania. Java obsługuje również odczyt z pliku binarnego przy użyciu InputStreams. Jeśli odczytywane pliki są ogromne, należy użyć jednego BufferedReaderz nich, FileReaderaby poprawić wydajność odczytu.
Przejrzyj ten artykuł na temat korzystania zReader
Polecam również pobranie i przeczytanie tej wspaniałej (jeszcze bezpłatnej) książki o nazwie Thinking In Java
Wybór Czytnika naprawdę zależy od tego, do czego potrzebujesz zawartości pliku. Jeśli plik jest mały (ish) i potrzebujesz go wszystko, to szybciej (testowane przez nas: 1,8-2x) wystarczy użyć FileReadera i odczytać wszystko (lub przynajmniej wystarczająco duże fragmenty). Jeśli przetwarzasz go wiersz po wierszu, wybierz BufferedReader.
Vlad
3
Czy kolejność linii zostanie zachowana podczas korzystania z „Files.lines (..). ForEach (...)”. Rozumiem, że po tej operacji kolejność będzie dowolna.
Daniil Shevelev
38
Files.lines(…).forEach(…)nie zachowuje kolejności wierszy, ale jest wykonywany równolegle @Dash. Jeśli kolejność jest ważna, możesz użyć Files.lines(…).forEachOrdered(…), która powinna zachować kolejność (jednak nie zweryfikowała).
Palec
2
@Palec jest to interesujące, ale czy możesz cytować z dokumentów, w których jest napisane, że Files.lines(...).forEach(...)jest wykonywany równolegle? Myślałem, że dzieje się tak tylko wtedy, gdy wyraźnie ustawiasz strumień równolegle Files.lines(...).parallel().forEach(...).
Klitos Kyriacou,
3
Moja oryginalna formuła nie jest kuloodporna, @KlitosKyriacou. Chodzi o to, że forEachnie gwarantuje żadnego zamówienia, a przyczyną jest łatwa równoległość. Aby zachować porządek, użyj forEachOrdered.
Palec,
687
Moim ulubionym sposobem na odczytanie małego pliku jest użycie BufferedReader i StringBuilder. Jest to bardzo proste i na temat (choć nie jest szczególnie skuteczne, ale wystarczające w większości przypadków):
BufferedReader br =newBufferedReader(newFileReader("file.txt"));try{StringBuilder sb =newStringBuilder();String line = br.readLine();while(line !=null){
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();}String everything = sb.toString();}finally{
br.close();}
Niektórzy zauważyli, że po Javie 7 powinieneś używać funkcji try-with-resources (tj. Automatycznego zamykania):
try(BufferedReader br =newBufferedReader(newFileReader("file.txt"))){StringBuilder sb =newStringBuilder();String line = br.readLine();while(line !=null){
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();}String everything = sb.toString();}
Kiedy czytam takie ciągi, zwykle i tak chcę trochę obsługiwać ciągi dla linii, więc idę do tej implementacji.
Chociaż jeśli chcę po prostu odczytać plik do ciągu, zawsze używam Apache Commons IO z klasą metody IOUtils.toString (). Możesz zajrzeć do źródła tutaj:
try(FileInputStream inputStream =newFileInputStream("foo.txt")){String everything =IOUtils.toString(inputStream);// do something with everything string}
Wprowadziłem niewielką korektę, aby przestać dodawać nową linię (\ n), jeśli dojdzie do ostatniej linii. code while (linia! = null) {sb.append (linia); line = br.readLine (); // Dodaj nową linię tylko wtedy, gdy curline NIE jest ostatnim wierszem .. if (line! = Null) {sb.append ("\ n"); }}code
Ramon Fincken
2
Podobnie do Apache Common IO IOUtils # toString () to sun.misc.IOUtils # readFully (), który jest zawarty w JRE Sun / Oracle.
gb96
3
Aby uzyskać wydajność, zawsze wywoływaj sb.append ('\ n') zamiast sb.append ("\ n"), ponieważ znak jest dodawany do StringBuilder szybciej niż String
gb96
2
FileReader może zgłaszać wyjątek FileNotFoundException, a BufferedRead może zgłaszać wyjątek IOException, więc musisz je złapać.
lub użyj „try-with-resources” try (czytnik FileReader = nowy FileReader (plik))
Hernán Eche
3
Zauważyłem file.length (), jak dobrze to działa z plikami utf-16?
Wayne
5
Ta technika zakłada, że read () wypełnia bufor; że liczba znaków jest równa liczbie bajtów; że liczba bajtów mieści się w pamięci; i że liczba bajtów mieści się w liczbie całkowitej. -1
użytkownik207421,
1
@HermesTrismegistus Podałem cztery powody, dla których jest to błąd. StefanReich ma całkowitą rację, zgadzając się ze mną.
user207421
34
Musiałem porównać różne sposoby. Skomentuję moje ustalenia, ale w skrócie, najszybszym sposobem jest użycie zwykłego starego BufferedInputStream zamiast FileInputStream. Jeśli trzeba odczytać wiele plików, trzy wątki skrócą całkowity czas wykonania do około połowy, ale dodawanie kolejnych wątków stopniowo obniży wydajność, aż do ukończenia trzykrotnie dłużej niż w przypadku dwudziestu wątków niż tylko jednego wątku.
Zakładamy, że musisz przeczytać plik i zrobić coś sensownego z jego zawartością. W przykładach tutaj jest czytanie linii z dziennika i policzenie tych, które zawierają wartości przekraczające określony próg. Zakładam więc, że jednowierszowa Java 8Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";")) nie jest opcją.
Testowałem na Java 1.8, Windows 7 oraz na dyskach SSD i HDD.
Napisałem sześć różnych implementacji:
rawParse : użyj BufferedInputStream na FileInputStream, a następnie wytnij linie czytające bajt po bajcie. To przewyższyło każde inne podejście z jednym wątkiem, ale może być bardzo niewygodne w przypadku plików innych niż ASCII.
lineReaderParse : Użyj BufferedReader nad FileReader, czytaj wiersz po wierszu, dziel linie, wywołując String.split (). Jest to około 20% wolniej niż rawParse.
lineReaderParseParallel : Jest taki sam jak lineReaderParse, ale używa kilku wątków. Jest to najszybsza opcja we wszystkich przypadkach.
nioAsyncParse : użyj AsynchronousFileChannel z modułem obsługi zakończenia i pulą wątków.
nioMemoryMappedParse : Użyj pliku odwzorowanego w pamięci. To naprawdę zły pomysł, który zapewnia czas wykonania co najmniej trzy razy dłuższy niż jakakolwiek inna implementacja.
Są to średnie czasy odczytu 204 plików po 4 MB każdy na czterordzeniowym dysku i7 i dysku SSD. Pliki są generowane w locie, aby uniknąć buforowania dysku.
Znalazłem różnicę mniejszą niż się spodziewałem między uruchomieniem na dysku SSD lub dysku HDD będącym dyskiem SSD o około 15% szybszym. Może to być spowodowane tym, że pliki są generowane na niefragmentowanym dysku twardym i są odczytywane sekwencyjnie, dlatego wirujący napęd może działać prawie jak dysk SSD.
Byłem zaskoczony niską wydajnością implementacji nioAsyncParse. Albo zaimplementowałem coś w niewłaściwy sposób, albo implementację wielowątkową za pomocą NIO, a moduł obsługi zakończenia wykonuje tę samą (lub nawet gorszą) niż implementacja jednowątkowa z API java.io. Ponadto asynchroniczna analiza składniowa z CompletionHandler jest znacznie dłuższa w liniach kodu i trudna do prawidłowego wdrożenia niż prosta implementacja na starych strumieniach.
Teraz sześć implementacji, po których następuje klasa zawierająca je wszystkie oraz parametryzowalna metoda main (), która pozwala grać z liczbą plików, rozmiarem pliku i stopniem współbieżności. Pamiętaj, że rozmiar plików różni się plus minus 20%. Ma to na celu uniknięcie jakiegokolwiek efektu, ponieważ wszystkie pliki mają dokładnie taki sam rozmiar.
rawParse
publicvoid rawParse(finalString targetDir,finalint numberOfFiles)throwsIOException,ParseException{
overrunCount =0;finalint dl =(int)';';StringBuffer lineBuffer =newStringBuffer(1024);for(int f=0; f<numberOfFiles; f++){File fl =newFile(targetDir+filenamePreffix+String.valueOf(f)+".txt");FileInputStream fin =newFileInputStream(fl);BufferedInputStream bin =newBufferedInputStream(fin);int character;while((character=bin.read())!=-1){if(character==dl){// Here is where something is done with each line
doSomethingWithRawLine(lineBuffer.toString());
lineBuffer.setLength(0);}else{
lineBuffer.append((char) character);}}
bin.close();
fin.close();}}publicfinalvoid doSomethingWithRawLine(String line)throwsParseException{// What to do for each lineint fieldNumber =0;finalint len = line.length();StringBuffer fieldBuffer =newStringBuffer(256);for(int charPos=0; charPos<len; charPos++){char c = line.charAt(charPos);if(c==DL0){String fieldValue = fieldBuffer.toString();if(fieldValue.length()>0){switch(fieldNumber){case0:Date dt = fmt.parse(fieldValue);
fieldNumber++;break;case1:double d =Double.parseDouble(fieldValue);
fieldNumber++;break;case2:int t =Integer.parseInt(fieldValue);
fieldNumber++;break;case3:if(fieldValue.equals("overrun"))
overrunCount++;break;}}
fieldBuffer.setLength(0);}else{
fieldBuffer.append(c);}}}
lineReaderParse
publicvoid lineReaderParse(finalString targetDir,finalint numberOfFiles)throwsIOException,ParseException{String line;for(int f=0; f<numberOfFiles; f++){File fl =newFile(targetDir+filenamePreffix+String.valueOf(f)+".txt");FileReader frd =newFileReader(fl);BufferedReader brd =newBufferedReader(frd);while((line=brd.readLine())!=null)
doSomethingWithLine(line);
brd.close();
frd.close();}}publicfinalvoid doSomethingWithLine(String line)throwsParseException{// Example of what to do for each lineString[] fields = line.split(";");Date dt = fmt.parse(fields[0]);double d =Double.parseDouble(fields[1]);int t =Integer.parseInt(fields[2]);if(fields[3].equals("overrun"))
overrunCount++;}
publicvoid nioFilesParse(finalString targetDir,finalint numberOfFiles)throwsIOException,ParseException{for(int f=0; f<numberOfFiles; f++){Path ph =Paths.get(targetDir+filenamePreffix+String.valueOf(f)+".txt");Consumer<String> action =newLineConsumer();Stream<String> lines =Files.lines(ph);
lines.forEach(action);
lines.close();}}classLineConsumerimplementsConsumer<String>{@Overridepublicvoid accept(String line){// What to do for each lineString[] fields = line.split(DL);if(fields.length>1){try{Date dt = fmt.parse(fields[0]);}catch(ParseException e){}double d =Double.parseDouble(fields[1]);int t =Integer.parseInt(fields[2]);if(fields[3].equals("overrun"))
overrunCount++;}}}
nioAsyncParse
publicvoid nioAsyncParse(finalString targetDir,finalint numberOfFiles,finalint numberOfThreads,finalint bufferSize)throwsIOException,ParseException,InterruptedException{ScheduledThreadPoolExecutor pool =newScheduledThreadPoolExecutor(numberOfThreads);ConcurrentLinkedQueue<ByteBuffer> byteBuffers =newConcurrentLinkedQueue<ByteBuffer>();for(int b=0; b<numberOfThreads; b++)
byteBuffers.add(ByteBuffer.allocate(bufferSize));for(int f=0; f<numberOfFiles; f++){
consumerThreads.acquire();String fileName = targetDir+filenamePreffix+String.valueOf(f)+".txt";AsynchronousFileChannel channel =AsynchronousFileChannel.open(Paths.get(fileName),EnumSet.of(StandardOpenOption.READ), pool);BufferConsumer consumer =newBufferConsumer(byteBuffers, fileName, bufferSize);
channel.read(consumer.buffer(),0l, channel, consumer);}
consumerThreads.acquire(numberOfThreads);}classBufferConsumerimplementsCompletionHandler<Integer,AsynchronousFileChannel>{privateConcurrentLinkedQueue<ByteBuffer> buffers;privateByteBuffer bytes;privateString file;privateStringBuffer chars;privateint limit;privatelong position;privateDateFormat frmt =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");publicBufferConsumer(ConcurrentLinkedQueue<ByteBuffer> byteBuffers,String fileName,int bufferSize){
buffers = byteBuffers;
bytes = buffers.poll();if(bytes==null)
bytes =ByteBuffer.allocate(bufferSize);
file = fileName;
chars =newStringBuffer(bufferSize);
frmt =newSimpleDateFormat("yyyy-MM-dd HH:mm:ss");
limit = bufferSize;
position =0l;}publicByteBuffer buffer(){return bytes;}@Overridepublicsynchronizedvoid completed(Integer result,AsynchronousFileChannel channel){if(result!=-1){
bytes.flip();finalint len = bytes.limit();int i =0;try{for(i =0; i < len; i++){byte by = bytes.get();if(by=='\n'){// ***// The code used to process the line goes here
chars.setLength(0);}else{
chars.append((char) by);}}}catch(Exception x){System.out.println("Caught exception "+ x.getClass().getName()+" "+ x.getMessage()+" i="+String.valueOf(i)+", limit="+String.valueOf(len)+", position="+String.valueOf(position));}if(len==limit){
bytes.clear();
position += len;
channel.read(bytes, position, channel,this);}else{try{
channel.close();}catch(IOException e){}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);}}else{try{
channel.close();}catch(IOException e){}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);}}@Overridepublicvoid failed(Throwable e,AsynchronousFileChannel channel){}};
Co chcesz zrobić z tekstem? Czy plik jest wystarczająco mały, aby zmieścił się w pamięci? Spróbuję znaleźć najprostszy sposób obsługi pliku dla twoich potrzeb. Biblioteka FileUtils doskonale się do tego nadaje.
@PeterLawrey prawdopodobnie oznacza org.apache.commons.io.FileUtils. Link Google może z czasem zmieniać treść, ponieważ najbardziej rozpowszechnione znaczenie zmienia się, ale odpowiada to jego zapytaniu i wygląda poprawnie.
Palec
2
Niestety, obecnie nie ma go readLines(String)i readLines(File)jest przestarzały na korzyść readLines(File, Charset). Kodowanie może być również dostarczone jako ciąg.
Udokumentowałem 15 sposobów odczytywania pliku w Javie, a następnie przetestowałem go pod kątem szybkości przy różnych rozmiarach plików - od 1 KB do 1 GB, a oto trzy najlepsze sposoby na zrobienie tego:
import java.io.BufferedReader;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;BufferedReader br;try{
br =newBufferedReader(newFileReader("/fileToRead.txt"));try{String x;while((x = br.readLine())!=null){// Printing out each line in the fileSystem.out.println(x);}}catch(IOException e){
e.printStackTrace();}}catch(FileNotFoundException e){System.out.println(e);
e.printStackTrace();}
Jest to w zasadzie dokładnie to samo, co odpowiedź Jezusa Ramosa, z wyjątkiem File zamiast FileReadera i iteracji umożliwiającej przeglądanie zawartości pliku.
Scanner in =newScanner(newFile("filename.txt"));while(in.hasNext()){// Iterates each line in the fileString line = in.nextLine();// Do something with line}
in.close();// Don't forget to close resource leaks
File vs FileReader: W przypadku FileReadera plik musi istnieć, a uprawnienia systemu operacyjnego muszą umożliwiać dostęp. Za pomocą pliku można przetestować te uprawnienia lub sprawdzić, czy plik jest katalogiem. Plik ma przydatne funkcje: isFile (), isDirectory (), listFiles (), canExecute (), canRead (), canWrite (), istnieje (), mkdir (), delete (). File.createTempFile () zapisuje w domyślnym katalogu temp systemu. Ta metoda zwróci obiekt pliku, którego można użyć do otwarcia obiektów FileOutputStream itp. Źródło
ThisClark
7
Buforowane klasy strumieni są w praktyce znacznie wydajniejsze, do tego stopnia, że interfejs API NIO.2 zawiera metody, które zwracają te klasy strumieni, po części, aby zachęcić Cię do korzystania z buforowanych strumieni w aplikacji.
Oto przykład:
Path path =Paths.get("/myfolder/myfile.ext");try(BufferedReader reader =Files.newBufferedReader(path)){// Read from the streamString currentLine =null;while((currentLine = reader.readLine())!=null)//do your code here}catch(IOException e){// Handle file I/O exception...}
To prawda, powinien być: if(scanner.hasNext()) content = scanner.next();
David Soroko,
1
W przypadku Androida 4.4 to mi się nie udaje. Odczytywane są tylko 1024 bajty. YMMV.
Roger Keays
3
Nie widzę tego jeszcze w innych odpowiedziach. Ale jeśli „Najlepsza” oznacza szybkość, to nowe Java I / O (NIO) może zapewnić najszybszą wydajność, ale nie zawsze najłatwiejszą do znalezienia dla kogoś, kto się uczy.
To może nie być dokładna odpowiedź na pytanie. To po prostu inny sposób odczytywania pliku, w którym nie podajesz wprost ścieżki do pliku w kodzie Java, a zamiast tego czytasz go jako argument wiersza poleceń.
Myślę, że readAllBytes jest szybszy i bardziej precyzyjny, ponieważ nie zastępuje nowej linii, \na także może być nowa linia \r\n. To zależy od twoich potrzeb.
try{File f =newFile("filename.txt");Scanner r =newScanner(f);while(r.hasNextLine()){String data = r.nextLine();JOptionPane.showMessageDialog(data);}
r.close();}catch(FileNotFoundException ex){JOptionPane.showMessageDialog("Error occurred");
ex.printStackTrace();}
O wiele szybciej, wątpię, jeśli użyjesz prostej konkatenacji łańcucha zamiast StringBuilder ...
PhiLho
6
Myślę, że głównym wzrostem prędkości jest odczyt w blokach 1 MB (1024 * 1024). Jednak możesz zrobić to samo, przekazując 1024 * 1024 jako drugi argument do konstruktora BufferedReader.
gb96
3
nie sądzę, żeby to zostało w ogóle przetestowane. użycie +=w ten sposób zapewnia kwadratową (!) złożoność zadania, które powinno być złożonością liniową. zacznie to indeksować pliki powyżej kilku MB. aby obejść ten problem, powinieneś trzymać bloki tekstowe na liście <ciąg> lub użyć wyżej wspomnianego konstruktora łańcuchów.
kritzikratzi
5
Znacznie szybciej niż co? Z pewnością nie jest szybsze niż dołączanie do StringBuffer. -1
użytkownik207421,
1
@ gb96 Tak samo myślałem o rozmiarach buforów, ale szczegółowy eksperyment w tym pytaniu dał zaskakujące wyniki w podobnym kontekście: bufor 16 KB był konsekwentnie i zauważalnie szybszy.
chiastic-security
-3
String fileName ='yourFileFullNameWithPath';File file =newFile(fileName);// Creates a new file object for your fileFileReader fr =newFileReader(file);// Creates a Reader that you can use to read the contents of a file read your fileBufferedReader br =newBufferedReader(fr);//Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
Powyższy zestaw linii można zapisać w 1 pojedynczej linii jako:
Dodawanie do konstruktora łańcuchów (jeśli plik jest ogromny, zaleca się użycie konstruktora łańcuchów, w przeciwnym razie należy użyć zwykłego obiektu String)
try{StringBuilder sb =newStringBuilder();String line = br.readLine();while(line !=null){
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();}String everything = sb.toString();}finally{
br.close();}
Odpowiedzi:
ASCII to plik TEXT, więc możesz go użyć
Readers
do czytania. Java obsługuje również odczyt z pliku binarnego przy użyciuInputStreams
. Jeśli odczytywane pliki są ogromne, należy użyć jednegoBufferedReader
z nich,FileReader
aby poprawić wydajność odczytu.Przejrzyj ten artykuł na temat korzystania z
Reader
Polecam również pobranie i przeczytanie tej wspaniałej (jeszcze bezpłatnej) książki o nazwie Thinking In Java
W Javie 7 :
(dokumenty) lub
(dokumenty)
W Javie 8 :
(dokumenty)
źródło
Files.lines(…).forEach(…)
nie zachowuje kolejności wierszy, ale jest wykonywany równolegle @Dash. Jeśli kolejność jest ważna, możesz użyćFiles.lines(…).forEachOrdered(…)
, która powinna zachować kolejność (jednak nie zweryfikowała).Files.lines(...).forEach(...)
jest wykonywany równolegle? Myślałem, że dzieje się tak tylko wtedy, gdy wyraźnie ustawiasz strumień równolegleFiles.lines(...).parallel().forEach(...)
.forEach
nie gwarantuje żadnego zamówienia, a przyczyną jest łatwa równoległość. Aby zachować porządek, użyjforEachOrdered
.Moim ulubionym sposobem na odczytanie małego pliku jest użycie BufferedReader i StringBuilder. Jest to bardzo proste i na temat (choć nie jest szczególnie skuteczne, ale wystarczające w większości przypadków):
Niektórzy zauważyli, że po Javie 7 powinieneś używać funkcji try-with-resources (tj. Automatycznego zamykania):
Kiedy czytam takie ciągi, zwykle i tak chcę trochę obsługiwać ciągi dla linii, więc idę do tej implementacji.
Chociaż jeśli chcę po prostu odczytać plik do ciągu, zawsze używam Apache Commons IO z klasą metody IOUtils.toString (). Możesz zajrzeć do źródła tutaj:
http://www.docjar.com/html/api/org/apache/commons/io/IOUtils.java.html
A nawet prostsze w Javie 7:
źródło
code
while (linia! = null) {sb.append (linia); line = br.readLine (); // Dodaj nową linię tylko wtedy, gdy curline NIE jest ostatnim wierszem .. if (line! = Null) {sb.append ("\ n"); }}code
Najprostszym sposobem jest użycie
Scanner
klasy w Javie i obiektu FileReader. Prosty przykład:Scanner
ma kilka metod odczytu ciągów, cyfr itp. Więcej informacji na ten temat można znaleźć na stronie dokumentacji Java.Na przykład czytanie całej treści w
String
:Również jeśli potrzebujesz konkretnego kodowania, możesz użyć tego zamiast
FileReader
:źródło
BufferedReader
while ((line = br.readLine()) != null) { sb.append(line); }
?Oto proste rozwiązanie:
źródło
Oto inny sposób, aby to zrobić bez użycia bibliotek zewnętrznych:
źródło
Musiałem porównać różne sposoby. Skomentuję moje ustalenia, ale w skrócie, najszybszym sposobem jest użycie zwykłego starego BufferedInputStream zamiast FileInputStream. Jeśli trzeba odczytać wiele plików, trzy wątki skrócą całkowity czas wykonania do około połowy, ale dodawanie kolejnych wątków stopniowo obniży wydajność, aż do ukończenia trzykrotnie dłużej niż w przypadku dwudziestu wątków niż tylko jednego wątku.
Zakładamy, że musisz przeczytać plik i zrobić coś sensownego z jego zawartością. W przykładach tutaj jest czytanie linii z dziennika i policzenie tych, które zawierają wartości przekraczające określony próg. Zakładam więc, że jednowierszowa Java 8
Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))
nie jest opcją.Testowałem na Java 1.8, Windows 7 oraz na dyskach SSD i HDD.
Napisałem sześć różnych implementacji:
rawParse : użyj BufferedInputStream na FileInputStream, a następnie wytnij linie czytające bajt po bajcie. To przewyższyło każde inne podejście z jednym wątkiem, ale może być bardzo niewygodne w przypadku plików innych niż ASCII.
lineReaderParse : Użyj BufferedReader nad FileReader, czytaj wiersz po wierszu, dziel linie, wywołując String.split (). Jest to około 20% wolniej niż rawParse.
lineReaderParseParallel : Jest taki sam jak lineReaderParse, ale używa kilku wątków. Jest to najszybsza opcja we wszystkich przypadkach.
nioFilesParse : Użyj java.nio.files.Files.lines ()
nioAsyncParse : użyj AsynchronousFileChannel z modułem obsługi zakończenia i pulą wątków.
nioMemoryMappedParse : Użyj pliku odwzorowanego w pamięci. To naprawdę zły pomysł, który zapewnia czas wykonania co najmniej trzy razy dłuższy niż jakakolwiek inna implementacja.
Są to średnie czasy odczytu 204 plików po 4 MB każdy na czterordzeniowym dysku i7 i dysku SSD. Pliki są generowane w locie, aby uniknąć buforowania dysku.
Znalazłem różnicę mniejszą niż się spodziewałem między uruchomieniem na dysku SSD lub dysku HDD będącym dyskiem SSD o około 15% szybszym. Może to być spowodowane tym, że pliki są generowane na niefragmentowanym dysku twardym i są odczytywane sekwencyjnie, dlatego wirujący napęd może działać prawie jak dysk SSD.
Byłem zaskoczony niską wydajnością implementacji nioAsyncParse. Albo zaimplementowałem coś w niewłaściwy sposób, albo implementację wielowątkową za pomocą NIO, a moduł obsługi zakończenia wykonuje tę samą (lub nawet gorszą) niż implementacja jednowątkowa z API java.io. Ponadto asynchroniczna analiza składniowa z CompletionHandler jest znacznie dłuższa w liniach kodu i trudna do prawidłowego wdrożenia niż prosta implementacja na starych strumieniach.
Teraz sześć implementacji, po których następuje klasa zawierająca je wszystkie oraz parametryzowalna metoda main (), która pozwala grać z liczbą plików, rozmiarem pliku i stopniem współbieżności. Pamiętaj, że rozmiar plików różni się plus minus 20%. Ma to na celu uniknięcie jakiegokolwiek efektu, ponieważ wszystkie pliki mają dokładnie taki sam rozmiar.
rawParse
lineReaderParse
lineReaderParseParallel
nioFilesParse
nioAsyncParse
PEŁNE URUCHOMIENIE WSZYSTKICH PRZYPADKÓW
https://github.com/sergiomt/javaiobenchmark/blob/master/FileReadBenchmark.java
źródło
Oto trzy działające i przetestowane metody:
Za pomocą
BufferedReader
Za pomocą
Scanner
Za pomocą
FileReader
Przeczytaj cały plik bez pętli za pomocą
Scanner
klasyźródło
java.nio.file.Files
? Teraz możemy po prostu użyćreadAllLines
,readAllBytes
ilines
.Dostępne metody
org.apache.commons.io.FileUtils
mogą być również bardzo przydatne, np .:źródło
Co chcesz zrobić z tekstem? Czy plik jest wystarczająco mały, aby zmieścił się w pamięci? Spróbuję znaleźć najprostszy sposób obsługi pliku dla twoich potrzeb. Biblioteka FileUtils doskonale się do tego nadaje.
źródło
org.apache.commons.io.FileUtils
. Link Google może z czasem zmieniać treść, ponieważ najbardziej rozpowszechnione znaczenie zmienia się, ale odpowiada to jego zapytaniu i wygląda poprawnie.readLines(String)
ireadLines(File)
jest przestarzały na korzyśćreadLines(File, Charset)
. Kodowanie może być również dostarczone jako ciąg.Udokumentowałem 15 sposobów odczytywania pliku w Javie, a następnie przetestowałem go pod kątem szybkości przy różnych rozmiarach plików - od 1 KB do 1 GB, a oto trzy najlepsze sposoby na zrobienie tego:
java.nio.file.Files.readAllBytes()
Testowany do pracy w Javie 7, 8 i 9.
java.io.BufferedReader.readLine()
Testowany do pracy w Javie 7, 8, 9.
java.nio.file.Files.lines()
Zostało to przetestowane pod kątem działania w Javie 8 i 9, ale nie będzie działać w Javie 7 z powodu wymagań wyrażenia lambda.
źródło
Poniżej znajduje się jedna linijka robienia tego w sposób Java 8. Zakładając, że
text.txt
plik znajduje się w katalogu głównym projektu Eclipse.źródło
Za pomocą BufferedReader:
źródło
Jest to w zasadzie dokładnie to samo, co odpowiedź Jezusa Ramosa, z wyjątkiem File zamiast FileReadera i iteracji umożliwiającej przeglądanie zawartości pliku.
... rzuca
FileNotFoundException
źródło
Buforowane klasy strumieni są w praktyce znacznie wydajniejsze, do tego stopnia, że interfejs API NIO.2 zawiera metody, które zwracają te klasy strumieni, po części, aby zachęcić Cię do korzystania z buforowanych strumieni w aplikacji.
Oto przykład:
Możesz zastąpić ten kod
z
Polecam ten artykuł, aby poznać główne zastosowania Java NIO i IO.
źródło
Prawdopodobnie nie tak szybko, jak w przypadku buforowanych operacji we / wy, ale dość zwięzłe:
\Z
Wzór opowiadaScanner
, że separatorem jest EOF.źródło
if(scanner.hasNext()) content = scanner.next();
Nie widzę tego jeszcze w innych odpowiedziach. Ale jeśli „Najlepsza” oznacza szybkość, to nowe Java I / O (NIO) może zapewnić najszybszą wydajność, ale nie zawsze najłatwiejszą do znalezienia dla kogoś, kto się uczy.
http://download.oracle.com/javase/tutorial/essential/io/file.html
źródło
Najprostszym sposobem odczytu danych z pliku w Javie jest użycie klasy File do odczytania pliku oraz klasy Scanner do odczytania zawartości pliku.
PS: Nie zapomnij zaimportować java.util. *; dla skanera do pracy.
źródło
Guava zapewnia do tego jedno-liniową linię:
źródło
To może nie być dokładna odpowiedź na pytanie. To po prostu inny sposób odczytywania pliku, w którym nie podajesz wprost ścieżki do pliku w kodzie Java, a zamiast tego czytasz go jako argument wiersza poleceń.
Za pomocą następującego kodu
po prostu uruchom i uruchom z:
Spowoduje to odczytanie zawartości
input.txt
i wydrukowanie jej na konsoli.Możesz także
System.out.println()
napisać do określonego pliku za pomocą wiersza poleceń w następujący sposób:Odczytuje to
input.txt
i piszeoutput.txt
.źródło
Możesz użyć readAllLines i
join
metody, aby uzyskać całą zawartość pliku w jednym wierszu:Domyślnie wykorzystuje kodowanie UTF-8, które poprawnie odczytuje dane ASCII.
Możesz także użyć readAllBytes:
Myślę, że readAllBytes jest szybszy i bardziej precyzyjny, ponieważ nie zastępuje nowej linii,
\n
a także może być nowa linia\r\n
. To zależy od twoich potrzeb.źródło
W przypadku aplikacji internetowych Maven opartych na JSF wystarczy użyć ClassLoader i
Resources
folderu, aby odczytać dowolny plik:Umieść zależność IO Apache Commons w swojej POM:
Użyj poniższego kodu, aby go przeczytać (np. Poniżej czyta plik .json):
To samo możesz zrobić dla plików tekstowych, plików .properties, schematów XSD itp.
źródło
Kaktusy dają Ci deklaratywną jednowarstwowość :
źródło
Użyj pocałunku Java, jeśli chodzi o prostotę struktury:
źródło
Wystarczy użyć strumienia Java 8.
źródło
źródło
Najbardziej intuicyjna metoda została wprowadzona w Javie 11
Files.readString
PHP ma ten luksus sprzed kilkudziesięciu lat! ☺
źródło
Ten kod, który zaprogramowałem, jest znacznie szybszy dla bardzo dużych plików:
źródło
+=
w ten sposób zapewnia kwadratową (!) złożoność zadania, które powinno być złożonością liniową. zacznie to indeksować pliki powyżej kilku MB. aby obejść ten problem, powinieneś trzymać bloki tekstowe na liście <ciąg> lub użyć wyżej wspomnianego konstruktora łańcuchów.Powyższy zestaw linii można zapisać w 1 pojedynczej linii jako:
Dodawanie do konstruktora łańcuchów (jeśli plik jest ogromny, zaleca się użycie konstruktora łańcuchów, w przeciwnym razie należy użyć zwykłego obiektu String)
źródło