ගොනුවක අන්තර්ගතයෙන් ජාවා නූලක් නිර්මාණය කරන්නේ කෙසේද?


1528

මම දැන් කාලයක් තිස්සේ පහත මෝඩකම භාවිතා කරමි. අවම වශයෙන් මා සංචාරය කළ අඩවි වලවත් එය වඩාත් පුළුල් ලෙස පැතිරී ඇති බව පෙනේ.

ජාවා හි නූලකට ගොනුවක් කියවීමට වඩා හොඳ / වෙනස් ක්‍රමයක් තිබේද?

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();
    }
}

7
NIO හි ඇති දේ කිසිවෙකුට ඉතා සරල ආකාරයකින් පැහැදිලි කළ හැකිද? මම ඒ ගැන කියවන සෑම අවස්ථාවකම නාලිකාව පිළිබඳ
නවවන සඳහන මග හැරී යනු ඇත

7
පද්ධතියේ රේඛා බෙදුම්කරුට සමානව ගොනුවේ ඇති රේඛා බෙදුම්කරු අවශ්‍ය නොවන බව සහතික නොවන බව මතක තබා ගන්න.
හෙන්රික් පෝල්

139
කරුණාකර පා try කයා වැසෙන නිසි උත්සාහයක් ඇතුළත් කිරීමට ඔබට හැකිද? කවුරුහරි ඇත්ත වශයෙන්ම මෙම උදාහරණය භාවිතා කර ඔහුගේ කේතයට දෝෂයක් හඳුන්වා දිය හැකිය.
හාන්ස්-පීටර් ස්ටෝර්

6
ඉහත කේතයේ අවසාන පේළියේ අමතර නව පේළි එකතු කිරීමේ දෝෂයක් ඇත. (Line = reader.readLine ()) = null) {stringBuilder.append (line) නම් එය අනුගමනය කිරීම වැනි දෙයක් විය යුතුය; } අතර (line = reader.readLine ()) = null) {stringBuilder.append (ls); stringBuilder.append (පේළිය); }
ගැඹුරු

27
ජාවා 7 හඳුන්වා දෙයි byte[] Files.readAllBytes(file);, 'එක්-පේළියේ' ස්කෑනර් විසඳුම යෝජනා කරන අයට: ඔබට එය වසා දැමීමට අවශ්‍ය නැද්ද?
Val

Answers:


1551

ගොනුවකින් සියලුම පෙළ කියවන්න

ජාවා 11 මඟින් කුඩා ලිපිගොනු කියවීමට readString () ක්‍රමය එකතු කරන ලදි, රේඛීය පර්යන්තString ආරක්ෂා කරයි:

String content = Files.readString(path, StandardCharsets.US_ASCII);

ජාවා 7 සහ 11 අතර අනුවාද සඳහා, මෙන්න උපයෝගීතා ක්‍රමයකින් ඔතා ඇති සංයුක්ත ශක්තිමත් මෝඩකමක්:

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

ගොනුවකින් පෙළ පේළි කියවන්න

ජාවා 7 ගොනුවක් පෙළ රේඛා ලෙස කියවීමට පහසු ක්‍රමයක් එකතු කළ අතර එය a List<String>. එක් එක් පේළියේ කෙළවරේ සිට රේඛා බෙදුම්කරුවන් ඉවත් කර ඇති නිසා මෙම ප්‍රවේශය "පාඩු" වේ.

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

ජාවා 8 Files.lines()මඟින් නිෂ්පාදනය කිරීමේ ක්‍රමය එකතු කරන ලදී Stream<String>. නැවතත්, මෙම ක්‍රමය පාඩු වන්නේ රේඛා බෙදුම්කරුවන් ඉවත් කර ඇති බැවිනි. IOExceptionගොනුව කියවන විට එය හමු වුවහොත් , එය ඔතා ඇත UncheckedIOException, මන්ද Streamපරීක්ෂා කළ ව්‍යතිරේකයන් විසි කරන ලැම්බඩා පිළිගන්නේ නැත.

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

මේ Streamසඳහා close()ඇමතුමක් අවශ්‍යයි ; මෙය API හි දුර්වල ලෙස ලේඛනගත කර ඇති අතර, බොහෝ අය ක්‍රමවේදයක් Streamඇති බව close()නොදැනේ යැයි මම සැක කරමි . පෙන්වා ඇති පරිදි ARM- බ්ලොක් එකක් භාවිතා කිරීමට වග බලා ගන්න.

ඔබ ගොනුවක් හැර වෙනත් ප්‍රභවයක් සමඟ වැඩ කරන්නේ නම්, ඒ වෙනුවට ඔබට lines()ක්‍රමය භාවිතා කළ හැකිය BufferedReader.

මතක භාවිතය

