Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 逐行读取字符串_Java_String - Fatal编程技术网

Java 逐行读取字符串

Java 逐行读取字符串,java,string,Java,String,给定一个不太长的字符串,逐行读取它的最佳方式是什么 我知道你可以做到: BufferedReader reader = new BufferedReader(new StringReader(<string>)); reader.readLine(); 还有其他更简单的方法吗?我对上述方法没有问题,只是想知道你们中是否有人知道一些看起来更简单、更有效的方法?也有。您可以像使用BufferedReader一样使用它: Scanner scanner = new Scanner(myS

给定一个不太长的字符串,逐行读取它的最佳方式是什么

我知道你可以做到:

BufferedReader reader = new BufferedReader(new StringReader(<string>));
reader.readLine();
还有其他更简单的方法吗?我对上述方法没有问题,只是想知道你们中是否有人知道一些看起来更简单、更有效的方法?

也有。您可以像使用
BufferedReader
一样使用它:

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

我认为这是一种比建议的两种方法更干净的方法。

您也可以使用字符串的
拆分方法:

String[] lines = myString.split(System.getProperty("line.separator"));
这将为您提供一个方便的数组中的所有行

我不知道斯普利特的表现如何。它使用正则表达式。

使用,您可以通过

List<String> lines = IOUtils.readLines(new StringReader(string));
List lines=IOUtils.readLines(新的StringReader(string));
它没有做任何聪明的事情,但是它很好而且紧凑。它还可以处理流,如果您愿意,您也可以使用
LineIterator

您还可以使用:

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

如果这不起作用,请尝试将
\n
替换为
\r\n

因为我对效率角度特别感兴趣,所以创建了一个小测试类(如下)。5000000条生产线的结果:

Comparing line breaking performance of different solutions
Testing 5000000 lines
Split (all): 14665 ms
Split (CR only): 3752 ms
Scanner: 10005
Reader: 2060
和往常一样,确切的时间可能会有所不同,但不管我运行的频率有多高,这个比率都是正确的

结论:OP的“更简单”和“更高效”要求不能同时得到满足,
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();
    }
}
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.StringReader;
导入java.util.ArrayList;
导入java.util.List;
导入java.util.Scanner;
/**
*用于在换行符处将字符串拆分为行的测试类
*/
公共类断线测试{
/**主要方法:传入所需的行数作为第一个参数(默认值为10000)*/
公共静态void main(字符串[]args){
int lineCount=args.length==0?10000:Integer.parseInt(args[0]);
System.out.println(“比较不同解决方案的断线性能”);
System.out.printf(“测试%d行%n”,行数);
字符串文本=createText(行计数);
TestSplitAllPlatform(文本);
testSplitWindowsOnly(文本);
测试扫描仪(文本);
测试阅读器(文本);
}
私有静态void testSplitAllPlatforms(字符串文本){
长启动=System.currentTimeMillis();
text.split(“\n\r | \r”);
System.out.printf(“拆分(regexp):%d%n”,System.currentTimeMillis()-start);
}
私有静态void testSplitWindowsOnly(字符串文本){
长启动=System.currentTimeMillis();
text.split(“\n”);
System.out.printf(“拆分(仅限CR):%d%n”,System.currentTimeMillis()-start);
}
专用静态void testScanner(字符串文本){
长启动=System.currentTimeMillis();
列表结果=新建ArrayList();
尝试(扫描仪=新扫描仪(文本)){
while(scanner.hasNextLine()){
result.add(scanner.nextLine());
}
}
System.out.printf(“扫描仪:%d%n”,System.currentTimeMillis()-start);
}
私有静态void testReader(字符串文本){
长启动=System.currentTimeMillis();
列表结果=新建ArrayList();
try(BufferedReader=newbufferedreader(newstringreader(text))){
字符串行=reader.readLine();
while(行!=null){
结果。添加(行);
line=reader.readLine();
}
}捕获(IOException){
//退出
}
System.out.printf(“读卡器:%d%n”,System.currentTimeMillis()-start);
}
私有静态字符串createText(int lineCount){
StringBuilder结果=新建StringBuilder();
StringBuilder lineBuilder=新建StringBuilder();
对于(int i=0;i<20;i++){
lineBuilder.append(“word”);
}
String line=lineBuilder.toString();
对于(int i=0;i
自Java 11以来,出现了一种新方法
String.lines

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

或者将新的try with resources子句与Scanner结合使用:

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

您可以使用流api和包装在BufferedReader中的StringReader,BufferedReader在java 8中获得lines()流输出:

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


与BufferedReader的readLine一样,换行符本身也不包括在内。支持所有类型的换行符分隔符(甚至在同一个字符串中)。

解决方案使用
Java8
功能,如
流API
方法引用

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


可以尝试以下正则表达式:

\r?\n
代码:

输出:


最简单和最通用的方法是只使用正则表达式
换行符匹配器
\R
,它匹配
任何Unicode换行符序列

Pattern NEWLINE = Pattern.compile("\\R")
String lines[] = NEWLINE.split(input)

@请参见

尽管如此,我认为这不是一个公平的比较-String.split依赖于将整个输入读入内存,这并不总是可行的(例如,对于大文件)。输入必须驻留在内存中,因为输入是字符串。内存开销由数组决定。此外,生成的字符串重复使用相同的后端字符数组。如果使用Unicode字符扫描UTF-8文件,并且未在扫描程序中指定编码,则扫描程序可能会产生错误的结果。它可能会将不同的字符解释为行尾。在Windows中,它使用默认编码。希望行分隔符中没有正则表达式字符。:)“line.separator”无论如何都不可靠。仅因为代码在(例如)Unix上运行,如何阻止文件使用Windows样式的“\r\n”行分隔符?BufferedReader.readLine()和Scanner.nextLine()总是检查所有三种类型的分隔符。我知道这条注释非常古老,
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
}
\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 ""
Pattern NEWLINE = Pattern.compile("\\R")
String lines[] = NEWLINE.split(input)