जावा में एक फ़ाइल से विशिष्ट लाइन नंबर का उपयोग करके एक विशिष्ट लाइन कैसे पढ़ें?


90

जावा में, क्या किसी फ़ाइल से किसी विशेष लाइन को पढ़ने की कोई विधि है? उदाहरण के लिए, पंक्ति 32 या कोई अन्य पंक्ति संख्या पढ़ें।


5
मुझे पता है कि मुझे बहुत देर हो चुकी है, लेकिन अगर किसी को यह सवाल मिला: ध्यान दें कि एक फ़ाइल सिर्फ बाइट्स का एक क्रम है। और एक नई लाइन सिर्फ एक चरित्र (विंडोज पर दो) है, और एक चरित्र सिर्फ एक (या अधिक, एन्कोडिंग पर निर्भर करता है) बाइट है। और, किसी फाइल में बाइट के पदों का सूचकांक न होने पर, यह जानने का एकमात्र तरीका है कि वे बाइट्स कहां हैं, इसे पढ़ें और इसे देखें। (इसका मतलब यह नहीं है कि आपको पूरी फ़ाइल को मेमोरी में लोड करना है)।
szgal

जवाबों:


71

जब तक आपको फ़ाइल में लाइनों के बारे में पहले से जानकारी नहीं है, तब तक 31 पिछली पंक्तियों को पढ़े बिना सीधे 32 वीं पंक्ति तक पहुँचने का कोई तरीका नहीं है।

यह सभी भाषाओं और सभी आधुनिक फ़ाइल सिस्टम के लिए सही है।

इतनी प्रभावी ढंग से आप बस लाइनों को पढ़ेंगे जब तक आप 32 वें एक को नहीं पा लेते हैं।


4
"पिछले ज्ञान" फ़ाइल में सटीक लाइन आकार पैटर्न के रूप में सरल हो सकता है ताकि आप एक निश्चित स्थिति की तलाश कर सकें।
मुरली वीपी

2
@ मुरली: बिल्कुल। यह बाइट ऑफसेट या इसके किसी भी संयोजन के लिए लाइन नंबर का एक सूचकांक भी हो सकता है।
जोकिम सॉयर

102

छोटी फ़ाइलों के लिए:

String line32 = Files.readAllLines(Paths.get("file.txt")).get(32)

बड़ी फ़ाइलों के लिए:

try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    line32 = lines.skip(31).findFirst().get();
}

यह java.nio.charset.alformedInputException देता है: इनपुट लंबाई = 1 जब स्किप वैल्यू के साथ प्रयोग किया जाता है 1
canadiancreed

यह मेरे द्वारा पोस्ट किए गए कोड के साथ कोई समस्या नहीं है, यह आपकी फ़ाइल के एन्कोडिंग के साथ एक समस्या है। इस पोस्ट को देखें ।
एरियोब

3
"ध्यान दें कि यह विधि साधारण मामलों के लिए है जहाँ एक ही ऑपरेशन में सभी लाइनों को पढ़ना सुविधाजनक है। यह बड़ी फ़ाइलों के लिए अभिप्रेत नहीं है।" - Files.readAllLines () का जावाडोक
PragmaticProgrammer

निम्न कोड को Android में API स्तर 26 की आवश्यकता है। यदि हमारा न्यूनतम स्तर कम है तो यह स्तर काम नहीं करता है
अली अज़ाज़ आलम

38

ऐसा नहीं है कि मुझे पता है, लेकिन आप क्या कर सकते हैं पहली 31 लाइनों के माध्यम से लूप है जो बफ़र बिल्डर की रीडलाइन () फ़ंक्शन का उपयोग करके कुछ नहीं कर रहा है

