জাভাতে কোনও ফাইলে লাইনের সংখ্যা


213

আমি বিশাল ডেটা ফাইলগুলি ব্যবহার করি, কখনও কখনও আমাকে কেবল এই ফাইলগুলির লাইনগুলির সংখ্যা জানতে হবে, সাধারণত আমি এগুলি খুলি এবং লাইনের পরে লাইনে পড়ি যতক্ষণ না আমি ফাইলটির শেষে পৌঁছায় না

আমি ভাবছিলাম যে এটি করার জন্য আরও চতুর উপায় আছে কিনা

উত্তর:


237

এটি আমি এখন পর্যন্ত সবচেয়ে দ্রুততম সংস্করণ পেয়েছি, রিডলাইনগুলির চেয়ে প্রায় 6 গুণ বেশি দ্রুত। 150 এমবি লগ ফাইলে এটি 0.35 সেকেন্ড সময় নেয়, রিডলাইনস () ব্যবহার করার সময় 2.40 সেকেন্ডের তুলনায়। কেবল মজাদার জন্য, লিনাক্স ডাব্লুসি-ল কমান্ডটি 0.15 সেকেন্ড সময় নেয়।

public static int countLinesOld(String filename) throws IOException {
    InputStream is = new BufferedInputStream(new FileInputStream(filename));
    try {
        byte[] c = new byte[1024];
        int count = 0;
        int readChars = 0;
        boolean empty = true;
        while ((readChars = is.read(c)) != -1) {
            empty = false;
            for (int i = 0; i < readChars; ++i) {
                if (c[i] == '\n') {
                    ++count;
                }
            }
        }
        return (count == 0 && !empty) ? 1 : count;
    } finally {
        is.close();
    }
}

সম্পাদনা, 9 1/2 বছর পরে: আমার কাছে জাভা অভিজ্ঞতা নেই, তবে যাইহোক আমি LineNumberReaderনীচের সমাধানের বিরুদ্ধে এই কোডটি বেঞ্চমার্ক করার চেষ্টা করেছি যেহেতু এটি আমাকে বিরক্ত করে যে কেউ তা করেনি। দেখে মনে হচ্ছে বিশেষত বড় ফাইলগুলির জন্য আমার সমাধানটি দ্রুত। অপ্টিমাইজার একটি শালীন কাজ না করা পর্যন্ত এটি কয়েক রান নেবে বলে মনে হচ্ছে। আমি কোডটি নিয়ে কিছুটা খেলেছি এবং একটি নতুন সংস্করণ তৈরি করেছি যা ধারাবাহিকভাবে দ্রুততম:

public static int countLinesNew(String filename) throws IOException {
    InputStream is = new BufferedInputStream(new FileInputStream(filename));
    try {
        byte[] c = new byte[1024];

        int readChars = is.read(c);
        if (readChars == -1) {
            // bail out if nothing to read
            return 0;
        }

        // make it easy for the optimizer to tune this loop
        int count = 0;
        while (readChars == 1024) {
            for (int i=0; i<1024;) {
                if (c[i++] == '\n') {
                    ++count;
                }
            }
            readChars = is.read(c);
        }

        // count remaining characters
        while (readChars != -1) {
            System.out.println(readChars);
            for (int i=0; i<readChars; ++i) {
                if (c[i] == '\n') {
                    ++count;
                }
            }
            readChars = is.read(c);
        }

        return count == 0 ? 1 : count;
    } finally {
        is.close();
    }
}

বেনমার্কটি ১.৩ গিগাবাইট পাঠ্য ফাইলের জন্য স্থির হয়, সেকেন্ডে y অক্ষ। আমি একই ফাইল দিয়ে 100 রান করেছি এবং প্রতিটি রান মাপ করেছি System.nanoTime()। আপনি দেখতে পাচ্ছেন যে countLinesOldএর কয়েকজন বহিরাগত countLinesNewরয়েছে এবং এর কোনওটিই নেই এবং এটি কেবল একটু দ্রুত হলেও পার্থক্যটি পরিসংখ্যানগতভাবে তাৎপর্যপূর্ণ। LineNumberReaderস্পষ্টভাবে ধীর।

Benchmark Plot


