【问题标题】:BufferedReader messed up by different line seperatorsBufferedReader 被不同的行分隔符搞砸了
【发布时间】:2016-04-12 19:14:35
【问题描述】:

我有一个缓冲阅读器流式传输文件。目前有两种情况:

它正在流式传输在一台 PC 上生成的文件,我们称之为 File1。 它正在流式传输在另一台计算机上生成的文件,我们称之为 File2。

我假设我的问题是由 EOL 引起的。

BufferedReader 确实读取了这两个文件,但对于 File2,它会为每个新行读取一个额外的空行。

此外,当我使用line.equalsIgnoreCase("abc") 比较该行时,假设该行是"abc" 它不会返回true。

将此代码与两个链接中提供的两个文件一起使用以复制问题:

public class JavaApplication {

/**
 * @param args the command line arguments
 */
public static void main(String[] args) throws IOException {
    File file = new File("C:/Users/User/Downloads/html (2).htm");
    BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
    String line = "";

    while ((line = in.readLine()) != null) {
        System.out.println(line);
    }
}

File1, File2

注意第二个文件如何在每行之后打印一个空行...

我一直在寻找和尝试,寻找和尝试,但无法提出解决方案。

任何想法如何解决这个问题? (尤其是比较的东西?)

【问题讨论】:

  • 我认为\r, CR, 0x0d 和\n, LF, 0x0a 之间存在混淆。因为如果行以\n\r 结尾,BufferedReader 会识别两行:以\n = Unix 风格和\r = 旧Mac 风格结束,而\r\n 将是Windows 风格。
  • 好吧,如果\r\n 让它每隔一行读取一个空行会更有意义,但它是\r 这样做......我用这个答案来找出分隔符,也许它也不是功能齐全^^ stackoverflow.com/a/13828045/3653975
  • @JoopEggen 有什么问题?更新了答案以显示我用来获取新行的代码,以及比较行...非常感谢帮助
  • 你可以试试line = line.replaceAll("\r\n","\n");
  • 第一个显示 UTF-8,另一个显示 UTF-16。 UTF-16 错误地读取为 ASCII 的 UTF-8,在每个字节 (char) 之后包含一个 nul 字节 (char)。 这就是解决方案。在HTML中也是这样指定的,charset=...

标签: java bufferedreader


【解决方案1】:

为我工作。

public class CRTest
{
   static StringReader test = new StringReader( "Line 1\rLine 2\rLine 3\r" );
   public static void main(String[] args) throws IOException {
      BufferedReader buf = new BufferedReader( test );
      for( String line = null; (line = buf.readLine()) != null; )
         System.out.println( line );
   }
}

打印:

run:
Line 1
Line 2
Line 3
BUILD SUCCESSFUL (total time: 1 second)

正如 Joop 所说,我认为您混淆了哪个文件不起作用。请使用上面的框架创建一个MCVE,并准确地向我们展示哪些文件输入不适合您。


由于您似乎有一个带有反转 \r\n 行的文件,这是我第一次尝试修复。请测试一下,我还没试过。你需要用这个类包裹你的InputStreamReader,然后像往常一样在外面包裹BufferedReader

class CRFix extends Reader
{

   private final Reader reader;
   private boolean readNL = false;

   public CRFix( Reader reader ) {
      this.reader = reader;
   }

   @Override
   public int read( char[] cbuf, int off, int len )
           throws IOException
   {
      for( int i = off; i < off+len; i++ ) {
         int c = reader.read();
         if( c == -1 )
            if( i == off ) return -1;
            else return i-off-1;
         if( c == '\r' && readNL ) { 
            readNL = false;
            c = reader.read();
         }
         if( c == '\n' ) 
            readNL = true;
         else 
            readNL = false;
         cbuf[i] = (char)c;
      }
      return len;
   }

   @Override
   public void close()
           throws IOException
   {
      reader.close();
   }

}

【讨论】:

  • 好吧,我猜我用来确定哪个使用返回相反结果的方法......但不确定。假设它实际上是相反的,当行分隔符为 \r\n 时,我如何让它只读取一行而不是两行?
  • 我(终于)用一个样本更新了我的问题,希望它能做它应该做的......
  • 我测试了 CRFix 类并修复了如何检测文件结尾。它现在应该可以工作了。但是当您提到您发布的文件没有您描述的问题时。您的问题可能出在其他地方。
  • 我们去,再次尝试 File2,它使用我的问题中提供的代码下载并复制问题,无论是否使用 CRFix
【解决方案2】:

Joop 是对的,经过更多研究后看来,即使两个文件都在其标头中指定了 UTF-16 编码,一个以 UTF-16 编码,另一个(File1)以 UTF-8 编码。这导致了“双线效应”。 感谢您在回答这个问题时付出的努力。

【讨论】:

  • 我相信您可以将自己的答案标记为正确。如果这是实际答案,您应该这样做。
  • 我打算这样做,但您需要等一天才能这样做;)再次感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 2019-08-08
  • 1970-01-01
  • 2012-12-27
  • 2013-06-16
  • 1970-01-01
相关资源
最近更新 更多