FileInputStream fs= new FileInputStream("someFile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fs));
for(int i = 0; i < 31; ++i)
  br.readLine();
String lineIWant = br.readLine();

1
कृपया ध्यान दें कि यहाँ आप पंक्ति संख्या ३० को पढ़ते हैं, जो ३१ वीं पंक्ति है क्योंकि हम ०. read से पंक्ति संख्याएँ शुरू करते हैं। इसलिए मैं इस प्रश्न का सटीक मिलान करने के लिए इसे बदलने का सुझाव दूंगा।
कीडायस्कॉट्स

15

निश्चित रूप से जोआचिम सही है, और क्रिस के लिए एक वैकल्पिक कार्यान्वयन '(केवल छोटी फ़ाइलों के लिए क्योंकि यह पूरी फ़ाइल को लोड करता है) अपाचे से कॉमन्स-आईओ का उपयोग करने के लिए हो सकता है (हालांकि यकीनन आप एक नई निर्भरता का परिचय नहीं देना चाह सकते हैं) यदि आप इसे अन्य सामानों के लिए भी उपयोगी पाते हैं, तो यह समझ में आता है)।

उदाहरण के लिए:

String line32 = (String) FileUtils.readLines(file).get(31);

http://commons.apache.org/io/api-release/org/apache/commons/io/FileUtils.html#readLines(java.io.File , java.lang.String)


2
हालाँकि यह पूरी फ़ाइल को 32 वीं पंक्ति में जाने से पहले मेमोरी में लोड कर देगा, जो कि एक बड़ी फ़ाइल के साथ व्यावहारिक नहीं हो सकता है और यह 32 वीं लाइन खोजने के उपयोग को पढ़ने की तुलना में धीमा होगा ...
ben2323

उचित बिंदु, हाँ। मैंने इसका उपयोग परीक्षण के मामलों में किया है, जहां परीक्षण फाइलें छोटी थीं, हालांकि बड़ी फ़ाइलों पर, सहमत, अच्छा दृष्टिकोण नहीं।
चार्ली कॉलिन्स

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

11

आप अनुक्रमित-फ़ाइल-रीडर (अपाचे लाइसेंस 2.0) की कोशिश कर सकते हैं । IndexedFileReader में एक विधि है जिसे रीडलाइन (int, int से) कहा जाता है जो एक SortedMap देता है जिसकी कुंजी लाइन संख्या होती है और मान वह रेखा होती है जो पढ़ी जाती है।

उदाहरण:

File file = new File("src/test/resources/file.txt");
reader = new IndexedFileReader(file);

lines = reader.readLines(6, 10);
assertNotNull("Null result.", lines);
assertEquals("Incorrect length.", 5, lines.size());
assertTrue("Incorrect value.", lines.get(6).startsWith("[6]"));
assertTrue("Incorrect value.", lines.get(7).startsWith("[7]"));
assertTrue("Incorrect value.", lines.get(8).startsWith("[8]"));
assertTrue("Incorrect value.", lines.get(9).startsWith("[9]"));
assertTrue("Incorrect value.", lines.get(10).startsWith("[10]"));      

उपरोक्त उदाहरण में निम्नलिखित प्रारूप में 50 लाइनों से बना एक पाठ फ़ाइल है:

[1] The quick brown fox jumped over the lazy dog ODD
[2] The quick brown fox jumped over the lazy dog EVEN

डिस्क्लेमर: मैंने यह लाइब्रेरी लिखी है


6

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

The offsets can be calculated by using the RandomAccessFile

    RandomAccessFile raf = new RandomAccessFile("myFile.txt","r"); 
    //above 'r' means open in read only mode
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    String cur_line = "";
    while((cur_line=raf.readLine())!=null)
    {
    arrayList.add(raf.getFilePointer());
    }
    //Print the 32 line
    //Seeks the file to the particular location from where our '32' line starts
    raf.seek(raf.seek(arrayList.get(31));
    System.out.println(raf.readLine());
    raf.close();

अधिक जानकारी के लिए जावा डॉक्स पर भी जाएं: https://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html#mode

जटिलता : यह O (n) है क्योंकि यह पूरी फाइल को एक बार पढ़ता है। कृपया स्मृति आवश्यकताओं के लिए जागरूक रहें। यदि यह मेमोरी में होना बहुत बड़ा है, तो एक अस्थायी फ़ाइल बनाएं जो कि ऊपर दिखाए गए अनुसार ArrayList के बजाय ऑफ़सेट को संग्रहीत करता है।

नोट : यदि आप सभी '32 ’लाइन में चाहते हैं, तो आपको सिर्फ रीडलाइन () भी उपलब्ध है जो अन्य वर्गों के माध्यम से। 32’ बार उपलब्ध है। यदि आप एक विशिष्ट लाइन (निश्चित रूप से लाइन की संख्या के आधार पर) प्राप्त करना चाहते हैं तो उपरोक्त दृष्टिकोण उपयोगी है।

धन्यवाद !


उपरोक्त कोड कार्य करने के लिए कुछ संपादन की आवश्यकता है। और अगर किसी को चिंतित होने की आवश्यकता है, तो यू वास्तव में इसे पढ़ना चाहिए: stackoverflow.com/a/37275357/3198960
rufushuang

5

दूसरा रास्ता।

try (BufferedReader reader = Files.newBufferedReader(
        Paths.get("file.txt"), StandardCharsets.UTF_8)) {
    List<String> line = reader.lines()
                              .skip(31)
                              .limit(1)
                              .collect(Collectors.toList());

    line.stream().forEach(System.out::println);
}

1
सुरुचिपूर्ण, मुझे यह पसंद है।
फ्लोरसेक्यू कैटेलिन

4

नहीं, जब तक कि फ़ाइल प्रारूप में लाइन की लंबाई पूर्व-निर्धारित न हो (उदाहरण के लिए सभी लाइनें एक निश्चित लंबाई के साथ), आपको उन्हें गिनने के लिए लाइन द्वारा लाइन को पुनरावृत्त करना होगा।


2

यदि आप एक पाठ फ़ाइल के बारे में बात कर रहे हैं, तो वास्तव में ऐसा करने का कोई तरीका नहीं है कि इसे पढ़े जाने वाली सभी पंक्तियों के बिना - आखिरकार, लाइनों को एक नई रेखा की उपस्थिति से निर्धारित किया जाता है, इसलिए इसे पढ़ना होगा।

एक स्ट्रीम का उपयोग करें जो रीडलाइन का समर्थन करता है, और बस पहले एक्स -1 लाइनों को पढ़ें और परिणाम डंप करें, फिर अगले एक को संसाधित करें।


2

जावा 8 में,

छोटी फ़ाइलों के लिए:

String line = Files.readAllLines(Paths.get("file.txt")).get(n);

बड़ी फ़ाइलों के लिए:

String line;
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    line = lines.skip(n).findFirst().get();
}

जावा 7 में

String line;
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    for (int i = 0; i < n; i++)
        br.readLine();
    line = br.readLine();
}

