【问题标题】:BufferedReader stops reading when reaching an empty lineBufferedReader 到达空行时停止读取
【发布时间】:2014-12-05 08:44:11
【问题描述】:

我有一个正在读取文件的 BufferedReader。该文件可以很容易地在 2 个段落之间有一个空行,例如:

Lorem ipsum dolor sit amet,mel in docendi eleifend sapientem,mei cu natum possit salutandi。 Quaeque legimus appareat cum in, tamquam cotidieque duo in. Justo ubique efficiantur ei sit, idque dicat sadipscing ad sit。 Amet 领事 disputationi ei 海。在 reque lorem quo,每立方米的动物奇异,usu euripidis reprimique inciderint eu。

Ocurreret dissentias ei per。 Copiosae vulputate vel ei, ne est dissentias adversarium, ad quo graecis nostrum volutpat。 Vix ut sale persequeris,id est volumus noluisse,mel et Ridens Molestiae。 Ut qui iriure volutpat contentiones, unum propriae inciderint ut duo。 Ei singulis delicata per。 Usu verterem nominati in.

BufferedReader 在到达第一段的末尾时停止阅读。我知道为什么它会停止,因为它认为只要找到一个空行,它就认为它是文件的结尾,这是我的问题。

我一直使用while循环的方式来遍历文件。

我一直在为这个问题争吵,我放弃了我原来的 bufferedreader 方法并对其进行了多次编辑,但它是这样的:(伪代码,这段代码不正确。主要注意 while 循环)

public static String currenttxt() throws IOException {
   BufferedReader br = new BufferedReader(new FileReader(file)); 
     try {
        while (br.readLine() != null) {
           return br.readline();
        }
     } catch (Exception e) {
        e.PrintStackTrace();
     }
}

我该如何解决这个问题?

【问题讨论】:

  • 你能用相关代码sn-p更新你的问题吗?
  • 会的。给我一分钟。
  • 您从流中读取了两次。您在 while() 中读取的数据将被丢弃 :(
  • 由于循环中的return,您的函数只会返回文件的第一行。循环永远不会被执行超过一次。我猜你的第一个“段落”实际上是一个单一的“行”。

标签: java bufferedreader


【解决方案1】:

正如在 cmets 中已经提到的那样,由于while (br.readLine()),您的函数正在丢弃第一行,并在阅读第二行后离开循环。

您应该在某个局部变量中保留已读取的行。

public static String currenttxt() throws IOException {

       try (BufferedReader br = new BufferedReader(new FileReader(file))) {
       StringBuilder b = new StringBuilder();
         try {

            String line = br.readLine();
            while (line != null) {
               b.append(line);
               b.append(System.getProperty("line.separator"));
               line = br.readLine();
            }

         } catch (Exception e) {
            e.printStackTrace();
            throw e;
         }

         // remove the last line separator at the end using trim()
         return b.toString().trim();
       }

使用 java 7 可以简化为

public static String currenttxt() throws IOException{
    List<String> lines; 
    lines = Files.readAllLines(FileSystems.getDefault()
             .getPath(file.getAbsolutePath()));

    StringBuilder b = new StringBuilder();
    boolean insertNewLine = false;
    for (String line : lines) {
        if (insertNewLine) 
            b.append(System.getProperty("line.separator"));

        b.append(line);
        insertNewLine = true;       
    }

    return b.toString();
}

第二个示例显示了一种如何避免最后出现trim() 的方法。 另一种方法是从StringBuilder b 中删除最后一行分隔符。

【讨论】:

    【解决方案2】:

    您应该在每次读取一行时初始化一个变量并为其分配一个值以避免该问题:

        BufferedReader br = new BufferedReader(new FileReader(file));
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();
    
        while (line != null) {
            sb.append(line);
            line = br.readLine();
        }
    
        return sb.toString();
    

    如果您想保留段落之间的空行,最好按字符阅读:

        BufferedReader br = new BufferedReader(new FileReader(file));
        StringBuilder sb = new StringBuilder();
        int c = br.read();
    
        while (c != -1) {
            sb.append(String.valueOf((char)c));
            c = br.read();
        }
    
        return sb.toString();
    

    【讨论】:

    • 在循环头中使用赋值绝对容易出错,而且几乎就是人们所说的“坏代码”。
    • @specializt 不关闭资源也被认为是不好的做法并且容易出错。为了展示如何“正确”实现它,可以在循环中使用赋值 - 只需我的两分钱。
    • 你显然不知道 Java 是如何工作的。资源会自动关闭自己,明确控制该行为只有在外部资源依赖于它时才合理,在其他所有情况下,只需丢弃对象就可以完成它应该发生的一切(在这种情况下)。这不是 C。
    • @specializt 关于这个话题有很多讨论可以在这里找到stackoverflow.com/questions/515975/closing-streams-in-java
    • 那很好....并且永远记住:java为你做了大部分的“清理”——它被称为“垃圾收集”,尽管人们不应该每次都依赖它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 2014-01-25
    • 1970-01-01
    相关资源
    最近更新 更多