Kaip sukurti „Java“ eilutę iš failo turinio?

Aš tam tikrą laiką naudoju žemiau pateiktą idiomą. Atrodo, kad tai yra didžiausias platinimas, bent jau lankomose svetainėse.

Ar yra geresnis / kitoks būdas skaityti failą į eilutę „Java“?

 private String readFile(String file) throws IOException { BufferedReader reader = new BufferedReader(new FileReader (file)); String line = null; StringBuilder stringBuilder = new StringBuilder(); String ls = System.getProperty("line.separator"); try { while((line = reader.readLine()) != null) { stringBuilder.append(line); stringBuilder.append(ls); } return stringBuilder.toString(); } finally { reader.close(); } } 
1311
28 нояб. paskelbė OscarRyz 28 d 2008-11-28 21:32 '08 ne 9:32 2008-11-28 21:32
@ 35 atsakymai
  • 1
  • 2

Skaityti visą tekstą iš failo

Čia yra kompaktiškas, patikimas „Java 7“ idiotas, suvyniotas į naudingumo metodą:

 static String readFile(String path, Charset encoding) throws IOException { byte[] encoded = Files.readAllBytes(Paths.get(path)); return new String(encoded, encoding); } 

Teksto eilutės skaitymas iš failo

„Java 7“ pridėjo failo skaitymo būdą kaip teksto eilutes, pateikiamas kaip List<String> . Šis požiūris yra „prarastas“, nes linijos terminatoriai pašalinami iš kiekvienos eilutės pabaigos.

 List<String> lines = Files.readAllLines(Paths.get(path), encoding); 

„Java 8 BufferedReader “ buvo pridėtas naujas lines() metodas, sukuriantis Stream<String> . Jei skaitydami failą susiduriama su „ IOException , ji yra suvyniota į „ UncheckedIOException , nes Stream nepriima lambdas, kuri neįtraukia patikrintų išimčių.

 try (BufferedReader r = Files.newBufferedReader(path, encoding)) { r.lines().forEach(System.out::println); } 

Taip pat yra „ Files.lines() metodas, kuris daro kažką labai panašaus, tiesiogiai grąžindamas Stream<String> . Bet man tai nepatinka. Stream reikalauja close() skambutį; Tai yra blogai dokumentuota API, ir manau, kad daugelis žmonių net nepastebi, kad Stream turi close() metodą. Taigi, jūsų kodas bus labai panašus, pavyzdžiui:

 try (Stream<String> lines = Files.lines(path, encoding)) { lines.forEach(System.out::println); } 

Skirtumas yra tas, kad turite kintamąjį priskirtą Stream , ir aš stengiuosi jį išvengti kaip praktiką, todėl aš netyčia nenoriu du kartus skambinti sraute.

Atminties naudojimas

Pirmasis būdas, kuris taupo linijų pertraukas, gali laikinai reikalauti atminties kelis kartus didesniu nei failo dydis, nes trumpą laiką neapdoroto failo (baitų masyvo) ir dekoduotų simbolių turinys (kiekvienas iš jų yra 16 bitų, net jei jie koduojami kaip 8 bitai faile). ) vienu metu yra atmintyje. Saugiausia taikyti failus, kurie, kaip žinoma, yra nedideli, palyginti su turima atmintimi.

Antrasis metodas, skaitantis eilutes, dažniausiai yra efektyvesnis atminties požiūriu, nes įvesties baito buferis dekodavimui neturėtų apimti viso failo. Tačiau jis vis dar netinka failams, kurie yra labai dideli, palyginti su turima atmintimi.

Norėdami skaityti didelius failus, jums reikia kitokio savo programos dizaino, kuris skaito tekstą iš srauto, apdoroja jį ir tada pereina į kitą, pakartotinai panaudodamas tą patį fiksuoto dydžio atminties bloką. Čia „didelis“ priklauso nuo kompiuterio charakteristikų. Šiuo metu ši riba gali būti daug gigabaitų RAM. Trečiasis būdas, naudojant Stream<String> , yra vienas iš būdų tai padaryti, jei įvesties „įrašai“ yra atskiros eilutės. (Naudojant „ readLine() metodą „ readLine() , šis procesas yra lygiavertis.)