5
বাফার্ড ইনপুট স্ট্রিমটি আপনার জন্য বাফারিং করা উচিত, সুতরাং আমি দেখছি না কীভাবে মধ্যবর্তী বাইট [] অ্যারে ব্যবহার করা এটি আরও দ্রুততর করে তুলবে। আপনি যেভাবেই হোক বার বার রিডলাইন () ব্যবহারের চেয়ে অনেক ভাল করার সম্ভাবনা নেই (যেহেতু এটি এপিআই দ্বারা অনুকূলিত হবে)।
wds 13

54
আপনি যখন ইনপুট স্ট্রিমটি শেষ করবেন তখন এটি বন্ধ করবেন, তাই না?
বেন্ডিন

5
যদি বাফারিং সহায়তা করে তবে এটি বাফারআইনপুট স্ট্রিমটি 8 কে ডিফল্টরূপে বাফার করে। আপনার বাইটটি [] এই আকার বা তার চেয়ে বড় বা বড় করুন এবং আপনি বাফার্ড ইনপুট স্ট্রিমটি ড্রপ করতে পারেন। যেমন 1024 * 1024 বাইট চেষ্টা করুন।
পিটার লরে

8
দুটি জিনিস: (1) জাভা উত্সে লাইন টার্মিনেটরের সংজ্ঞাটি হ'ল ক্যারেজ রিটার্ন, একটি লাইন ফিড, বা একটি লাইন ফিডের পরে ক্যারিজ রিটার্ন। লাইন টার্মিনেটর হিসাবে ব্যবহৃত সিআর এর জন্য আপনার সমাধান কাজ করবে না। মঞ্জুর, কেবলমাত্র ওএসের মধ্যে যা আমি সিআরকে ডিফল্ট লাইন টার্মিনেটর হিসাবে ব্যবহার করতে পারি তা ম্যাক ওএস এক্সের পূর্বে ম্যাক ওএস ( লাইন গণনাটি ইউটিএফ -16 এর মতো এনকোডিংয়ের ক্ষেত্রে ভুল হতে পারে।
নাথান রায়ান

2
অসাধারণ কোড ... 400 এমবি পাঠ্য ফাইলের জন্য, এটি মাত্র এক সেকেন্ড সময় নিয়েছে। অনেক ধন্যবাদ @ মার্টিনাস
ব্যবহারকারী3181500

199

আমি সমস্যার আরেকটি সমাধান বাস্তবায়ন করেছি, আমি সারিগুলি গণনায় এটি আরও দক্ষ পেয়েছি:

try
(
   FileReader       input = new FileReader("input.txt");
   LineNumberReader count = new LineNumberReader(input);
)
{
   while (count.skip(Long.MAX_VALUE) > 0)
   {
      // Loop just in case the file is > Long.MAX_VALUE or skip() decides to not read the entire file
   }

   result = count.getLineNumber() + 1;                                    // +1 because line index starts at 0
}

LineNumberReaderএর lineNumberক্ষেত্রটি একটি পূর্ণসংখ্যা ... এটি কেবল পূর্ণসংখ্যার চেয়ে বেশি সময় ধরে ফাইলের জন্য আবৃত করবে না? MAX_VALUE? কেন এখানে দীর্ঘ সময় এড়িয়ে চলা বিরক্ত করবেন?
এপিবি

1
গণিতে একটি যুক্ত করা আসলে ভুল। wc -lফাইলটিতে নিউলাইন অক্ষরের সংখ্যা গণনা করে। ফাইলের চূড়ান্ত লাইন সহ প্রতিটি লাইন একটি নতুন লাইন দিয়ে সমাপ্ত হওয়ার পরে এটি কাজ করে। খালি লাইনগুলি সহ প্রতিটি লাইনের একটি নতুন লাইন অক্ষর থাকে, সুতরাং একটি ফাইলের মধ্যে নতুন লাইন অক্ষরের সংখ্যা == লাইনের সংখ্যা। এখন, lineNumberভেরিয়েবলটি FileNumberReaderদেখা নতুন লাইনের চরগুলির সংখ্যাও উপস্থাপন করে। এটি কোনও শূন্য থেকে শুরু হয়, কোনও নতুন লাইন পাওয়া যাওয়ার আগে এবং প্রতিটি নিউলাইনের চর দেখা গেলে এটি বাড়িয়ে দেওয়া হয়। সুতরাং দয়া করে লাইন নম্বরটিতে একটি যুক্ত করবেন না।
আলেকজান্ডার টর্স্টলিং