රේඛීය බිඳීම් ආරක්ෂා කරන පළමු ක්‍රමය, තාවකාලිකව ගොනුවේ ප්‍රමාණය මෙන් කිහිප ගුණයක් මතකය අවශ්‍ය වේ, මන්ද කෙටි කාලයක් සඳහා අමු ගොනු අන්තර්ගතය (බයිට් අරා) සහ විකේතනය කළ අක්ෂර (ඒ සෑම එකක්ම බිටු 16 ක් කේතනය කර තිබුණත්) ගොනුවේ බිටු 8 ක් ලෙස) එකවර මතකයේ රැඳේ. පවතින මතකයට සාපේක්ෂව කුඩා යැයි ඔබ දන්නා ලිපිගොනු වලට අයදුම් කිරීම ආරක්ෂිත වේ.

දෙවන ක්‍රමය, රේඛා කියවීම සාමාන්‍යයෙන් වඩා මතක කාර්යක්‍ෂම වේ, මන්ද විකේතනය සඳහා ආදාන බයිට් බෆරය මුළු ගොනුවම අඩංගු නොවිය යුතුය. කෙසේ වෙතත්, පවතින මතකයට සාපේක්ෂව ඉතා විශාල ගොනු සඳහා එය තවමත් සුදුසු නොවේ.

විශාල ලිපිගොනු කියවීම සඳහා, ඔබේ වැඩසටහන සඳහා වෙනස් මෝස්තරයක් අවශ්‍ය වේ, එය ධාරාවකින් පෙළ කැබැල්ලක් කියවා, එය ක්‍රියාවට නංවා, ඊළඟට ඉදිරියට ගොස් එකම ස්ථාවර ප්‍රමාණයේ මතක වාරණයක් නැවත භාවිතා කරයි. මෙන්න, "විශාල" පරිගණක පිරිවිතර මත රඳා පවතී. වර්තමානයේ, මෙම සීමාව බොහෝ ගිගාබයිට් RAM විය හැකිය. තෙවන ක්‍රමය, a භාවිතා කිරීම Stream<String>මෙය කළ හැකි එක් ක්‍රමයකි, ඔබේ ආදාන “වාර්තා” තනි රේඛා වේ නම්. ( readLine()ක්‍රමවේදය භාවිතා BufferedReaderකිරීම මෙම ප්‍රවේශයට සමාන ක්‍රියා පටිපාටිය වේ.)

අක්ෂර කේතන

මුල් පෝස්ට් එකේ නියැදියෙන් අස්ථානගත වී ඇති එක් දෙයක් නම් අක්ෂර කේතනයයි. වේදිකා පෙරනිමිය ඔබට අවශ්‍ය විශේෂ අවස්ථා කිහිපයක් ඇත, නමුත් ඒවා දුර්ලභ වන අතර ඔබේ තේරීම සාධාරණීකරණය කිරීමට ඔබට හැකි විය යුතුය.

මෙම StandardCharsetsපන්තියේ සියලුම ජාවා runtimes අවශ්ය වන ගැනීමේදී කේතන ක්රමවල සඳහා යම් යම් නියත නිර්වචනය:

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

වේදිකාව පෙරනිමි සිට ලබා ගත හැකි වේ Charsetපන්ති ය:

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

සටහන: මෙම පිළිතුර බොහෝ දුරට මගේ ජාවා 6 අනුවාදය ප්‍රතිස්ථාපනය කරයි. ජාවා 7 හි උපයෝගීතාව කේතය ආරක්ෂිතව සරල කරන අතර, සිතියම්ගත කළ බයිට් බෆරයක් භාවිතා කළ පැරණි පිළිතුර, සිතියම්ගත කළ බෆරය කසළ එකතු කරන තෙක් කියවූ ගොනුව මකා දැමීම වලක්වනු ලැබීය. මෙම පිළිතුරෙහි "සංස්කරණය කරන ලද" සබැඳිය හරහා ඔබට පැරණි අනුවාදය නැරඹිය හැකිය.


3
තාක්ෂණික වශයෙන් ගත් කල, එය කාලය හා අවකාශය තුළ O (n) වේ. ගුණාත්මකව, නූල්වල වෙනස් කළ නොහැකි අවශ්‍යතාවය නිසා එය මතකය මත තරමක් දුෂ්කර ය; තාවකාලිකව මතකයේ දත්ත වල පිටපත් දෙකක් ඇත, තවද කේතනය කළ බයිට් සඳහා කාමරය. තනි බයිට් කේතීකරණයක් යැයි උපකල්පනය කළහොත්, (තාවකාලිකව) ගොනුවේ එක් එක් අක්‍ෂර සඳහා මතක බයිට් 5 ක් අවශ්‍ය වේ. ප්‍රශ්නය විශේෂයෙන් නූලක් ඉල්ලා සිටින බැවින්, එය මා පෙන්වන්නේ, නමුත් ඔබට "විකේතනය" මඟින් ආපසු ලබා දුන් චාර්බෆර් සමඟ වැඩ කළ හැකි නම්, මතක අවශ්‍යතාවය බෙහෙවින් අඩු ය. කාලානුරූපව, ජාවා ලිබ්ස් තුළ ඔබ වේගයෙන් කිසිවක් සොයාගනු ඇතැයි මම නොසිතමි.
එරික්සන්

5
යතුරු ලියනය කළ හැකිද? NIO සතුව java.nio.charset.Charset නමින් චාර්සෙට් (චාර්සෙට් නොවේ) පන්තියක් ඇත. චාර්සෙට් විය යුතුව තිබුණේ මෙයද?
ජොනතන් රයිට්

33
සටහන: එම කේතය ටිකක් ව්‍යායාම කිරීමෙන් පසුව, මෙම ක්‍රමය සමඟ ගොනුව කියවීමෙන් පසු ඔබට එය විශ්වාසදායක ලෙස මකා දැමිය නොහැකි බව මම දැන ගතිමි, එය කිසියම් අවස්ථාවක ගැටළුවක් නොවන නමුත් මගේ නොවේ. එය මෙම ගැටලුව හා සම්බන්ධ විය හැකිද : bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 ? මම අවසානයේ ගියේ මෙම දෝෂයෙන් පීඩා විඳින්නේ නැති ජෝන් ස්කීට්ගේ යෝජනාව සමඟ ය. කෙසේ වෙතත්, මට අවශ්‍ය වූයේ තොරතුරු වෙනත් පුද්ගලයින් සඳහා ලබා දීමට ය ...
සෙබස්තියන් නස්බෝමර්

5
@ සෙබස්තියන් නස්බෝමර්: මමත් මේ ගැටලුව විසඳුවා. දෝෂය "නිවැරදි නොවනු ඇත" යනුවෙන් සලකුණු කර තිබීම පුදුමයකි. මෙයින් සාරභූතව අදහස් වන්නේ FileChannel#mapඑය පොදුවේ භාවිතා කළ නොහැකි බවයි.
ජූනාස් පුලක්ක

4
@ සෙබස්තියන් නස්බෝමර්: ඔරකල් / සන් බග් දත්ත ගබඩාවෙන් දෝෂය මකා දමා ඇත: "මෙම දෝෂය නොමැත." ගූගල් වෙබ් අඩවිය accache.googleusercontent.com/search?q=cache:bugs.sun.com/…
bobndrew

354

ඔබ බාහිර පුස්තකාලයක් භාවිතා කිරීමට කැමති නම්, පරීක්ෂා කරන්න Apache Commons IO (200KB JAR) බලන්න. එය අඩංගු org.apache.commons.io.FileUtils.readFileToString()ඔබ මුළු කියවීමට ඉඩ ක්රමය Fileබවට Stringකේතය එක් රේඛාව සමඟ.

උදාහරණයක්:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}

ඔබ සපයන URL එකෙහි මට එම ක්‍රමය හමු නොවේ.
ඔස්කාර් රයිස්

2
එය පන්තියේ org.apache.commons.io.FileUtils
සිරිල් කා

2
මම FileUtils ද භාවිතා කරමි, නමුත් මම කල්පනා කරන්නේ FileUtils හෝ පිළිගත් nio පිළිතුර භාවිතා කිරීම වඩා හොඳ කුමක්ද?
ගුයිලූම්

4
U ගුයිලූම්: ලොකුම ප්‍රශ්නය වන්නේ තෙවන පාර්ශවීය පුස්තකාලයක් මත යැපීම ඔබට පහසු ද යන්නයි. ඔබේ ව්‍යාපෘතියේ කොමන්ස් අයිඕ හෝ ගුවා තිබේ නම්, එය භාවිතා කරන්න (කේත සරල බව සඳහා පමණි; එසේ නොමැතිනම් සැලකිය යුතු වෙනසක් නොවනු ඇත).
ජොනික්

183

පදනම් කරගත් ඉතා කෙට්ටු විසඳුමක් Scanner:

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

නැතහොත්, ඔබට අක්ෂර මාලාව සැකසීමට අවශ්‍ය නම්:

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

නැතහොත්, ඔබ සමඟ කැඳවිය හැකි සම්පත් සමඟ උත්සාහ කරන්නscanner.close() :

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

Scannerඉදිකිරීම්කරුට විසි කළ හැකි බව මතක තබා ගන්න IOException. හා ආනයනය කිරීමට අමතක කරන්න එපා java.ioසහjava.util .

