java - मैं फ़ाइल की सामग्री से जावा स्ट्रिंग कैसे बना सकता हूं?




file file-io (20)

फ़ाइल से सभी पाठ पढ़ें

जावा 7 के लिए एक कॉम्पैक्ट, मजबूत मुहावरे है, जो एक उपयोगिता विधि में लपेटा गया है:

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

फ़ाइल से पाठ की रेखाएं पढ़ें

जावा 7 ने एक फ़ाइल को पाठ की पंक्तियों के रूप में पढ़ने के लिए एक सुविधा विधि जोड़ा , जो List<String> रूप में दर्शाया गया है। यह दृष्टिकोण "हानिकारक" है क्योंकि रेखा विभाजक प्रत्येक पंक्ति के अंत से अलग हो जाते हैं।

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

जावा 8 में, BufferedReader ने Stream<String> बनाने के लिए एक नई विधि, lines() जोड़ दी। यदि फ़ाइल पढ़ने के दौरान IOException का सामना करना IOException है, तो यह एक IOException में लपेटा जाता है, क्योंकि Stream IOException स्वीकार नहीं करता है जो चेक अपवादों को फेंक देता है।

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

एक Files.lines() विधि भी है जो कुछ बहुत समान होती है, Stream<String> सीधे लौटती है। लेकिन मुझे यह पसंद नहीं है। Stream को एक close() कॉल की आवश्यकता है; यह एपीआई पर खराब दस्तावेज है, और मुझे संदेह है कि कई लोगों को यह भी ध्यान नहीं दिया जाता है कि Stream में एक close() विधि है। तो आपका कोड बहुत समान दिखाई देगा, इस तरह:

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

अंतर यह है कि आपके पास एक चर को आवंटित Stream , और मैं इसे एक अभ्यास के रूप में टालने का प्रयास करता हूं ताकि मैं गलती से दो बार स्ट्रीम को आज़माने की कोशिश न करूं।

मेमोरी उपयोग

पहली विधि, जो लाइन ब्रेक को बरकरार रखती है, अस्थायी रूप से फ़ाइल के आकार को स्मृति के लिए अस्थायी रूप से आवश्यक कर सकती है, क्योंकि कच्चे फ़ाइल की सामग्री (एक बाइट सरणी), और डीकोडेड वर्णों में से कम समय के लिए (जिनमें से प्रत्येक एन्कोडेड होने पर भी 16 बिट्स है फ़ाइल में 8 बिट्स के रूप में) एक बार में स्मृति में रहते हैं। उन फ़ाइलों पर लागू करना सबसे सुरक्षित है जिन्हें आप उपलब्ध स्मृति के छोटे सापेक्ष होने के बारे में जानते हैं।

दूसरी विधि, पढ़ने वाली रेखाएं आमतौर पर अधिक मेमोरी कुशल होती हैं, क्योंकि डिकोडिंग के लिए इनपुट बाइट बफर को पूरी फ़ाइल को रखने की आवश्यकता नहीं होती है। हालांकि, यह अभी भी उन फ़ाइलों के लिए उपयुक्त नहीं है जो उपलब्ध स्मृति के सापेक्ष बहुत बड़े हैं।

बड़ी फ़ाइलों को पढ़ने के लिए, आपको अपने प्रोग्राम के लिए एक अलग डिज़ाइन की आवश्यकता होती है, जो एक स्ट्रीम से पाठ का एक हिस्सा पढ़ता है, इसे संसाधित करता है, और फिर उसी फिक्स्ड-साइज्ड मेमोरी ब्लॉक का पुन: उपयोग करते हुए अगले पर चलता है। यहां, "बड़ा" कंप्यूटर चश्मे पर निर्भर करता है। आजकल, यह दहलीज रैम के कई गीगाबाइट हो सकती है। Stream<String> का उपयोग करने वाली तीसरी विधि यह करने का एक तरीका है, यदि आपका इनपुट "रिकॉर्ड" अलग-अलग रेखाएं होती है। ( BufferedReader की readLine() विधि का उपयोग इस दृष्टिकोण के समतुल्य प्रक्रियात्मक है।)

अक्षरों को सांकेतिक अक्षरों में बदलना

मूल पोस्ट में नमूना से गुम एक चीज चरित्र एन्कोडिंग है। कुछ विशेष मामले हैं जहां मंच डिफ़ॉल्ट आप चाहते हैं, लेकिन वे दुर्लभ हैं, और आप अपनी पसंद को औचित्य साबित करने में सक्षम होना चाहिए।

StandardCharsets क्लास सभी जावा रनटाइम्स की आवश्यक एन्कोडिंग के लिए कुछ स्थिरांक परिभाषित करता है:

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

प्लेटफार्म डिफ़ॉल्ट Charset वर्ग से ही उपलब्ध है:

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

नोट: यह उत्तर बड़े पैमाने पर मेरे जावा 6 संस्करण को प्रतिस्थापित करता है। जावा 7 की उपयोगिता कोड को सुरक्षित रूप से सरल बनाती है, और पुराना उत्तर, जो मैप किए गए बाइट बफर का उपयोग करता है, ने उस फ़ाइल को रोक दिया जो मैप किए गए बफर को कचरा इकट्ठा होने तक हटाया जाने से पढ़ा गया था। आप इस उत्तर पर "संपादित" लिंक के माध्यम से पुराना संस्करण देख सकते हैं।

मैं अब कुछ समय के लिए मुहावरे का उपयोग कर रहा हूं। और कम से कम उन साइटों पर, जो मैंने देखा है, सबसे व्यापक रूप से फैलता प्रतीत होता है।