1
@ পিবি_এমটিটি: যদিও আপনি ঠিক বলেছেন যে নিউলাইন ছাড়াই একটি লাইনযুক্ত একটি ফাইলকে 0 লাইন হিসাবে প্রতিবেদন করা হবে, এই জাতীয় wc -lফাইলটিও এইভাবে রিপোর্ট করে। আরো দেখুন stackoverflow.com/questions/729692/...
আলেকজান্ডার Torstling

@ পিবি_এমটিটি: ফাইলটি যদি কেবল একটি নতুন লাইন থাকে তবে আপনি বিপরীত সমস্যাটি পেতে পারেন। আপনার প্রস্তাবিত অ্যালগো 0 ​​ফিরে আসবে এবং wc -l1 ফিরে আসবে I আমি সিদ্ধান্তে পৌঁছেছি যে সমস্ত পদ্ধতির ত্রুটি রয়েছে এবং আমি কীভাবে এটি আচরণ করতে চাই তার উপর ভিত্তি করে একটি বাস্তবায়ন করেছি, আমার অন্য উত্তরটি এখানে দেখুন।
আলেকজান্ডার টর্সলিং

3
আমি এই প্রতিক্রিয়াটি নীচে ফেলেছি, কারণ আপনারা কেউই এর বেঞ্চমার্ক করেছেন বলে মনে হচ্ছে না
amstegraf

30

গৃহীত উত্তরের মাল্টি লাইন ফাইলগুলির জন্য এক ত্রুটি বন্ধ রয়েছে যা নতুন লাইনে শেষ হয় না। একটি নিউলাইন ছাড়াই শেষ হওয়া একটি লাইনের ফাইলটি 1 ফিরে আসবে, তবে একটি নিউলাইন ছাড়াই শেষ হওয়া দুটি লাইনের ফাইলটিও 1 ফিরে আসবে। এখানে গৃহীত সমাধানের একটি বাস্তবায়ন যা এটি ঠিক করে। শেষগুলি উইথআউট নিউলাইন চেকগুলি চূড়ান্ত পঠন ব্যতীত সমস্ত কিছুর জন্য অপ্রয়োজনীয়, তবে সামগ্রিক ফাংশনের তুলনায় তুচ্ছ সময় অনুযায়ী হওয়া উচিত।

public int count(String filename) throws IOException {
    InputStream is = new BufferedInputStream(new FileInputStream(filename));
    try {
        byte[] c = new byte[1024];
        int count = 0;
        int readChars = 0;
        boolean endsWithoutNewLine = false;
        while ((readChars = is.read(c)) != -1) {
            for (int i = 0; i < readChars; ++i) {
                if (c[i] == '\n')
                    ++count;
            }
            endsWithoutNewLine = (c[readChars - 1] != '\n');
        }
        if(endsWithoutNewLine) {
            ++count;
        } 
        return count;
    } finally {
        is.close();
    }
}

6
ভালো বল ধরা. আপনি কেবলমাত্র গৃহীত উত্তরটি সম্পাদনা করেননি এবং যদিও একটি মন্তব্যে একটি নোট তৈরি করেছেন তা নিশ্চিত নয়। বেশিরভাগ লোক এ পর্যন্ত পড়বে না।
রায়ান

@ রায়ান, 90+ টি উর্ধ্বে 4 বছরের পুরানো স্বীকৃত উত্তরটি সম্পাদনা করা ঠিক মনে হয়নি।
ডুমুলিগান

@ আফিনকেলস্টেইন, আমি অনুভব করি যে এটিই এই সাইটটিকে এত দুর্দান্ত করে তুলেছে যে আপনি শীর্ষে ভোট দেওয়া উত্তর সম্পাদনা করতে পারেন
সেবাস্তিয়ান

3
এই সমাধানটি ক্যারেজ রিটার্ন (\ r) এবং ক্যারিজ রিটার্নের পরে লাইনফিড (\ r \ n) পরিচালনা করে না
সাইমন ব্র্যান্ডহফ - সোনারসোর্স

@ সিমন ব্র্যান্ডহফ, আমি কেনা গাড়ি ফেরত অন্য লাইন হিসাবে গণ্য হবে তা নিয়ে আমি বিভ্রান্ত? "" "N" একটি ক্যারিজ রিটার্ন লাইন ফিড, সুতরাং যে "" \ r \ n "লিখেছে সে কিছু বোঝে না ... এছাড়াও সে চরের দ্বারা চর অনুসন্ধান করছে, সুতরাং আমি নিশ্চিত যে কেউ" use r ব্যবহার করছে কিনা । n "এটি এখনও" \ n "ধরবে এবং রেখাটি গণনা করবে। যেভাবেই হোক আমার কাছে মনে হয় তিনি বিষয়টি ঠিকঠাক করেছেন। যাইহোক, তাদের অনেকগুলি পরিস্থিতি যেখানে লাইন গণনা পাওয়ার পক্ষে এটি পর্যাপ্ত উপায় নয়।
nckbrz

22

সঙ্গে , আপনি স্ট্রিম ব্যবহার করতে পারেন:

try (Stream<String> lines = Files.lines(path, Charset.defaultCharset())) {
  long numOfLines = lines.count();
  ...
}

1
কোডে ত্রুটি রয়েছে। সহজ, তবে খুব ধীর ... আমার উত্তরটি নীচে (উপরে) দেখার চেষ্টা করুন।
আর্নেস্তাস গ্রুডিস

12

উপরের পদ্ধতি গণনা () সহ উত্তরটি আমাকে ফাইলের শেষের দিকে একটি নতুন লাইন না থাকলে লাইন মিসকাউন্ট দিয়েছে - এটি ফাইলের শেষ লাইনটি গণনা করতে ব্যর্থ হয়েছে।

এই পদ্ধতিটি আমার পক্ষে আরও ভাল কাজ করে:

public int countLines(String filename) throws IOException {
    LineNumberReader reader  = new LineNumberReader(new FileReader(filename));
int cnt = 0;
String lineRead = "";
while ((lineRead = reader.readLine()) != null) {}

cnt = reader.getLineNumber(); 
reader.close();
return cnt;
}

এই ক্ষেত্রে, লাইন নম্বরেরডিডার ব্যবহার করার দরকার নেই, কেবল বাফারড্রিডার ব্যবহার করুন, সেক্ষেত্রে আপনার জন্য লম্বা ডেটাটাইপ ব্যবহার করার নমনীয়তা থাকবে cnt
সৈয়দ আকিল আশিক

[তথ্য] পিএমডি ব্যর্থতা: এক্সএক্স: 19 বিধি: খালি শখ স্টেমট অগ্রাধিকার: 3 বিবৃতি দেওয়ার সময় খালি এড়িয়ে চলুন।
ছহর্ন এলিট

8

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে গ্রহণযোগ্য সমাধানটি আমার যা করা দরকার তা মেলে না। সুতরাং, আমি এটিকে বিভিন্ন লাইন টার্মিনেটরগুলি গ্রহণের জন্য (কেবল লাইন ফিডের পরিবর্তে ) স্বীকৃত করতে এবং নির্দিষ্ট বর্ণচিহ্ন এনকোডিং (আইএসও -8859- n এর পরিবর্তে ) ব্যবহার করতে সংশোধন করেছি। সমস্ত এক পদ্ধতিতে (যথাযথ হিসাবে চুল্লি):

