13

我正在通过 BufferedReader 读取文件

String filename = ...
br = new BufferedReader( new FileInputStream(filename));
while (true) {
   String s = br.readLine();
   if (s == null) break;
   ...
}

我需要知道这些行是否由 '\n' 或 '\r\n' 分隔,有什么办法可以找到吗?

我不想打开 FileInputStream 所以最初扫描它。理想情况下,我想问 BufferedReader,因为它必须知道。

我很高兴覆盖 BufferedReader 来破解它,但我真的不想打开文件流两次。

谢谢,

注意:当前行分隔符(由 System.getProperty("line.separator") 返回)不能使用,因为该文件可能已由另一个操作系统上的另一个应用程序写入。

4

9 回答 9

14

要与 BufferedReader 类同步,您可以使用以下处理 \n、\r、\n\r 和 \r\n 结束行分隔符的方法:

public static String retrieveLineSeparator(File file) throws IOException {
    char current;
    String lineSeparator = "";
    FileInputStream fis = new FileInputStream(file);
    try {
        while (fis.available() > 0) {
            current = (char) fis.read();
            if ((current == '\n') || (current == '\r')) {
                lineSeparator += current;
                if (fis.available() > 0) {
                    char next = (char) fis.read();
                    if ((next != current)
                            && ((next == '\r') || (next == '\n'))) {
                        lineSeparator += next;
                    }
                }
                return lineSeparator;
            }
        }
    } finally {
        if (fis!=null) {
            fis.close();
        }
    }
    return null;
}
于 2012-12-11T20:32:10.380 回答
7

在阅读了java 文档(我承认自己是一个 pythonista)之后,似乎没有一种干净的方法来确定特定文件中使用的行尾编码。

我可以推荐的最好的事情是你使用BufferedReader.read()和迭代文件中的每个字符。像这样的东西:

String filename = ...
br = new BufferedReader( new FileInputStream(filename));
while (true) {
   String l = "";
   Char c = " ";
   while (true){
        c = br.read();
        if not c == "\n"{
            // do stuff, not sure what you want with the endl encoding
            // break to return endl-free line
        }
        if not c == "\r"{
            // do stuff, not sure what you want with the endl encoding
            // break to return endl-free line
            Char ctwo = ' '
            ctwo = br.read();
            if ctwo == "\n"{
                // do extra stuff since you know that you've got a \r\n
            }
        }
        else{
            l = l + c;
        }
   if (l == null) break;
   ...
   l = "";
}
于 2011-05-24T16:43:07.183 回答
3

BufferedReader.readLine()不提供任何方法来确定换行符是什么。如果你需要知道,你需要自己阅读字符并自己找到换行符。

您可能对Guava的内部LineBuffer类(以及它使用的公共LineReader类)感兴趣。提供了一个回调方法,换行符在哪里。您可能可以基于某些东西来做您想做的事情。API 可能类似于where is 包含行文本和行尾的对象。LineBuffervoid handleLine(String line, String end)endpublic Line readLine()Line

于 2011-05-24T16:30:18.800 回答
2

BufferedReader不接受FileInputStreams

不,您无法找出 BufferedReader 正在读取的文件中使用的行终止符。该信息在读取文件时丢失。

不幸的是,以下所有答案都不正确。

编辑:是的,您始终可以扩展 BufferedReader 以包含您想要的附加功能。

于 2011-05-24T16:23:10.670 回答
2

答案是你无法找出行尾是什么。

我正在寻找什么会导致同一功能中的行结束。查看 BufferedReader 源代码后,我可以发现 BufferedReader.readLine 在 '\r' 或 '\n' 上结束行并跳过 leftower '\r' 或 '\n'。硬编码,不关心设置。

于 2012-07-20T11:29:30.227 回答
1

如果您碰巧将此文件读入 Swing 文本组件,那么您可以使用 JTextComponent.read(...) 方法将文件加载到 Document 中。然后你可以使用:

textComponent.getDocument().getProperty( DefaultEditorKit.EndOfLineStringProperty );

获取文件中使用的实际 EOL 字符串。

于 2011-05-24T16:38:58.053 回答
1

也许你可以Scanner改用。

您可以传递正则表达式Scanner#useDelimiter()来设置自定义分隔符。

String regex="(\r)?\n";
String filename=....;
Scanner scan = new Scanner(new FileInputStream(filename));
scan.useDelimiter(Pattern.compile(regex));
while (scan.hasNext()) {
    String str= scan.next();
    // todo
}

您可以使用下面的代码转换BufferedReaderScanner

 new Scanner(bufferedReader);
于 2020-04-29T06:16:16.697 回答
0

不确定是否有用,但有时我需要在阅读完文件后找出行分隔符。

在这种情况下,我使用以下代码:

/**
* <h1> Identify which line delimiter is used in a string </h1>
*
* This is useful when processing files that were created on different operating systems.
*
* @param str - the string with the mystery line delimiter.
* @return  the line delimiter for windows, {@code \r\n}, <br>
*           unix/linux {@code \n} or legacy mac {@code \r} <br>
*           if none can be identified, it falls back to unix {@code \n}
*/
public static String identifyLineDelimiter(String str) {
    if (str.matches("(?s).*(\\r\\n).*")) {     //Windows //$NON-NLS-1$
        return "\r\n"; //$NON-NLS-1$
    } else if (str.matches("(?s).*(\\n).*")) { //Unix/Linux //$NON-NLS-1$
        return "\n"; //$NON-NLS-1$
    } else if (str.matches("(?s).*(\\r).*")) { //Legacy mac os 9. Newer OS X use \n //$NON-NLS-1$
        return "\r"; //$NON-NLS-1$
    } else {
        return "\n";  //fallback onto '\n' if nothing matches. //$NON-NLS-1$
    }
}
于 2014-07-22T14:37:14.027 回答
-2

如果您使用的是 groovy,您可以简单地执行以下操作:

def lineSeparator = new File('path/to/file').text.contains('\r\n') ? '\r\n' : '\n'
于 2014-06-02T15:39:59.877 回答