මූලාශ්‍රය: පැට් නියෙමියර්ගේ බ්ලොගය


4
Work ක්‍රියා කරන්නේ "ගොනුවේ වෙනත් ආරම්භයක්" නොමැති නිසාය, එබැවින් ඔබ ඇත්ත වශයෙන්ම අවසාන ටෝකනය කියවනු ලැබේ ... එයද පළමු වැන්නයි. \\ Z සමඟ කිසි විටෙකත් උත්සාහ කර නැත. ලිපිගොනු, ඉන්පුට්ස්ට්රීම්, නාලිකා වැනි ඔබට කියවිය හැකි ඕනෑම දෙයක් කියවිය හැකි බව සලකන්න ... මම සමහර විට මෙම කේතය සූර්යග්‍රහණයේ දර්ශන කවුළුවෙන් කියවීමට භාවිතා කරමි, මම එක් ගොනුවක් හෝ වෙනත් ගොනුවක් කියවනවාදැයි මට විශ්වාස නැති විට .. .එය, පන්තියේ මාවත ව්‍යාකූල කරයි.
පැබ්ලෝ ග්‍රිසාෆි

1
පෝස්ටරය ලෙස, ගොනුව නිසියාකාරව වසා තිබේදැයි මම නොදනිමි යැයි මට කිව හැකිය ... මම මෙය කිසි විටෙකත් නිෂ්පාදන කේතයේ ලියා නැත, මම එය භාවිතා කරන්නේ පරීක්ෂණ හෝ නිදොස්කරණය සඳහා පමණි.
පැබ්ලෝ ග්‍රිසාෆි

2
එහි
අක්ෂර

21
ස්කෑනරය වසා දැමිය හැකි දෑ ක්‍රියාත්මක කරයි (එය ප්‍රභවයට සමීපව ආයාචනා කරයි) - එබැවින් අලංකාර වන අතර එය සැබවින්ම එක් ලයිනර් එකක් නොවිය යුතුය. බෆරයේ පෙරනිමි ප්‍රමාණය 1024, නමුත් ස්කෑනරය අවශ්‍ය ප්‍රමාණය වැඩි කරයි (ස්කෑනර් # makeSpace () බලන්න)
earcam

8
මෙය හිස් ලිපිගොනු සඳහා අසමත් වේ java.util.NoSuchElementException.
SpaceTrucker

120
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

ජාවා 7 සිට ඔබට එය මේ ආකාරයෙන් කළ හැකිය.


මෙය පිළිතුරක් ලෙස පිළිගත යුතුය - තනි පේළියක්, බාහිර ලිබ් නොමැත.
චෙරි

මෙය ගොනුවේ
නොතිබුණද

79

ඔබ තෙවන පාර්ශවීය පුස්තකාලයකට සම්බන්ධ නොවන විකල්පයක් සොයන්නේ නම් (උදා: පොදු I / O ), ඔබට ස්කෑනර් පන්තිය භාවිතා කළ හැකිය :

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();
    }
}

2
මම හිතන්නේ මෙය හොඳම ක්‍රමයයි. Java.sun.com/docs/books/tutorial/essential/io/scanning.html
Tarski

3
නූලක් පිළිගන්නා ස්කෑනර් ඉදිකිරීම්කරු කියවීමට ගොනුවක නමක් ලෙස සලකන්නේ නැත, නමුත් පරිලෝකනය කළ යුතු පා as ය ලෙස සලකයි. මම හැම වෙලේම ඒ වැරැද්ද කරනවා. : - /
ඇලන් මුවර්

Lan ඇලන්, හොඳ ඇල්ලීම. එය නිවැරදි කිරීම සඳහා මම ඩොන්ගේ පිළිතුර තරමක් සංස්කරණය කළෙමි (මම බලාපොරොත්තු වෙමි).
ජොනික්

3
fileContents.append (scanner.nextLine ()) එකතු කරන්න (lineSeparator);
තහනම-භූ ඉංජිනේරු විද්‍යාව

1
ආරම්භක ප්‍රකාශය වෙනස් කරන්න Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));. එසේ නොමැතිනම් ඔබට ගොනුවේ කොටසක් පමණක් අල්ලා ගත හැකිය.
යැං

71

පේර විලි Aus Rohr සඳහන් බව Commons IOUtils සිට එක් සමාන ක්රමයක් ඇත:

import com.google.common.base.Charsets;
import com.google.common.io.Files;

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

PiggyPiglet විසින් සංස්කරණය කරන්න,
Files#toString එය ඉවත් කිරීමට නියමිත අතර 2019 ඔක්තෝබර් ඉවත් කිරීමට නියමිතය. ඒ වෙනුවට භාවිතා කරන්න Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