स्रोत: फाइल से एनटी लाइन पढ़ना


1
public String readLine(int line){
        FileReader tempFileReader = null;
        BufferedReader tempBufferedReader = null;
        try { tempFileReader = new FileReader(textFile); 
        tempBufferedReader = new BufferedReader(tempFileReader);
        } catch (Exception e) { }
        String returnStr = "ERROR";
        for(int i = 0; i < line - 1; i++){
            try { tempBufferedReader.readLine(); } catch (Exception e) { }
        }
        try { returnStr = tempBufferedReader.readLine(); }  catch (Exception e) { }

        return returnStr;
    }

1

यह मेरे लिए काम करता है: मैंने एक साधारण पाठ फ़ाइल पढ़ने के उत्तर को संयुक्त किया है

लेकिन एक स्ट्रिंग के बदले मैं एक लिंकडलिस्ट ऑफ स्ट्रिंग्स वापस कर रहा हूं। फिर मैं उस लाइन का चयन कर सकता हूं जो मुझे चाहिए।

public static LinkedList<String> readFromAssets(Context context, String filename) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(context.getAssets().open(filename)));
    LinkedList<String>linkedList = new LinkedList<>();
    // do reading, usually loop until end of file reading
    StringBuilder sb = new StringBuilder();
    String mLine = reader.readLine();
    while (mLine != null) {
        linkedList.add(mLine);
        sb.append(mLine); // process line
        mLine = reader.readLine();


    }
    reader.close();
    return linkedList;
}

इसके बाद आप कर सकते हैं: linkedlist.get (31)
Tachenko

1

इस कोड का उपयोग करें:

import java.nio.file.Files;

import java.nio.file.Paths;

public class FileWork 
{

    public static void main(String[] args) throws IOException {

        String line = Files.readAllLines(Paths.get("D:/abc.txt")).get(1);

        System.out.println(line);  
    }

}

0

आप बफ़ररएडर के बजाय लाइननंबर राइडर का उपयोग कर सकते हैं। आपी के माध्यम से जाओ। आप setLineNumber और getLineNumber विधियाँ पा सकते हैं।


मदद नहीं करता है - आप अभी भी पहले सभी लाइनों को पढ़ने के लिए है ... को छोड़कर आप धोखा देते हैं और पहली पंक्ति को 32 <g> पर सेट करें
kleopatra

0

तुम भी LineNumberReader, BufferedReader के उपवर्ग पर एक नज़र डाल सकते हैं। रीडलाइन पद्धति के साथ, इसमें लाइन नंबर तक पहुंचने के लिए सेटर / गेट्टर विधियां भी हैं। फ़ाइल से डेटा पढ़ते समय, पढ़ी गई लाइनों की संख्या पर नज़र रखने के लिए बहुत उपयोगी है।


0

आप स्किपिंग से लाइनों को स्किप करने के लिए स्किप () फ़ंक्शन का उपयोग कर सकते हैं।

public static void readFile(String filePath, long lineNum) {
    List<String> list = new ArrayList<>();
    long totalLines, startLine = 0;

    try (Stream<String> lines = Files.lines(Paths.get(filePath))) {
        totalLines = Files.lines(Paths.get(filePath)).count();
        startLine = totalLines - lineNum;
        // Stream<String> line32 = lines.skip(((startLine)+1));

        list = lines.skip(startLine).collect(Collectors.toList());
        // lines.forEach(list::add);
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    list.forEach(System.out::println);

}

-7

वे सभी गलत हैं मैंने इसे लगभग 10 सेकंड में लिखा था। इसके साथ मैं जो भी लाइन मैं चाहता हूं उसे वापस लाने के लिए मुख्य विधि में ऑब्जेक्ट .getQuestion ("लिनेनंबर") को कॉल करने में कामयाब रहा।

public class Questions {

File file = new File("Question2Files/triviagame1.txt");

public Questions() {

}

public String getQuestion(int numLine) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(file));
    String line = "";
    for(int i = 0; i < numLine; i++) {
        line = br.readLine();
    }
    return line; }}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.