স্ট্রিং লাইন লাইনে পড়ুন


144

একটি স্ট্রিং দেওয়া হয়েছে যা খুব বেশি দীর্ঘ নয়, এটি রেখার দ্বারা লাইন পড়ার সর্বোত্তম উপায় কী?

আমি জানি আপনি করতে পারেন:

BufferedReader reader = new BufferedReader(new StringReader(<string>));
reader.readLine();

অন্য উপায় হ'ল ইওলটিতে সাবস্ট্রিং নেওয়া:

final String eol = System.getProperty("line.separator");
output = output.substring(output.indexOf(eol + 1));

এটি করার সহজ উপায়গুলি অন্য কোনও? উপরোক্ত পদ্ধতির সাথে আমার কোনও সমস্যা নেই, কেবলমাত্র আপনার মধ্যে এমন কেউ যদি এমন কিছু জানেন যা সহজ এবং আরও দক্ষ দেখায় তা জানতে আগ্রহী?


5
ঠিক আছে আপনার প্রয়োজনীয়তাটি "এটি রেখার সাথে রেখায় পড়ুন" বলেছে, যা বোঝায় যে আপনার একসাথে সমস্ত স্মৃতি রেখার দরকার নেই, তাই আমি বাফারড্রেডার বা স্ক্যানার পদ্ধতির সাথে আঁকড়ে থাকব, যার সাথে আপনি আরও স্বাচ্ছন্দ্য বোধ করেন (জানেন না) যা আরও দক্ষ)। এইভাবে আপনার স্মৃতির প্রয়োজনীয়তা কম। এটি আপনাকে ভবিষ্যতে কোনও ফাইল থেকে ডেটা সম্ভাব্যভাবে পড়ার মাধ্যমে অ্যাপ্লিকেশনটিকে আরও বড় স্ট্রিং ব্যবহার করতে "স্কেল আপ" করতে দেয় allow
ক্যামিকার

উত্তর:


133

আপনি splitস্ট্রিংয়ের পদ্ধতিটিও ব্যবহার করতে পারেন :

String[] lines = myString.split(System.getProperty("line.separator"));

এটি আপনাকে একটি সহজ অ্যারেতে সমস্ত লাইন দেয়।

আমি বিভাজনের পারফরম্যান্স সম্পর্কে জানি না। এটি নিয়মিত এক্সপ্রেশন ব্যবহার করে।


3
এবং আশা করি লাইন বিভাজকটির এতে রেজেক্স অক্ষর নেই। :)
টম হাটিন - 9

47
"line.separator" যাইহোক নির্ভরযোগ্য নয়। কোডটি (উদাহরণস্বরূপ) ইউনিক্সে চলমান থাকায়, উইন্ডোজ-স্টাইলের "\ r \ n" লাইন বিভাজক হওয়া থেকে ফাইলটি থামানো কী? বাফারড্রেডার.ড্রেডলাইন () এবং স্ক্যানার.নেক্সটলাইন () সর্বদা বিভাজকের তিনটি শৈলীর জন্য পরীক্ষা করে দেখুন।
অ্যালান মুর

6
আমি জানি এই মন্তব্যটি সত্যই পুরানো, কিন্তু ... প্রশ্নটিতে ফাইলগুলির মোটেও উল্লেখ করা হয়নি। ধরে নেওয়া যে স্ট্রিংটি কোনও ফাইল থেকে পড়া হয়নি, সম্ভবত এই পদ্ধতিটি নিরাপদ।
জোলাটা

@ জোলতা এটি নিজে নিজে তৈরি স্ট্রিংয়ের জন্যও নিরাপদ নয়, যদি আপনি উইন্ডোতে থাকেন এবং আপনার স্ট্রিংটি '' n 'দিয়ে তৈরি করেন এবং তারপরে লাইন.সেটেপরে বিভক্ত হন তবে আপনার কোনও লাইন নেই।
মাস্টারেক্সিলো

তাই না? আমি যদি আমার লিনাক্স বাক্সটি ব্যবহার করে একটি স্ট্রিং তৈরি করি line.separatorএবং অন্য কেউ উইন্ডো ব্যবহার করে এটি পড়েন line.separator, তবে এটি আবদ্ধ। এটি মূ .় কাজ করা থেকে অক্ষম কোডার নয়, জিনিসগুলি (সর্বদা না) ঠিক কীভাবে কাজ করে তা।
ল্যারি

205

এছাড়াও আছে Scanner। আপনি এটির মতো ব্যবহার করতে পারেন BufferedReader:

Scanner scanner = new Scanner(myString);
while (scanner.hasNextLine()) {
  String line = scanner.nextLine();
  // process the line
}
scanner.close();

আমি মনে করি এটি প্রস্তাবিত উভয়ই কিছুটা পরিষ্কার পরিচ্ছন্নতা।


5
যদিও আমি মনে করি না এটি একটি উপযুক্ত তুলনা - স্ট্রিং.স্প্লিট মেমরির মধ্যে পড়ার পুরো ইনপুটটির উপর নির্ভর করে যা সর্বদা সম্ভব হয় না (যেমন বড় ফাইলগুলির জন্য)।
অ্যাডামসকি

3
ইনপুটটি মেমরিতে থাকতে হবে, প্রদত্ত ইনপুটটি স্ট্রিং। মেমরি ওভারহেড অ্যারে হয়। এছাড়াও, ফলস্বরূপ স্ট্রিংগুলি একই ব্যাক-এন্ড অক্ষরের অ্যারে পুনরায় ব্যবহার করে।
ননোপ করুন

আপনি যদি ইউনিকোড অক্ষর দিয়ে কোনও ইউটিএফ -8 ফাইল স্ক্যান করেন এবং স্ক্যানারটিতে এনকোডিং নির্দিষ্ট না করেন তবে সাবধান থাকুন স্ক্যানার ভুল ফলাফল তৈরি করতে পারে t এটি লাইনের শেষ হিসাবে আলাদা চরিত্রের ব্যাখ্যা করতে পারে। উইন্ডোজ এটির ডিফল্ট এনকোডিং ব্যবহার করে।
লাইভ-লাভ

43

যেহেতু আমি দক্ষতার কোণে বিশেষভাবে আগ্রহী ছিলাম, তাই আমি একটি সামান্য পরীক্ষার শ্রেণী তৈরি করেছি (নীচে)। 5,000,000 লাইনের ফলাফল:

Comparing line breaking performance of different solutions
Testing 5000000 lines
Split (all): 14665 ms
Split (CR only): 3752 ms
Scanner: 10005
Reader: 2060

যথারীতি যথাযথ সময়গুলি পরিবর্তিত হতে পারে তবে অনুপাতটি সত্য থাকে তবে প্রায়শই আমি এটি চালিয়েছি।

উপসংহার: ওপি'র "সরল" এবং "আরও দক্ষ" প্রয়োজনীয়তাগুলি একই সাথে সন্তুষ্ট হতে পারে না, splitসমাধান (উভয় অবতারে) সহজ, তবে Readerবাস্তবায়ন অন্যদের হাতছাড়া করে।

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * Test class for splitting a string into lines at linebreaks
 */
public class LineBreakTest {
    /** Main method: pass in desired line count as first parameter (default = 10000). */
    public static void main(String[] args) {
        int lineCount = args.length == 0 ? 10000 : Integer.parseInt(args[0]);
        System.out.println("Comparing line breaking performance of different solutions");
        System.out.printf("Testing %d lines%n", lineCount);
        String text = createText(lineCount);
        testSplitAllPlatforms(text);
        testSplitWindowsOnly(text);
        testScanner(text);
        testReader(text);
    }

    private static void testSplitAllPlatforms(String text) {
        long start = System.currentTimeMillis();
        text.split("\n\r|\r");
        System.out.printf("Split (regexp): %d%n", System.currentTimeMillis() - start);
    }

    private static void testSplitWindowsOnly(String text) {
        long start = System.currentTimeMillis();
        text.split("\n");
        System.out.printf("Split (CR only): %d%n", System.currentTimeMillis() - start);
    }

    private static void testScanner(String text) {
        long start = System.currentTimeMillis();
        List<String> result = new ArrayList<>();
        try (Scanner scanner = new Scanner(text)) {
            while (scanner.hasNextLine()) {
                result.add(scanner.nextLine());
            }
        }
        System.out.printf("Scanner: %d%n", System.currentTimeMillis() - start);
    }

    private static void testReader(String text) {
        long start = System.currentTimeMillis();
        List<String> result = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new StringReader(text))) {
            String line = reader.readLine();
            while (line != null) {
                result.add(line);
                line = reader.readLine();
            }
        } catch (IOException exc) {
            // quit
        }
        System.out.printf("Reader: %d%n", System.currentTimeMillis() - start);
    }

    private static String createText(int lineCount) {
        StringBuilder result = new StringBuilder();
        StringBuilder lineBuilder = new StringBuilder();
        for (int i = 0; i < 20; i++) {
            lineBuilder.append("word ");
        }
        String line = lineBuilder.toString();
        for (int i = 0; i < lineCount; i++) {
            result.append(line);
            result.append("\n");
        }
        return result.toString();
    }
}

4
জাভা 8-এর হিসাবে, বাফারড্রেডারের একটি লাইনের lines()ফাংশন রয়েছে Stream<String>যা আপনি চাইলে একটি তালিকাতে সংগ্রহ করতে পারেন বা প্রবাহটি প্রক্রিয়াজাত করতে পারেন।
স্টিভ কে

22

অ্যাপাচি কমন্স আইইউটিস ব্যবহার করে আপনি এটি মাধ্যমে সুন্দরভাবে এটি করতে পারেন

List<String> lines = IOUtils.readLines(new StringReader(string));

এটি চালাক কিছু করছে না, তবে এটি দুর্দান্ত এবং কমপ্যাক্ট। এটি পাশাপাশি স্ট্রিমগুলি পরিচালনা করবে এবং আপনি LineIteratorযদি পছন্দ করেন তবে আপনি এটি পেতেও পারেন।


2
এই পদ্ধতির এক অপূর্ণতা যে IOUtils.readlines(Reader)একটি ছোঁড়ার IOException। যদিও এটি সম্ভবত স্ট্রিংরেডার দিয়ে কখনই ঘটবে না, আপনাকে এটি ধরতে বা ঘোষণা করতে হবে।
স্লেসকে

একটি সামান্য টাইপও রয়েছে, এটি হওয়া উচিত: তালিকা লাইন = আইউইটিস.ড্রেডলাইনস (নতুন স্ট্রিংরেডার (স্ট্রিং));
tommy chheng

17

Java 8যেমন Stream APIএবং এর মতো বৈশিষ্ট্যগুলি ব্যবহার করে সমাধান করুনMethod references

new BufferedReader(new StringReader(myString))
        .lines().forEach(System.out::println);

অথবা

public void someMethod(String myLongString) {

    new BufferedReader(new StringReader(myLongString))
            .lines().forEach(this::parseString);
}

private void parseString(String data) {
    //do something
}

11

জাভা ১১-এর পর থেকে একটি নতুন পদ্ধতি রয়েছে String.lines:

/**
 * Returns a stream of lines extracted from this string,
 * separated by line terminators.
 * ...
 */
public Stream<String> lines() { ... }

ব্যবহার:

"line1\nline2\nlines3"
    .lines()
    .forEach(System.out::println);

7

আপনি স্ট্রিম এপিআই এবং স্ট্রিংরেডারকে একটি বাফার্ডারিডারে মোড়ানো ব্যবহার করতে পারেন যা জাভা 8 এ একটি লাইন () স্ট্রিম আউটপুট পেয়েছে:

import java.util.stream.*;
import java.io.*;
class test {
    public static void main(String... a) {
        String s = "this is a \nmultiline\rstring\r\nusing different newline styles";

        new BufferedReader(new StringReader(s)).lines().forEach(
            (line) -> System.out.println("one line of the string: " + line)
        );
    }
}

দেয়

one line of the string: this is a
one line of the string: multiline
one line of the string: string
one line of the string: using different newline styles

ঠিক বাফার্ডরিডারের রিডলাইনের মতোই, নতুন লাইনের চরিত্রগুলি নিজেরাই অন্তর্ভুক্ত করা হয় না। সকল ধরণের নিউলাইন বিভাজক সমর্থিত (একই স্ট্রিংয়ের মধ্যেও)।


তাও জানতেন না! অনেক ধন্যবাদ .
GOXR3PLUS

6

আপনি এটি ব্যবহার করতে পারেন:

String[] lines = someString.split("\n");

যে যদি না হয় কাজ করে দেখুন প্রতিস্থাপন \nসঙ্গে \r\n


3
নতুন লাইনের উপস্থাপনা হার্ডকোডিং সমাধান প্ল্যাটফর্ম-নির্ভর করে তোলে।
thSoft

@ সোফট আমি এটি যুক্তি দিয়ে বলব যে এটি হার্ডোডিং না করার বিষয়ে বলা যেতে পারে - আপনি যদি এটি হার্ডকোড না করেন তবে একই ইনপুটটির জন্য আপনি বিভিন্ন প্ল্যাটফর্মে বিভিন্ন ফলাফল পাবেন (যেমন প্ল্যাটফর্ম নির্ভর নির্ভর লাইন বিচ্ছেদের পরিবর্তে ঠিক একই লাইন ব্রেক সহ) ইনপুট)। এটি সত্যিই হ্যাঁ / না নয় এবং আপনার ইনপুটটি কী হবে সে সম্পর্কে আপনাকে ভাবতে হবে।
জিরি তোসেক

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

5

বা স্ক্যানারের সাথে মিলিত সংস্থানসমূহের নতুন প্রচেষ্টা ব্যবহার করুন:

   try (Scanner scanner = new Scanner(value)) {
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            // process the line
        }
    }

2

আপনি নিম্নলিখিত নিয়মিত এক্সপ্রেশন চেষ্টা করতে পারেন:

\r?\n

কোড:

String input = "\nab\n\n    \n\ncd\nef\n\n\n\n\n";
String[] lines = input.split("\\r?\\n", -1);
int n = 1;
for(String line : lines) {
    System.out.printf("\tLine %02d \"%s\"%n", n++, line);
}

আউটপুট:

Line 01 ""
Line 02 "ab"
Line 03 ""
Line 04 "    "
Line 05 ""
Line 06 "cd"
Line 07 "ef"
Line 08 ""
Line 09 ""
Line 10 ""
Line 11 ""
Line 12 ""

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.