public static long getLinesCount(String fileName, String encodingName) throws IOException {
    long linesCount = 0;
    File file = new File(fileName);
    FileInputStream fileIn = new FileInputStream(file);
    try {
        Charset encoding = Charset.forName(encodingName);
        Reader fileReader = new InputStreamReader(fileIn, encoding);
        int bufferSize = 4096;
        Reader reader = new BufferedReader(fileReader, bufferSize);
        char[] buffer = new char[bufferSize];
        int prevChar = -1;
        int readCount = reader.read(buffer);
        while (readCount != -1) {
            for (int i = 0; i < readCount; i++) {
                int nextChar = buffer[i];
                switch (nextChar) {
                    case '\r': {
                        // The current line is terminated by a carriage return or by a carriage return immediately followed by a line feed.
                        linesCount++;
                        break;
                    }
                    case '\n': {
                        if (prevChar == '\r') {
                            // The current line is terminated by a carriage return immediately followed by a line feed.
                            // The line has already been counted.
                        } else {
                            // The current line is terminated by a line feed.
                            linesCount++;
                        }
                        break;
                    }
                }
                prevChar = nextChar;
            }
            readCount = reader.read(buffer);
        }
        if (prevCh != -1) {
            switch (prevCh) {
                case '\r':
                case '\n': {
                    // The last line is terminated by a line terminator.
                    // The last line has already been counted.
                    break;
                }
                default: {
                    // The last line is terminated by end-of-file.
                    linesCount++;
                }
            }
        }
    } finally {
        fileIn.close();
    }
    return linesCount;
}

এই সমাধানটি স্বীকৃত সমাধানের সাথে গতিতে তুলনীয়, আমার পরীক্ষাগুলিতে প্রায় 4% ধীর (যদিও জাভাতে সময় পরীক্ষাগুলি কুখ্যাতভাবে বিশ্বাসযোগ্য নয়)।


8

আমি লাইন গণনার জন্য উপরের পদ্ধতিগুলি পরীক্ষা করেছি এবং আমার সিস্টেমে পরীক্ষিত হিসাবে বিভিন্ন পদ্ধতির জন্য আমার পর্যবেক্ষণগুলি এখানে রয়েছে

ফাইলের আকার: 1.6 জিবি পদ্ধতি:

  1. স্ক্যানার ব্যবহার করে : প্রায় 35s
  2. বাফারডারিডার ব্যবহার করে : প্রায় 5 এস
  3. জাভা 8 : 5 এস প্রায় ব্যবহার করে
  4. লাইননিবারেডার ব্যবহার করে : প্রায় 5 এস

তাছাড়া জাভা 8 অ্যাপ্রোচটি বেশ সহজ বলে মনে হচ্ছে:

Files.lines(Paths.get(filePath), Charset.defaultCharset()).count()
[Return type : long]

5
/**
 * Count file rows.
 *
 * @param file file
 * @return file row count
 * @throws IOException
 */
public static long getLineCount(File file) throws IOException {

    try (Stream<String> lines = Files.lines(file.toPath())) {
        return lines.count();
    }
}

জেডিকে 8_ইউ 31 তে পরীক্ষা করা হয়েছে। তবে প্রকৃতপক্ষে এই পদ্ধতির তুলনায় কর্মক্ষমতা ধীর:

/**
 * Count file rows.
 *
 * @param file file
 * @return file row count
 * @throws IOException
 */
public static long getLineCount(File file) throws IOException {

    try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(file), 1024)) {

        byte[] c = new byte[1024];
        boolean empty = true,
                lastEmpty = false;
        long count = 0;
        int read;
        while ((read = is.read(c)) != -1) {
            for (int i = 0; i < read; i++) {
                if (c[i] == '\n') {
                    count++;
                    lastEmpty = true;
                } else if (lastEmpty) {
                    lastEmpty = false;
                }
            }
            empty = false;
        }

        if (!empty) {
            if (count == 0) {
                count = 1;
            } else if (!lastEmpty) {
                count++;
            }
        }

        return count;
    }
}

পরীক্ষিত এবং খুব দ্রুত।


এটি সঠিক নয়। আপনার কোড দিয়ে কিছু পরীক্ষা-নিরীক্ষা করেছেন এবং পদ্ধতিটি সর্বদা ধীর। Stream<String> - Time consumed: 122796351 Stream<String> - Num lines: 109808 Method - Time consumed: 12838000 Method - Num lines: 1আর লাইনের সংখ্যা এমনকি ভুল অত্যন্ত
AW-মনে

আমি 32-বিট মেশিনে পরীক্ষা করেছি। সম্ভবত 64৪-বিটের উপর বিভিন্ন ফলাফল হতে পারে .. এবং আমার মনে আছে এটি 10 ​​গুণ বা তার বেশি পার্থক্য ছিল। আপনি কোথাও লাইন গণনা করতে পাঠ্য পোস্ট করতে পারেন? সুবিধার জন্য লাইন ব্রেক দেখতে আপনি নোটপ্যাড 2 ব্যবহার করতে পারেন।
আর্নেস্তাস গ্রুদিস

পার্থক্য হতে পারে।
ও-ভাবনা

আপনি যদি পারফরম্যান্সের বিষয়ে চিন্তা করেন তবে আপনি BufferedInputStreamযখন নিজের উপায়ে বাফারে পড়তে যাবেন তখন আপনার কোনও ব্যবহার করা উচিত নয় । এছাড়াও, আপনার পদ্ধতির সামান্য পারফরম্যান্স সুবিধা থাকলেও এটি নমনীয়তা হারাবে কারণ এটি একক \rলাইন টার্মিনেটরগুলি (পুরানো ম্যাকোস) সমর্থন করে না এবং প্রতিটি এনকোডিং সমর্থন করে না।
হোলার

4

স্ক্যানার ব্যবহার করে একটি সোজা-সামনের উপায়

static void lineCounter (String path) throws IOException {

        int lineCount = 0, commentsCount = 0;

        Scanner input = new Scanner(new File(path));
        while (input.hasNextLine()) {
            String data = input.nextLine();

            if (data.startsWith("//")) commentsCount++;

            lineCount++;
        }

        System.out.println("Line Count: " + lineCount + "\t Comments Count: " + commentsCount);
    }

3

আমি এই সিদ্ধান্তে wc -lপৌঁছেছি যে : নিউলাইন গণনা করার পদ্ধতিটি ঠিক আছে তবে এমন ফাইলগুলিতে অ-স্বজ্ঞাত ফলাফল দেয় যেখানে শেষ লাইনটি কোনও নতুন লাইনের সাথে শেষ হয় না।

এবং লাইননিবারেডারের উপর ভিত্তি করে @ এরআরভিকাস সমাধান তবে লাইন কাউন্টে একটি যুক্ত করার ফলে ফাইলগুলিতে যেখানে শেষ লাইনটি নতুন লাইনের সাথে শেষ হয় না সেখানে স্বজ্ঞাত ফলাফল পেয়েছে।

অতএব আমি একটি অ্যালগো তৈরি করেছি যা নিম্নলিখিত হিসাবে পরিচালনা করে:

@Test
public void empty() throws IOException {
    assertEquals(0, count(""));
}

@Test
public void singleNewline() throws IOException {
    assertEquals(1, count("\n"));
}

@Test
public void dataWithoutNewline() throws IOException {
    assertEquals(1, count("one"));
}

@Test
public void oneCompleteLine() throws IOException {
    assertEquals(1, count("one\n"));
}

@Test
public void twoCompleteLines() throws IOException {
    assertEquals(2, count("one\ntwo\n"));
}

@Test
public void twoLinesWithoutNewlineAtEnd() throws IOException {
    assertEquals(2, count("one\ntwo"));
}

@Test
public void aFewLines() throws IOException {
    assertEquals(5, count("one\ntwo\nthree\nfour\nfive\n"));
}

এবং এটি এর মতো দেখাচ্ছে:

static long countLines(InputStream is) throws IOException {
    try(LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is))) {
        char[] buf = new char[8192];
        int n, previousN = -1;
        //Read will return at least one byte, no need to buffer more
        while((n = lnr.read(buf)) != -1) {
            previousN = n;
        }
        int ln = lnr.getLineNumber();
        if (previousN == -1) {
            //No data read at all, i.e file was empty
            return 0;
        } else {
            char lastChar = buf[previousN - 1];
            if (lastChar == '\n' || lastChar == '\r') {
                //Ending with newline, deduct one
                return ln;
            }
        }
        //normal case, return line number + 1
        return ln + 1;
    }
}

আপনি যদি স্বজ্ঞাত ফলাফল চান তবে আপনি এটি ব্যবহার করতে পারেন। আপনি যদি কেবল wc -lসামঞ্জস্য চান তবে @ er.vikas সমাধানটি সহজ ব্যবহার করতে চান তবে ফলাফলটিতে একটি যুক্ত না করে এড়িয়ে যাবার চেষ্টা করুন:

try(LineNumberReader lnr = new LineNumberReader(new FileReader(new File("File1")))) {
    while(lnr.skip(Long.MAX_VALUE) > 0){};
    return lnr.getLineNumber();
}

2

জাভা কোডের মধ্যে থেকে প্রক্রিয়া শ্রেণীর ব্যবহার সম্পর্কে কীভাবে? এবং তারপর কমান্ড আউটপুট পড়া।

Process p = Runtime.getRuntime().exec("wc -l " + yourfilename);
p.waitFor();

BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
int lineCount = 0;
while ((line = b.readLine()) != null) {
    System.out.println(line);
    lineCount = Integer.parseInt(line);
}

যদিও এটি চেষ্টা করা প্রয়োজন। ফলাফল পোস্ট করবে।


1

আপনার যদি কোনও সূচক কাঠামো না থাকে তবে আপনি সম্পূর্ণ ফাইলটি পড়তে পারবেন না। তবে আপনি এটিকে লাইনে লাইনে পড়তে এড়াতে এবং সমস্ত লাইন টার্মিনেটরগুলির সাথে মিলে একটি রেজেেক্স ব্যবহার করে এটি অনুকূল করতে পারেন।


একটি ঝরঝরে ধারণা মত শোনাচ্ছে। যে কেউ এটি ব্যবহার করে দেখেছিল এবং এর জন্য একটি রেজিপ্সপ আছে?
উইলকোডেজাভাফরফুড

1
আমি সন্দেহ করি যে এটি এত ভাল ধারণা: এটি পুরো ফাইলটি একবারে পড়তে হবে (মার্টিনাস এটি এড়ায়) এবং এই জাতীয় ব্যবহারের জন্য রেগেক্সগুলি ওভারকিল (এবং ধীর) হয় (স্থির চরের সহজ অনুসন্ধান)।
ফিলিহো

@ উইল: কি সম্পর্কে / \ n /? @ ফিলিও: রেজেক্স এক্সিকিউটররা উচ্চ-সুরযুক্ত পারফরম্যান্স মেশিন। মেমরি ক্যাডিয়েট-এ-রিডিং-বাদে, আমি মনে করি না যে কোনও ম্যানুয়াল বাস্তবায়ন দ্রুততর হতে পারে।
ডেভিড স্মিট

1

এই মজার সমাধানটি আসলে খুব ভাল কাজ করে!

public static int countLines(File input) throws IOException {
    try (InputStream is = new FileInputStream(input)) {
        int count = 1;
        for (int aChar = 0; aChar != -1;aChar = is.read())
            count += aChar == '\n' ? 1 : 0;
        return count;
    }
}

0

ইউনিক্স-ভিত্তিক সিস্টেমে wcকমান্ড-লাইনে কমান্ডটি ব্যবহার করুন ।


@ আইএনএমএইচ, আপনার দ্বিতীয় পরামর্শটি কেবলমাত্র বর্তমান ডিরেক্টরিতে প্রবেশের সংখ্যা গণনা করে। কি উদ্দেশ্য ছিল না? (বা ওপি দ্বারা জিজ্ঞাসা করা হয়েছে)
আরকিটিপাল পল

@ আইএনএমএইচ: ডব্লিউসি যেভাবেই করেন (ফাইলটি পড়া, লাইন-এন্ডিংয়ের গণনা)।
ফিলিহো

@ ফিলিহো আপনাকে লাইনগুলি গণনা করতে -l সুইচ ব্যবহার করতে হবে। (আপনি না? - কিছুক্ষণ হয়ে গেল)
আইইন হোল্ডার

@ পল - আপনি অবশ্যই 100% সঠিক। আমার একমাত্র প্রতিরক্ষা হল যে আমি এটি আমার কফির আগে পোস্ট করেছি। আমি এখন একটি বোতাম হিসাবে তীক্ষ্ণ। : ডি
আইয়েন ধারক

0