Simbolių kodavimas

Vienas dalykas, kurio trūksta iš pradinio pranešimo, yra simbolių kodavimas. Yra keletas ypatingų atvejų, kai numatytoji platforma yra tai, ko norite, tačiau jie yra reti ir turėtumėte turėti galimybę pagrįsti savo pasirinkimą.

StandardCharsets klasė apibrėžia kai kurias koduotes, reikalingas visiems „Java“ procesams:

 String content = readFile("test.txt", StandardCharsets.UTF_8); 

Pagal numatytuosius nustatymus platforma pasiekiama pačioje „ Charset klasėje :

 String content = readFile("test.txt", Charset.defaultCharset()); 

Pastaba Šis atsakymas iš esmės pakeičia mano „Java 6“ versiją. „Java 7“ programinė įranga saugiai supaprastina kodą, o senas atsakymas, kuris naudojo rodomą baito buferį, neleido ištrinti failo, kuris buvo perskaitytas, kol rodomas buferis bus surinktas šiukšlių. Senąją versiją galite peržiūrėti naudodami „redaguotą“ nuorodą į šį atsakymą.

1340 m
28 нояб. atsakymą pateikė erickson lapkričio 28 d. 2008-11-28 21:56 '08, 21:56, 2008-11-28 21:56

Commons FileUtils.readFileToString :

 public static String readFileToString(File file) throws IOException 

Perskaito failo turinį į eilutę naudodamas numatytąjį VM kodavimą. Failas visada uždarytas.

Parametrai:

  • file - failas, kurį reikia skaityti, neturėtų būti nulinis

Grąžina: failo turinį, niekada

Mesti: - IOException - esant I / O klaidai

C: Commons IO 1.3.1

Kodas, naudojamas (netiesiogiai) pagal šią klasę:

border=0

IOUtils.java pagal Apache License 2.0 .

 public static long copyLarge(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long count = 0; int n = 0; while (-1 != (n = input.read(buffer))) { output.write(buffer, 0, n); count += n; } return count; } 

Jis labai panašus į Ritche_W.

308
28 нояб. Atsakymą pateikė Willi aus Rohr lapkričio 28 d. 2008-11-28 21:44 '08 at 9:44 pm 2008-11-28 21:44

Šiame puslapyje yra labai plonas sprendimas:

 Scanner scanner = new Scanner( new File("poem.txt") ); String text = scanner.useDelimiter("\\A").next(); scanner.close(); // Put this call in a finally block 

arba

 Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" ); String text = scanner.useDelimiter("\\A").next(); scanner.close(); // Put this call in a finally block 

Jei norite nustatyti kodavimą

168
16 сент. Atsakymą pateikė Pablo Grisafi . 2011-09-16 23:02 '11 prie 23:02 2011-09-16 23:02

Jei ieškote alternatyvos, kurioje nėra trečiosios šalies bibliotekos (pvz., I / O Commons ), galite naudoti skaitytuvo klasę:

 private String readFile(String pathname) throws IOException { File file = new File(pathname); StringBuilder fileContents = new StringBuilder((int)file.length()); try (Scanner scanner = new Scanner(file)) { while(scanner.hasNextLine()) { fileContents.append(scanner.nextLine() + System.lineSeparator()); } return fileContents.toString(); } } 
73
28 нояб. atsakymas duotas Dónal 28 lapkričio. 2008-11-28 22:00 '08 22:00 val. 2008-11-28 22:00
 import java.nio.file.Files; import java.nio.file.Paths; String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), "UTF-8"); 

kadangi java 7 galite tai padaryti.

67
28 окт. atsakymas, kurį pateikė Jobin Joseph, spalio 28 d 2016-10-28 10:04 '16 at 10:04 2016-10-28 10:04

Gvajaus metodas panašus į „Commons IOUtils“, kurį paminėjo Willy Aus Rohr:

 import com.google.common.base.Charsets; import com.google.common.io.Files; // ... String text = Files.toString(new File(path), Charsets.UTF_8); 

