簡體   English   中英

如何找出用於分割行的行分隔符 BufferedReader#readLine()?

[英]How to find out which line separator BufferedReader#readLine() used to split the line?

我正在通過 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") 返回),因為該文件可能已由另一個操作系統上的另一個應用程序寫入。

要與 BufferedReader class 保持同步,您可以使用以下方法處理 \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;
}

在閱讀了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 = "";
}

BufferedReader.readLine()不提供任何方法來確定換行符是什么。 如果你需要知道,你需要自己閱讀字符並自己找到換行符。

您可能對Guava的內部LineBuffer class(以及它所使用的公共LineReader class)感興趣。 LineBuffer提供了一個回調方法void handleLine(String line, String end)其中end是換行符。 您可能可以基於某些東西來做您想做的事情。 API 可能類似於public Line readLine() ,其中Line是包含行文本和行尾的 object。

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

我正在尋找什么會導致同一功能中的行結束。 查看 BufferedReader 源代碼后,我可以發現 BufferedReader.readLine 在 '\r' 或 '\n' 上結束行並跳過 leftower '\r' 或 '\n'。 硬編碼,不關心設置。

BufferedReader不接受FileInputStreams

不,您無法找出 BufferedReader 正在讀取的文件中使用的行終止符。 該信息在讀取文件時丟失。

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

編輯:是的,您始終可以擴展 BufferedReader 以包含您想要的附加功能。

如果您碰巧將此文件讀入 Swing 文本組件,那么您只需使用 JTextComponent.read(...) 方法將文件加載到 Document 中。 然后你可以使用:

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

獲取文件中使用的實際 EOL 字符串。

也許您可以改用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
}

您可以使用下面的代碼將BufferedReader轉換為Scanner

 new Scanner(bufferedReader);

不確定是否有用,但有時我需要在閱讀完文件后找出行分隔符。

在這種情況下,我使用以下代碼:

/**
* <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$
    }
}

如果您使用的是 groovy,您可以簡單地執行以下操作:

def lineSeparator = new File('path/to/file').text.contains('\r\n') ? '\r\n' : '\n'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM