Как узнать, какой разделитель строк BufferedReader # readLine () используется для разделения строки? - PullRequest
12 голосов
/ 24 мая 2011

Я читаю файл через 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")) нельзя использовать, поскольку файл мог быть записан другим приложением в другой операционной системе.

Ответы [ 8 ]

10 голосов
/ 12 декабря 2012

Чтобы быть в фазе с классом 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;
}
7 голосов
/ 24 мая 2011

После прочтения java-документации (я признаюсь, что являюсь питонистом), кажется, что нет чистого способа определить кодировку конца строки, используемую в конкретном файле.1004 * Лучшее, что я могу порекомендовать, это использовать 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 = "";
}
2 голосов
/ 20 июля 2012

Ответ будет таким: Вы не можете узнать, чем заканчивалась строка.

Я ищу, что может вызвать окончания строки в той же функции. Посмотрев исходный код BufferedReader, я могу заметить, что BufferedReader.readLine заканчивает строку на '\ r' или '\ n' и пропускает левую башню '\ r' или '\ n'. Закодировано, не заботится о настройках.

2 голосов
/ 24 мая 2011

BufferedReader.readLine() не предоставляет никаких средств для определения того, каким был разрыв строки.Если вам нужно знать, вам нужно читать символы в себе и находить разрывы строк самостоятельно.

Возможно, вас заинтересует внутренний LineBuffer класс из Гуава (а также общедоступный класс LineReader , в котором он используется).LineBuffer предоставляет метод обратного вызова void handleLine(String line, String end), где end - символы разрыва строки.Возможно, вы могли бы основывать что-то, чтобы делать то, что вы хотите на этом.API может выглядеть примерно так: public Line readLine(), где Line - это объект, который содержит как текст строки, так и конец строки.

2 голосов
/ 24 мая 2011

BufferedReader не принимает FileInputStreams

Нет, вы не можете найти символ конца строки, который использовался в файле, читаемом BufferedReader. Эта информация теряется при чтении файла.

К сожалению, все приведенные ниже ответы неверны.

Редактировать: И да, вы всегда можете расширить BufferedReader, чтобы включить дополнительные функции, которые вы хотите.

1 голос
/ 24 мая 2011

Если вы читаете этот файл в текстовый компонент Swing, вы можете просто использовать метод JTextComponent.read (...) для загрузки файла в документ. Тогда вы можете использовать:

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

чтобы получить фактическую строку EOL, которая использовалась в файле.

0 голосов
/ 22 июля 2014

Не уверен, что полезно, но иногда мне нужно найти разделитель строк после того, как я прочел файл уже далеко внизу.

В этом случае я использую этот код:

/**
* <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$
    }
}
0 голосов
/ 02 июня 2014

Если вы используете groovy, вы можете просто сделать:

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