Redaguoti Oscar Reyes

Tai (supaprastinta) bazinis kodas cituotoje bibliotekoje:

 InputStream in = new FileInputStream(file); byte[] b = new byte[file.length()]; int len = b.length; int total = 0; while (total < len) { int result = in.read(b, total, len - total); if (result == -1) { break; } total += result; } return new String( b , Charsets.UTF_8 ); 

Redaguoti (iš Joniko): aukščiau pateikta informacija neatitinka naujausių „Guava“ versijų kodo. Dabartiniam šaltiniui žr. „ Failai“ , „ CharStreams“ , „ ByteSource“ ir „ CharSource“ klases adresu com.google.common.io .

66
08 февр. atsakymas, pateiktas finnw 08 Feb 2010-02-08 23:08 '10, 11:08 val. 2010-02-08 23:08
 import java.nio.file.Files; 

.......

  String readFile(String filename) { File f = new File(filename); try { byte[] bytes = Files.readAllBytes(f.toPath()); return new String(bytes,"UTF-8"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return ""; } 
51
16 апр. atsakymą pateikė user590444 16 balandžio. 2012-04-16 17:33 '12, 17:33, 2012-04-16 17:33

Šis kodas normalizuos linijų pertraukas, kurios gali arba negali būti tai, ką tikrai norite padaryti.

Čia yra alternatyva, kuri to nepadaro ir kurią (TJO) lengviau suprasti nei NIO kodas (nors jis vis dar naudoja java.nio.charset.Charset ):

 public static String readFile(String file, String csName) throws IOException { Charset cs = Charset.forName(csName); return readFile(file, cs); } public static String readFile(String file, Charset cs) throws IOException { // No real need to close the BufferedReader/InputStreamReader // as they're only wrapping the stream FileInputStream stream = new FileInputStream(file); try { Reader reader = new BufferedReader(new InputStreamReader(stream, cs)); StringBuilder builder = new StringBuilder(); char[] buffer = new char[8192]; int read; while ((read = reader.read(buffer, 0, buffer.length)) > 0) { builder.append(buffer, 0, read); } return builder.toString(); } finally { // Potential issue here: if this throws an IOException, // it will mask any others. Normally I'd use a utility // method which would log exceptions and swallow them stream.close(); } } 
47
28 нояб. Atsakymą pateikė Jon Skeet lapkričio 28 d 2008-11-28 22:56 '08, 10:56 val. 2008-11-28 22:56

Jei jums reikia eilutės apdorojimo (lygiagretus apdorojimas), „Java 8“ turi puikią „Stream“ API.

 String result = Files.lines(Paths.get("file.txt")) .parallel() // for parallel processing .map(String::trim) // to change line .filter(line -> line.length() > 2) // to filter some lines by a predicate .collect(Collectors.joining()); // to join lines 

sample/lambda/BulkDataOperations JDK pavyzdžiuose, kuriuos galima atsisiųsti iš Java Java SE 8 atsisiuntimo puslapio ,

Kitas linijinis pavyzdys

 String out = String.join("\n", Files.readAllLines(Paths.get("file.txt"))); 
46
29 окт. Andrei N 29 d. Atsakymas . 2014-10-29 11:51 '14 at 11:51 am 2014-10-29 11:51

Jei tai yra tekstinis failas, kodėl gi ne naudoti apache commons-io ?

Jis turi tokį metodą

 public static String readFileToString(File file) throws IOException 

Jei norite naudoti sąrašo eilutes

 public static List<String> readLines(File file) throws IOException 
23
17 окт. atsakymas pateikiamas namo laikas 17 val. 2011-10-17 18:34 '11, 18:34, 2011-10-17 18:34

Surinkti visi galimi failo skaitymo būdai, kaip eilutės iš disko ar tinklo.

  • „Guava“: „Google“ naudoja Resources , Files klases

    APACHE - COMMON IO, naudojant IOUtils, FileUtils klases 

    BufferReader“ naudojant „ Stream“ API 

     static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString(); public static String streamURL_Scanner( URL url ) throws IOException { java.io.InputStream source = url.openStream(); Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A"); return scanner.hasNext() ? scanner.next() : ""; } public static String streamFile_Scanner( File file ) throws IOException { Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A"); return scanner.hasNext() ? scanner.next() : ""; } 

  • „Java 7“ ( java.nio.file.Files.readAllBytes )

     public static String getDiskFile_Lines( File file ) throws IOException { StringBuffer text = new StringBuffer(); FileInputStream fileStream = new FileInputStream( file ); BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) ); for ( String line; (line = br.readLine()) != null; ) text.append( line + System.lineSeparator() ); return text.toString(); } 