जावा में स्ट्रिंग में फ़ाइल को पढ़ने के लिए कोई बेहतर / अलग तरीका है?

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

@ एरिक्सन के उत्तर के आधार पर, आप इसका उपयोग कर सकते हैं:

public void readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}

आप स्कैनर और फ़ाइल क्लास, कुछ लाइन समाधान का प्रयास कर सकते हैं

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}

एक पंक्ति में (जावा 8), मानते हुए कि आपके पास रीडर है:

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

कोड का प्रयोग करें:

File file = new File("input.txt");
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(
                file));
byte[] buffer = new byte[(int) file.length()];
bin.read(buffer);
String fileStr = new String(buffer);

fileStr में स्ट्रिंग में आउटपुट होता है।


जावा 7 के साथ, यह यूटीएफ -8 फ़ाइल पढ़ने के लिए मेरा पसंदीदा विकल्प है:

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

जावा 7 के बाद से, java.nio.file में नया java.nio.file एपीआई है, जो कई शॉर्टकट प्रदान करता है, इसलिए सरल फ़ाइल संचालन के लिए तीसरे पक्ष के पुस्तकालयों की हमेशा आवश्यकता नहीं होती है।


जावा यह सब कुछ करता है में बेहद सामान्य और लचीला होने का प्रयास करता है। नतीजतन, कुछ जो एक स्क्रिप्टिंग भाषा में अपेक्षाकृत सरल है (आपका कोड " open(file).read() " पायथन में बदल दिया जाएगा) बहुत अधिक जटिल है। बाहरी पुस्तकालय (जैसे विली औस रोहर का उल्लेख) को छोड़कर, ऐसा करने का कोई छोटा रास्ता प्रतीत नहीं होता है। आपके विकल्प:

  • बाहरी पुस्तकालय का प्रयोग करें।
  • इस कोड को अपनी सभी परियोजनाओं में कॉपी करें।
  • अपनी खुद की मिनी लाइब्रेरी बनाएं जिसमें आपके द्वारा अक्सर उपयोग किए जाने वाले फ़ंक्शंस शामिल हों।

आपकी सबसे अच्छी शर्त शायद दूसरा है, क्योंकि इसकी कम से कम निर्भरताएं हैं।


फ़ाइल को बाइनरी के रूप में पढ़ने और अंत में रूपांतरित करने के लिए

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

यदि आप ऐसे विकल्प की तलाश में हैं जिसमें किसी तृतीय-पक्ष लाइब्रेरी (जैसे कॉमन्स I / O ) शामिल नहीं है, तो आप Scanner क्लास का उपयोग कर सकते हैं:

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

यदि आपके पास फ़ाइलों तक पहुंच नहीं है, तो आप अगला कार्य करते हैं:

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

यदि यह एक टेक्स्ट फ़ाइल है तो अपाचे कॉमन्स-आईओ का उपयोग क्यों न करें?

इसमें निम्नलिखित विधि है

public static String readFileToString(File file) throws IOException

यदि आप लाइनों को सूची के उपयोग के रूप में चाहते हैं

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

यह RandomAccessFile.readFully विधि का उपयोग करता है, ऐसा लगता है कि यह RandomAccessFile.readFully 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
        }
    }
}

वह कोड लाइन ब्रेक को सामान्यीकृत करेगा, जो आप वास्तव में करना चाहते हैं या नहीं भी हो सकता है।

यहां एक विकल्प है जो ऐसा नहीं करता है, और जो (आईएमओ) एनआईओ कोड की तुलना में समझने में आसान है (हालांकि यह अभी भी 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();
    }        
}

स्कैनर के बाद 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 में चीजें होनी चाहिए जो नौकरी को बेहतर तरीके से करनी चाहिए।

मेरा सुझाव है कि सभी बाइट्स को पकड़ने के लिए Files#readAllBytes(Path) का उपयोग करें और इसे स्ट्रिंग से बाहर निकालने के लिए इसे नए स्ट्रिंग (बाइट [] Files#readAllBytes(Path) पर फ़ीड करें। आपके जीवनकाल के दौरान चार्सेट्स का मतलब आपके लिए होगा, इसलिए अब इस सामान से सावधान रहें।

दूसरों ने कोड और सामान दिया है, और मैं उनकी महिमा चोरी नहीं करना चाहता हूं। ;)


Guava पास कॉमन्स IOUtils की तरह एक विधि है जो विली औस रोहर ने उल्लेख किया था:

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

// ...

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

ऑस्कर रेयस द्वारा संपादित करें

उद्धृत पुस्तकालय पर यह (सरलीकृत) अंतर्निहित कोड है:

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

संपादित करें (जोनिक द्वारा): उपर्युक्त हालिया गुवा संस्करणों के स्रोत कोड से मेल नहीं खाता है। वर्तमान स्रोत के लिए, com.google.common.io पैकेज में कक्षाएं Files , CharStreams , ByteSource और CharSource


इस पुस्तकालय का उपयोग करके, यह एक पंक्ति है:

String data = IO.from(new File("data.txt")).toString();

fileInputStream.available() का उपयोग करते समय जागरूक रहें fileInputStream.available() लौटा पूर्णांक को वास्तविक फ़ाइल आकार का प्रतिनिधित्व नहीं करना पड़ता है, बल्कि बाइट्स की 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();
}

यह माना जाना चाहिए कि यह दृष्टिकोण यूटीएफ -8 जैसे बहु-बाइट वर्ण एन्कोडिंग के लिए उपयुक्त नहीं है


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

जावा 7 के बाद से आप इसे इस तरह से कर सकते हैं।


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

public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    try {
        BufferedReader reader = new BufferedReader(new FileReader(file));

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






io