ফাইলটিতে কতগুলি রেখা রয়েছে তা জানার উপায় কেবল তাদের গণনা। আপনি অবশ্যই আপনার ডাটা থেকে একটি মেট্রিক তৈরি করতে পারেন যা আপনাকে এক লাইনের গড় দৈর্ঘ্য দেয় এবং তারপরে ফাইলের আকার পেতে পারে এবং এটিকে গড় দিয়ে ভাগ করতে পারে। দৈর্ঘ্য তবে এটি সঠিক হবে না।


1
আকর্ষণীয় ডাউনওয়েট, আপনি যে কোনও কমান্ড লাইন সরঞ্জামটি ব্যবহার করছেন তা বিবেচনা না করেই কেবল তারা অভ্যন্তরীণভাবেই একই জিনিস করেন। রেখার সংখ্যা বের করার কোনও যাদু উপায় নেই, সেগুলি হাতে হাতে গুণতে হবে। অবশ্যই এটি মেটাডেটা হিসাবে সংরক্ষণ করা যেতে পারে তবে এটি সম্পূর্ণ অন্য একটি গল্প ...
এসকো

0

ইওএফ-তে কোনও নতুন লাইন ('\ n') অক্ষর না থাকা মাল্টি লাইন ফাইলগুলির জন্য সেরা অনুকূলিত কোড।

/**
 * 
 * @param filename
 * @return
 * @throws IOException
 */
public static int countLines(String filename) throws IOException {
    int count = 0;
    boolean empty = true;
    FileInputStream fis = null;
    InputStream is = null;
    try {
        fis = new FileInputStream(filename);
        is = new BufferedInputStream(fis);
        byte[] c = new byte[1024];
        int readChars = 0;
        boolean isLine = false;
        while ((readChars = is.read(c)) != -1) {
            empty = false;
            for (int i = 0; i < readChars; ++i) {
                if ( c[i] == '\n' ) {
                    isLine = false;
                    ++count;
                }else if(!isLine && c[i] != '\n' && c[i] != '\r'){   //Case to handle line count where no New Line character present at EOF
                    isLine = true;
                }
            }
        }
        if(isLine){
            ++count;
        }
    }catch(IOException e){
        e.printStackTrace();
    }finally {
        if(is != null){
            is.close();    
        }
        if(fis != null){
            fis.close();    
        }
    }
    LOG.info("count: "+count);
    return (count == 0 && !empty) ? 1 : count;
}

0

রেজেক্স সহ স্ক্যানার:

public int getLineCount() {
    Scanner fileScanner = null;
    int lineCount = 0;
    Pattern lineEndPattern = Pattern.compile("(?m)$");  
    try {
        fileScanner = new Scanner(new File(filename)).useDelimiter(lineEndPattern);
        while (fileScanner.hasNext()) {
            fileScanner.next();
            ++lineCount;
        }   
    }catch(FileNotFoundException e) {
        e.printStackTrace();
        return lineCount;
    }
    fileScanner.close();
    return lineCount;
}

এটি আটকে নেই।


-2

যদি আপনি এটি ব্যবহার

public int countLines(String filename) throws IOException {
    LineNumberReader reader  = new LineNumberReader(new FileReader(filename));
    int cnt = 0;
    String lineRead = "";
    while ((lineRead = reader.readLine()) != null) {}

    cnt = reader.getLineNumber(); 
    reader.close();
    return cnt;
}

আপনি বড় নাম্বার সারি চালাতে পারবেন না, 100 কে সারি পছন্দ করুন, কারণ রিডার থেকে ফিরে আসা .getLineNumber ইন্ট্রি। সর্বাধিক সারি প্রক্রিয়াকরণের জন্য আপনার দীর্ঘ ধরণের ডেটা প্রয়োজন ..


14
একটি intপ্রায় 2 বিলিয়ন অবধি মান রাখতে পারে। আপনি যদি 2 বিলিয়নের বেশি লাইনের সাহায্যে কোনও ফাইল লোড করছেন তবে আপনার ওভারফ্লো সমস্যা রয়েছে। এটি বলেছে, আপনি যদি দুই বিলিয়নেরও বেশি লাইনের সাথে একটি আনইনডেক্স পাঠ্য ফাইল লোড করে থাকেন তবে আপনার সম্ভবত অন্যান্য সমস্যা রয়েছে।
অ্যাডাম নরবার্গ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.