Pavyzdys su pagrindiniu metodu, kaip pasiekti pirmiau minėtus metodus.

20
29 мая '18 в 13:09 2018-05-29 13:09 atsakymas pateikiamas „ Yash“ gegužės 29 d., 18 val., 13:09 val

Nuo JDK 11:

 String file = ... Path path = Paths.get(file); String content = Files.readString(path); // Or readString(path, someCharset), if you need a Charset different from UTF-8 
19
26 июня '18 в 17:26 2018-06-26 17:26 Atsakymą Leventovas pateikė birželio 26 d. 18 d. 17:26 val. 2018-06-26 17:26

„Java 7“ tai yra mano pageidaujamas variantas skaityti UTF-8 failą:

 String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8"); 

Pradedant „Java 7“, „JDK“ turi naują „ java.nio.file API, kuri suteikia daug nuorodų, todėl trečiosios šalies bibliotekos ne visada reikalingos paprastoms failų operacijoms atlikti.

15
19 апр. Atsakyti Moritz Petersen Bal. 19 2016-04-19 19:39 '16 at 19:39 PM 2016-04-19 19:39

Norėdami skaityti failą kaip dvejetainį ir konvertuoti į pabaigą

 public static String readFileAsString(String filePath) throws IOException { DataInputStream dis = new DataInputStream(new FileInputStream(filePath)); try { long len = new File(filePath).length(); if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes."); byte[] bytes = new byte[(int) len]; dis.readFully(bytes); return new String(bytes, "UTF-8"); } finally { dis.close(); } } 
15
18 апр. Atsakymas, kurį pateikė Peter Lawrey Apr 18 2010-04-18 10:34 '10, 10:34, 2010-04-18 10:34

„Java“ stengiasi būti labai bendru ir lanksčiu, viskas, ką ji daro. Kaip rezultatas, kažkas, kas yra gana paprasta skriptų kalba (jūsų kodas bus pakeistas į „ open(file).read() “ pythone) yra daug sudėtingesnis. Atrodo, kad tai nėra trumpesnis būdas, išskyrus išorinės bibliotekos naudojimą (pvz., Willi aus Rohr ). Jūsų parinktys:

  • Naudokite išorinę biblioteką.
  • Nukopijuokite šį kodą į visus savo projektus.
  • Sukurkite savo mini biblioteką, kuri dažnai naudoja jūsų naudojamas funkcijas.

Jūsų geriausias pasirinkimas tikriausiai yra antrasis, nes jis turi mažiausias priklausomybes.

14
28 нояб. Atsakymas pateikiamas Claudiu 28 lapkričio. 2008-11-28 21:52 '08 at 9:52 pm 2008-11-28 21:52

Jei neturite prieigos prie „ Files klasės, galite naudoti savo sprendimą.

 static String readFile(File file, String charset) throws IOException { FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[fileInputStream.available()]; int length = fileInputStream.read(buffer); fileInputStream.close(); return new String(buffer, 0, length, charset); } 
7
06 янв. Ilya Gazman atsakymas 06 Sau 2015-01-06 21:52 '15 - 21:52 2015-01-06 21:52

Naudojant JDK 8 arba naujesnę:

jokių išorinių bibliotekų nebuvo panaudota

Galite sukurti naują eilutės objektą iš failo turinio (naudojant klases iš java.nio.file paketo):

 public String readStringFromFile(String filePath) throws IOException { String fileContent = new String(Files.readAllBytes(Paths.get(filePath))); return fileContent; } 
7
21 июня '18 в 8:46 2018-06-21 08:46 atsakymas suteikiamas Saikatui birželio 21 d., 18 val., 08:46, 2018-06-21, 08:46

Yra tos pačios temos variacija, kad už „loop“ naudoja, o ne laiką, kad apribotų eilutės apimtį. Ar tai „geresnis“ asmeninio skonio klausimas.

 for(String line = reader.readLine(); line != null; line = reader.readLine()) { stringBuilder.append(line); stringBuilder.append(ls); } 
7
28 нояб. atsakymą pateikė Dan Dyer . 2008-11-28 23:33 '08 at 11:33 2008-11-28 23:33

Vienos linijos sprendimas

 String content = new String(Files.readAllBytes(Paths.get("d://test.txt"))); 
5
03 дек. Atsakymas pateikiamas prashant thakre 03 dec. 2017-12-03 06:50 '17 at 6:50 2017-12-03 06:50

Lankstus sprendimas, naudojant Apache IOUtils commons-io kartu su StringWriter :

 Reader input = new FileReader(); StringWriter output = new StringWriter(); try { IOUtils.copy(input, output); } finally { input.close(); } String fileContents = output.toString(); 

Jis veikia su bet kuriuo skaitytuvu ar įvesties srautu (ne tik su failais), pavyzdžiui, skaitant iš URL.

4
15 февр. Atsakymas pateikiamas vasario 15 d. 2012-02-15 13:47 '12, 13:47, 2012-02-15 13:47
 public static String slurp (final File file) throws IOException { StringBuilder result = new StringBuilder(); BufferedReader reader = new BufferedReader(new FileReader(file)); try { char[] buf = new char[1024]; int r = 0; while ((r = reader.read(buf)) != -1) { result.append(buf, 0, r); } } finally { reader.close(); } return result.toString(); } 
3
08 февр. Atsakymą pateikė Scott S. McCoy 08 vasaris. 2010-02-08 22:51 '10, 10:51, 2010-02-08 22:51

Atminkite, kad naudojant „ fileInputStream.available() grąžinamas sveikasis skaičius neturėtų atspindėti faktinio failo dydžio, o fileInputStream.available() baitų kiekis, kurį sistema turėtų galėti skaityti iš srauto be blokavimo I / O. Saugus ir paprastas būdas gali atrodyti taip:

 public String readStringFromInputStream(FileInputStream fileInputStream) { StringBuffer stringBuffer = new StringBuffer(); try { byte[] buffer; while (fileInputStream.available() > 0) { buffer = new byte[fileInputStream.available()]; fileInputStream.read(buffer); stringBuffer.append(new String(buffer, "ISO-8859-1")); } } catch (FileNotFoundException e) { } catch (IOException e) { } return stringBuffer.toString(); } 

Atkreipkite dėmesį, kad šis metodas netinka daugybinių simbolių kodavimui, pvz., UTF-8.

3
15 марта '13 в 12:09 2013-03-15 12:09 atsakymą pateikė Henry'as kovo 15 d. 13 val. 12:09 2013-03-15 12:09

Galite pabandyti skaitytuvo ir failų klasės, kelių linijų sprendimus

  try { String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next(); System.out.println(content); } catch(FileNotFoundException e) { System.out.println("not found!"); } 
3
07 февр. atsakymą pateikė Jamesas 07 07 vasaris 2017-02-07 09:10 '17 ne 9:10 2017-02-07 09:10

Šiuo metodu naudojamas „ RandomAccessFile.readFully metodas, kuris, atrodo, yra prieinamas iš JDK 1.0!

 public static String readFileContent(String filename, Charset charset) throws IOException { RandomAccessFile raf = null; try { raf = new RandomAccessFile(filename, "r"); byte[] buffer = new byte[(int)raf.length()]; raf.readFully(buffer); return new String(buffer, charset); } finally { closeStream(raf); } } private static void closeStream(Closeable c) { if (c != null) { try { c.close(); } catch (IOException ex) { // do nothing } } } 
3
23 окт. atsakymas, kurį pateikė barjakas spalio 23 d 2011-10-23 10:43 '11 prie 10:43 2011-10-23 10:43

Vienoje eilutėje („Java 8“), jei turite skaitytoją:

 String sMessage = String.join("\n", reader.lines().collect(Collectors.toList())); 
2
15 марта '17 в 5:39 2017-03-15 05:39 atsakymą įteikė Malcolm Boekhoff kovo 15 d. 17, 17:39 2017-03-15 05:39

Naudojant šią biblioteką , tai yra viena eilutė:

 String data = IO.from(new File("data.txt")).toString(); 
2
10 дек. atsakymas duotas 10 d. 2016-12-10 18:55 '16 at 18:55 pm 2016-12-10 18:55

Po Ctrl + F'ing po skaitytuvo, manau, taip pat turiu nurodyti skenerio sprendimą. Paprasčiausiai skaityti, atrodo, tai:

 public String fileToString(File file, Charset charset) { Scanner fileReader = new Scanner(file, charset); fileReader.useDelimiter("\\Z"); // \Z means EOF. String out = fileReader.next(); fileReader.close(); return out; } 

Jei naudojate „Java 7“ ar naujesnę versiją (ir jums iš tikrųjų reikia), pagalvokite, kaip naudoti bandymus su ištekliais, kad kodą būtų lengviau skaityti. Niekas dar neužsikrečia. Tačiau dažniausiai skamba stilistinis pasirinkimas.

Aš siunčiu jį dažniausiai užbaigti, nes jei jums tai reikia padaryti, reikia turėti java.nio.file.Files, kurie turėtų atlikti geresnį darbą.

Mano pasiūlymas būtų naudoti „ Files # readAllBytes“ (kelias), kad būtų galima užfiksuoti visus baitus ir perduoti juos naujam eilutei (baitas [] „Charset“), kad gautumėte eilutę, iš kurios galite pasitikėti. Kodai bus svarbūs jums visą gyvenimą, todėl saugokitės šios medžiagos.

Kiti davė kodą ir daiktus, ir aš nenoriu pavogti jų šlovės.)

2
29 нояб. Haakon Løtveit lapkričio 29 d. Atsakymas 2015-11-29 17:09 '15, 17:09, 2015-11-29 17:09

Remiantis @erickson atsakymu, galite naudoti:

 public String readAll(String fileName) throws IOException { List<String> lines = Files.readAllLines(new File(fileName).toPath()); return String.join("\n", lines.toArray(new String[lines.size()])); } 
2
01 апр. Atsakymas duotas Muskovets 01 balandžio. 2018-04-01 16:34 '18 at 16:34 pm 2018-04-01 16:34

Vartotojas java.nio.Files kad galėtumėte perskaityti visas failo eilutes.

 public String readFile() throws IOException { File fileToRead = new File("file path"); List<String> fileLines = Files.readAllLines(fileToRead.toPath()); return StringUtils.join(fileLines, StringUtils.EMPTY); } 
2
26 окт. atsakymas duotas Nitin Vavdiya 26 okt. 2018-10-26 09:38 '18, 9:38 ; 2018-10-26 09:38

Be to, jei failas yra jar'e, taip pat galite naudoti:

 public String fromFileInJar(String path) { try ( Scanner scanner = new Scanner(getClass().getResourceAsStream(path))) { return scanner.useDelimiter("\\A").next(); } } 

Kelias turi prasidėti / , pavyzdžiui, jei jūsų bankas

 my.jar/com/some/thing/a.txt 

Tada norite jį vadinti taip:

 String myTxt = fromFileInJar("/com/com/thing/a.txt"); 
2
16 февр. Atsakymą pateikė OscarRyz , vasario 16 d. 2017-02-16 00:15 '17 - 0:15 2017-02-16 00:15
  • 1
  • 2

Kiti klausimai apie „ žymų arba „ Užduoti klausimą“