සංස්කරණය කරන්න ඔස්කාර් රීස්

උපුටා ගත් පුස්තකාලයේ (සරල) යටින් පවතින කේතය මෙයයි:

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 );

සංස්කරණය කරන්න (ජොනික් විසින්): ඉහත සඳහන් මෑත ගුවා අනුවාදවල ප්‍රභව කේතයට නොගැලපේ. වත්මන් මූලාශ්රය සඳහා, පන්ති බලන්න ගොනු , CharStreams , ByteSource හා CharSource දී com.google.common.io පැකේජය.


මෙම කේතය දිගු සිට int දක්වා වාත්තු කර ඇති අතර එමඟින් විශාල ලිපිගොනු සමඟ පිස්සු හැසිරීමක් ඇතිවිය හැකිය. අමතර ඉඩ ප්‍රමාණයක් ඇති අතර ඔබ ආදාන ප්‍රවාහය වසා දමන්නේ කොතැනින්ද?
මොහොමඩ් තාහර් ඇල්රෙෆේ

@MTA: මෙම විෂය ධාරාව වේ වසා, භාවිතය සටහන් Closerදී CharSource . පිළිතුරේ කේතය සත්‍ය, වර්තමාන ගුවා ප්‍රභවය නොවේ.
ජොනික්

54
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 "";
    }

6
හෝ ඊටත් වඩා සරලයි:new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));

13
හෝ new String(Files.readAllBytes(Paths.get(filename)));:-)
assafmo

1
හොඳින් ක්‍රීඩා කර ඇති අතර ඊළඟ පුද්ගලයා Pathsගූග්ලිං බේරා ගැනීම සඳහා පෙනෙන ආකාරයට 1.7+ වේ FileSystems. (Dang it!)
ruffin

4
ලැජ්ජයි, මෙම පිළිතුරට වැඩි ඡන්ද ප්‍රමාණයක් නොමැත. පෙළ ගොනුවක් නූල් බවට පත් කිරීමට ඉක්මන්ම හා සරලම ක්‍රමය මම සොයමින් සිටියෙමි. මෙය එයයි. මම පහළට සහ පහළට අනුචලනය නොකළේ නම් මට එය මග හැරෙනු ඇත. මෙම පිළිතුර ඉහළට ගෙනයාම සඳහා පිළිගැනීම OP විසින් සලකා බැලිය යුතුය.
කටු

Orthorn මෙම පිළිතුරෙහි භයානක දෝෂ හැසිරවීමක් ඇත. නිෂ්පාදන කේතය තුළ මෙම ක්‍රමය භාවිතා නොකරන්න, හෝ වඩා හොඳ: කිසි විටෙකත්.
xehpuk

51

ඔබට නූල් සැකසුම් (සමාන්තර සැකසුම්) අවශ්‍ය නම් ජාවා 8 හි විශිෂ්ට ධාරා 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

තවත් උදාහරණ JDK සාම්පල ලබා ගත හැක sample/lambda/BulkDataOperationsබාගත කර ගත හැකි බව ඔරකල් ජාවා SE 8 අවපතන පිටුවට

තවත් එක් ලයිනර් උදාහරණයක්

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));

. සමාන්තර () සිදුවන්නේ ඔබ පේළි කියවීමෙන් පසුව හෝ ඊට පෙරද?
ඉස්තාන්

පර්යන්ත මෙහෙයුම් එකතු කිරීම (...) ක්‍රියාත්මක වන බැවින් සැබෑ වැඩ ආරම්භ වේ. ප්‍රවාහය රේඛාව අනුව කම්මැලි ජනගහනයකින් යුක්ත වේ. සැකසීමට පෙර මුළු ගොනුවම මතකයේ කියවීමට අවශ්‍ය නැත (උදා: පෙරීම සහ සිතියම්කරණය).
ඇන්ඩ්‍රි එන්

හිස් නොවන රේඛා තෝරා ගැනීමට පෙර කපන්න?
Thorbj Rrn Ravn Andersen

51

එම කේතය ඔබට සැබවින්ම කිරීමට අවශ්‍ය දේ හෝ නොවිය හැකි රේඛා බිඳීම් සාමාන්‍යකරණය කරයි.

මෙන්න එය නොකරන විකල්පයක් වන අතර (IMO) NIO කේතයට වඩා තේරුම් ගැනීමට පහසුය (එය තවමත් භාවිතා වුවද 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();
    }        
}

1
මෙම පැරණි අදහස් දැක්වීමක් නැවත පණ ගැන්වීම ගැන මට සමාව දෙන්න, නමුත් ඔබ අදහස් කළේ "ගොනුව" නමින් හැඳින්වෙන සංගීත වස්තුවක් පසුකර යාමටද, නැතහොත් එය ගොනු වස්තුවක් විය යුතුද?
බ්‍රයන් ලාර්සන්

