从InputStream读取一行

40
我正在使用一个InputStream来读取一些数据,我想读取字符直到换行或'\n'为止。
InputStream是一个通用的字节输入流,不限于任何特定的实现或任何来源(如文件)。

4
请使用 BufferedReader 和其 readLine 方法。重复问题:http://www.stackoverflow.com/questions/5868369/how-to-read-a-large-text-file-line-by-line-using-java - Tunaki
我不同意这是一个重复的问题。问题[1]和[2]是关于从文件中读取内容,答案使用了特定于文件的API。问题[3]是在那之后提出的(10个月后),并且得到的投票和关注度远远少于前两个问题,应该将问题[3]标记为重复。[1] https://stackoverflow.com/questions/5868369/how-can-i-read-a-large-text-file-line-by-line-using-java [2] https://stackoverflow.com/questions/14825374/reading-a-textfile-using-inputstream [3] https://stackoverflow.com/questions/40250814/read-a-line-of-a-file-using-an-inputstream - undefined
3个回答

104

如果你从文件中读取内容,应该使用FileInputStreamReaderBufferedReader

BufferedReader reader = new BufferedReader(new FileInputStreamReader(pathToFile));

如果您从任何其他 InputStream 中读取,则可以使用 InputStreamReader

BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

然后在循环中使用它的readLine()方法

while(reader.ready()) {
     String line = reader.readLine();
}

但是如果您真的喜欢InputStream,那么可以使用类似以下循环的方式

InputStream stream; 
char c; 
String s = ""; 
do {
   c = stream.read(); 
   if (c == '\n')
      break; 
   s += c + "";
} while (c != -1);

我希望有一些内置的东西 :/。另外,BufferedReader不支持编码。 - Radim Nyč
7
“built in”指的是内置。BufferedReader是Java标准库中的一部分,它实际上可以指定编码方式,例如: new BufferedReader(new InputStreamReader(new FileInputStream("path/to/file"), "UTF8")); - Tommaso Pasini
不知道这一点。我发现你可以使用InputStream来实现,然后我想找出是否有任何方法可以使InputStream在没有while循环的情况下读取行。我将尝试提到的BufferedReader构造函数... - Radim Nyč
1
对于未来像我一样偶然发现这个问题的人,正确的方法是使用 FileReader 而不是 FileInputStreamReader。 - Krusty the Clown
1
reader.ready() 不总是返回 true,导致无法读取行。更多失败证明:String line = null; while ((line = reader.readLine()) != null) { ... } - kaiser
1
(1) FileInputStreamReader 不存在。 (2) while (reader.ready()) 是无效的。ready() 不是用来测试流结束的方法,正如 Javadoc 中明确说明的那样。正确的测试方法是 while ((line = reader.readLine()) != null)。这段代码在流结束之前是完全能够停止的。回答是未经测试的胡言乱语。 - undefined

10

简而言之

try-with块中使用BufferedReader,它会在使用完资源后自动关闭。


可以使用BufferedReader和Scanner来读取输入流。如果没有充分的理由,最好使用BufferedReader(有关BufferedReader和Scanner的广泛讨论,请参见此处链接)。
我还建议使用带有try-with-resources的BufferedReader,以确保资源自动关闭(请参见此处链接)。
请参考以下代码。
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

1
while (reader.ready()) 是无效的。ready() 不是一个用于测试流结束的方法。正确的测试方法是 while ((line = reader.readLine()) != null)。这段代码在流结束之前是完全能够停止的。 - undefined
@user207421,已更新。感谢您的评论。 - undefined

6

对于文件,下面的代码将让您逐行读取:

import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.File;

public static void readText throws FileNotFoundException(){

     Scanner scan = new Scanner(new File("filename.txt"));

     while(scan.hasNextLine()){
         String line = scan.nextLine();

     }
}

6
这个回答与InputStreams无关。 - slang
4
是的,如果稍微改写一下,它就可以——var scan = new Scanner(InputStream source) - Kong
代码中的 val scan = Scanner(inputstream) 解决了我的问题,可以读取分块的 HTTP 响应。 - rwst
@rwst 我不明白。Scanner 中没有任何关于 HTTP 分块的信息。我想删除 reader.ready() 才是真正的解决办法。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接