28

ගොනුව තැටියෙන් හෝ ජාලයෙන් String ලෙස කියවීමට හැකි සියලු ක්‍රම එක්රැස් කරන ලදි.

  • ගුවා: පන්ති භාවිතා කරන ගූගල්Resources ,Files

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }

  • APACHE - IOUtils , FileUtils පන්ති භාවිතා කරන පොදු IO

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }

  • ජාවා 8 Bufferreader භාවිතා විෂය ධාරාව API

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }

  • රීජෙක්ස් සමඟ ස්කෑනර් පන්තිය \A. එය ආදානයේ ආරම්භයට ගැලපේ.

    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() : "";
    }

  • ජාවා 7 ( java.nio.file.Files.readAllBytes)

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }

  • BufferedReaderභාවිතා කිරීම InputStreamReader.

    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();
    }

ඉහත ක්‍රමවලට ප්‍රවේශ වීම සඳහා ප්‍රධාන ක්‍රමය සමඟ උදාහරණය.

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@ බලන්න


26

එය පෙළ ගොනුවක් නම් අපාචේ කොමන්ස්- io භාවිතා නොකරන්නේ ඇයි ?

එයට පහත ක්‍රමවේදය ඇත

public static String readFileToString(File file) throws IOException

ඔබට ලැයිස්තුවක් ලෙස පේළි අවශ්‍ය නම්

public static List<String> readLines(File file) throws IOException

25

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

ඇයි, අනේ, 2018 දී සුපුරුදු අක්ෂර මාලාව මත රඳා පවතින නව ක්‍රම හඳුන්වා දෙන්න?
mryan

2
rymryan මෙම ක්‍රමය පෙරනිමි පද්ධති අක්ෂර කට්ටලය මත රඳා නොපවතී. එය UTF-8 වෙත පෙරනිමිය, එය හොඳයි.
ලෙවෙන්ටොව්

@leventov ඔයා හරි! Files.readAllLines ද එසේමය! එමඟින් ගොනු API පැරණි ක්‍රම සමඟ නොගැලපෙන නමුත් එය වඩා හොඳ වේ :)
mryan

17

ගොනුවක් ද්විමය ලෙස කියවා අවසානයේ පරිවර්තනය කිරීම

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();
    }
}

16

ජාවා උත්සාහ කරන්නේ අතිශයින්ම සාමාන්‍ය හා නම්‍යශීලී වීමටයි. එහි ප්‍රති As ලයක් ලෙස, ස්ක්‍රිප්ටින් භාෂාවක සාපේක්ෂව සරල දෙයක් (ඔබේ කේතය පයිතන්හි " open(file).read()" සමඟ ප්‍රතිස්ථාපනය වේ) වඩා සංකීර්ණ වේ. බාහිර පුස්තකාලයක් භාවිතා කිරීම හැර ( විලී ඕස් රෝර් සඳහන් කළ පරිදි) එය කිරීමට කෙටි ක්‍රමයක් ඇති බවක් නොපෙනේ . ඔබේ විකල්ප:

  • බාහිර පුස්තකාලයක් භාවිතා කරන්න.
  • ඔබගේ සියලු ව්‍යාපෘති වලට මෙම කේතය පිටපත් කරන්න.
  • ඔබ නිතර භාවිතා කරන කාර්යයන් අඩංගු ඔබේම කුඩා පුස්තකාලයක් සාදන්න.

ඔබගේ හොඳම ඔට්ටුව 2 වන එක විය හැකිය, එයට අවම පරායත්තතා ඇත.


4
ඔව්. එමඟින් "ඉහළ" මට්ටමේ භාෂාව වෙනත් අර්ථයක් ගනී. සී සමඟ සසඳන විට ජාවා ඉහළ මට්ටමක පවතින නමුත් පයිතන් හෝ රූබි සමඟ සසඳන විට අඩුයි
ඔස්කාර් රයිස්

3
ජාවා ඉහළ මට්ටමේ වියුක්ත කිරීම් මත ඇති නමුත් පහසුව සඳහා කෙටි ක්‍රමවේදයන් ඇති බවට එකඟ වන්න
ඩෙනල්

3
ඇත්ත වශයෙන්ම, ජාවා ලිපිගොනු සමඟ ගනුදෙනු කිරීමේ උමතු සංඛ්‍යාවක් ඇති අතර ඒවායින් බොහොමයක් සංකීර්ණ බව පෙනේ. නමුත් මෙය ඉහළ මට්ටමේ භාෂාවලින් අප සතුව ඇති දෙයට තරමක් සමීප ය:byte[] bytes = Files.readAllBytes(someFile.toPath());
Thorn

16

ජාවා 7 සමඟ, යූටීඑෆ් -8 ගොනුවක් කියවීමට මෙය මගේ ප්‍රියතම විකල්පයයි:

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

ජාවා 7 සිට, JDK සතුව නව java.nio.fileAPI ඇත, එය බොහෝ කෙටිමං සපයයි, එබැවින් සරල ගොනු මෙහෙයුම් සඳහා තෙවන පාර්ශවීය පුස්තකාල සැමවිටම අවශ්‍ය නොවේ.


11

JDK 8 හෝ ඊට වැඩි භාවිතා කිරීම:

බාහිර පුස්තකාල භාවිතා නොකෙරේ

ගොනු අන්තර්ගතයෙන් ඔබට නව සංගීත වස්තුවක් නිර්මාණය කළ හැකිය ( java.nio.fileපැකේජයෙන් පන්ති භාවිතා කිරීම ):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}

ලියූ මොරිට්ස් පීටර්සන්ගේ පිටපත: නූල් අන්තර්ගතය = නව නූල් (Files.readAllBytes (Paths.get (ගොනු නාමය)), "UTF-8");
ජීන්-ක්‍රිස්ටෝෆ් බ්ලැන්චාර්ඩ්

8

රේඛීය විචල්‍යයේ විෂය පථය සීමා කිරීම සඳහා, ටික වේලාවක් වෙනුවට, ලූපයක් සඳහා භාවිතා කරන එකම තේමාවේ වෙනසක් ඇත. එය "වඩා හොඳ" ද යන්න පෞද්ගලික රුචිකත්වයට කරුණකි.

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}

3
මෙය නව රේඛා පෙරනිමි නව රේඛා තේරීමට වෙනස් කරයි. මෙය යෝග්‍ය හෝ අනපේක්ෂිත විය හැකිය.
පීටර් ලෝරි

මෙම පිළිතුර සංස්කරණයට පෙරළා දැමුවේ ලක්ෂ්‍යය lineවිචල්‍යයේ විෂය පථය පටු කිරීම නිසාය . සංස්කරණය එය දෙවරක් ප්‍රකාශයට පත් කළ අතර එය සම්පාදක දෝෂයකි.
ඩෑන් ඩයර්

7

ඔබට Filesපන්තියට ප්‍රවේශය නොමැති නම් , ඔබට ස්වදේශීය විසඳුමක් භාවිතා කළ හැකිය.

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);
}

ආයාචනා කිරීමට උදාහරණ අක්ෂර කට්ටලය?
Thufir

4

StringWriter සමඟ ඒකාබද්ධව Apache commons-io වෙතින් IOUtils භාවිතා කරන නම්‍යශීලී විසඳුමක් :

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

එය ඕනෑම පා er කයෙකු හෝ ආදාන ප්‍රවාහයක් සමඟ ක්‍රියා කරයි (ලිපිගොනු සමඟ පමණක් නොවේ), උදාහරණයක් ලෙස URL එකකින් කියවීමේදී.


3

fileInputStream.available()ආපසු ලබා දුන් නිඛිලය භාවිතා කරන විට සත්‍ය ගොනු ප්‍රමාණය නිරූපණය කළ යුතු නැත, නමුත් අනුමාන කළ බයිට් ප්‍රමාණය පද්ධතියට IO අවහිර නොකර ප්‍රවාහයෙන් කියවිය හැකිය. ආරක්ෂිත හා සරල ක්‍රමයක් මේ වගේ විය හැකිය

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();
}

UTF-8 වැනි බහු-බයිට් අක්ෂර කේතන සඳහා මෙම ප්‍රවේශය සුදුසු නොවන බව සැලකිල්ලට ගත යුතුය .


1
මෙම කේතය අනපේක්ෂිත ප්‍රති .ල ලබා දිය හැකිය. අනුව ප්රලේඛනය පිළිබඳ available()ක්රමය, ගොනු අවසන් වන අවස්ථාවකදී, ක්රමය, 0 නැවත බව එවැනි අවස්ථාවක දී ඔබ අසම්පූර්ණ ගොනුව සමග අවසන් විය එකඟ වී ඇති කිසිදු සහතිකයක් නැත. නරකම දෙය නම්, ඇත්ත වශයෙන්ම කියවන ලද බයිට් ගණන ආපසු ලබා දුන් වටිනාකමට වඩා කුඩා විය හැකි available()අතර එවිට ඔබට දූෂිත ප්‍රතිදානය ලැබේ.
wau

3

මෙය ක්‍රමය භාවිතා කරයි RandomAccessFile.readFully, එය 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

ඔබට ස්කෑනර් සහ ගොනු පන්තිය උත්සාහ කළ හැකිය, පේළි කිහිපයක් විසඳුම

 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

java.nio.Filesසියලුම ලිපිගොනු කියවීමට පරිශීලකයා .

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}

3
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();
}

වේදිකා පෙරනිමි කේතීකරණය භාවිතා කරමින් මෙය අපහසුතාවයට පත්ව ඇතැයි මම සිතමි. +1 කෙසේ වෙතත් :)
ඔස්කාර් රයිස්

7
උත්සාහක කොටසෙහි අර්ථ දක්වා ඇති විචල්‍යයන් අවසාන වාරණය නොදන්නා බව මට පෙනේ. javac 1.6.0_21 දෝෂය විසි කරයි cannot find symbol.
ceving

ඔබ ඔබේම කේතයක් පවා උත්සාහ කර තිබේද? ඔබ උත්සාහ කරන්නා / අල්ලා ගැනීමේ කොටසෙහි පා er කයා නිර්වචනය කර ඇත, එබැවින් එය අවසානයේ වාරණය කිරීමේදී ප්‍රවේශ විය නොහැක.
mauron85

2

මට තවම වෙනත් සටහන් දැක්විය නොහැක, එබැවින් මම එය මෙහි තබමි.

මෙහි හොඳම පිළිතුරු වලින් එකක් ( https://stackoverflow.com/a/326448/1521167 ):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

තවමත් එක් අඩුපාඩුවක් ඇත. එය සෑම විටම නව රේඛා වර්‍ගයක් නූල් අවසානයේ තබයි, එමඟින් සමහර විකාර දෝෂ ඇති විය හැක. මගේ යෝජනාව එය වෙනස් කිරීම:

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}

පළමු අවස්ථාවේ දී ඔබ අවසානයේ අතිරේක නව රේඛාවක් එකතු කරනවා විය හැකිය. දෙවන අවස්ථාවේදී ඔබ එකක් මඟ හැරිය හැක. එබැවින් දෙකම එක හා සමානව වැරදිය. මෙම ලිපිය
පැට්‍රික් පාකර්

2

ස්කෑනරයෙන් පසු Ctrl + F'ing පසු, ස්කෑනර් විසඳුම ද ලැයිස්තු ගත කළ යුතු යැයි මම සිතමි. විලාසිතා කියවීමට පහසුම ආකාරයෙන් එය මෙසේ ය:

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;
}

ඔබ ජාවා 7 හෝ නව භාවිතා කරන්නේ නම් (සහ ඔබ සැබවින්ම කළ යුත්තේ) කේතය කියවීම පහසු කිරීම සඳහා සම්පත් සමඟ උත්සාහ කිරීම සලකා බලන්න. සෑම දෙයක්ම පැටව් ගසන තිත්-සමීප දේවල් නැත. නමුත් එය බොහෝ දුරට ශෛලීය තේරීම් මෙතික්ස් ය.

මම මෙය වැඩිපුරම පළ කරන්නේ සම්පූර්ණ කිරීම සඳහා ය, මන්ද ඔබට මෙය බොහෝ දේ කිරීමට අවශ්‍ය නම්, java.nio.file.Files හි දේවල් තිබිය යුතු අතර එම කාර්යය වඩා හොඳින් කළ යුතුය.

මගේ යෝජනාව වනුයේ සියලුම බයිට් අල්ලා ගැනීමට ලිපිගොනු # readAllBytes (Path) භාවිතා කිරීම සහ ඔබට විශ්වාස කළ හැකි නූලක් ලබා ගැනීම සඳහා එය නව සංගීත (බයිට් [] චාර්සෙට්) වෙත පෝෂණය කිරීමයි . ඔබගේ ජීවිත කාලය තුළ අක්ෂර කට්ටල ඔබට පහත් වනු ඇත, එබැවින් දැන් මේ දේවල් වලින් පරිස්සම් වන්න.

තවත් සමහරු කේත සහ දේවල් ලබා දී ඇති අතර ඔවුන්ගේ මහිමය සොරකම් කිරීමට මට අවශ්‍ය නැත. ;)



2

ඔබේ ගොනුව භාජනයක් තුළ තිබේ නම්, ඔබට මෙයද භාවිතා කළ හැකිය:

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

/ ඔබේ බඳුන නම් මාර්ගය ආරම්භ විය යුතුය

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

එවිට ඔබට එය මේ ආකාරයට කැඳවීමට අවශ්‍යයි:

String myTxt = fromFileInJar("/com/com/thing/a.txt");

2

එක් පේළියක (ජාවා 8), ඔබට පා er කයෙකු ඇතැයි උපකල්පනය කරන්න:

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));

2

@ එරික්සන්ගේ පිළිතුර මත පදනම්ව, ඔබට මෙය භාවිතා කළ හැකිය:

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()]));
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.