Разбор и изменение файла построчно с сохранением символов EOL в Java - PullRequest
3 голосов
/ 15 октября 2010

Один адский длинный вопрос:)

Вот как я обычно это делаю:

StringBuilder b = new StringBuilder();
BufferedReader r = new BufferedReader(new StringReader(s));
while ((String line = r.readLine()) != null)
    b.append(doSomethingToTheString(s) + "\n");

Однако это заменяет все новые символы строки в файле переводом строки, плюс добавляет один в конце, если такового не было. Я хочу сохранить символы EOL, даже если они смешаны так:

Hello\r\n
World\n
This is\r
Messed up

Каков самый элегантный / эффективный способ сделать это?

Ответы [ 3 ]

4 голосов
/ 15 октября 2010

Это не длинный вопрос:)

В принципе, вы не сможете ничего сделать с BufferedReader.readLine() здесь. Он всегда удаляет терминатор строки, и с этим ничего не поделаешь.

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

0 голосов
/ 16 октября 2010

Вот эскиз решения, так как у меня нет времени на разработку полного фрагмента кода.

  1. Вам нужен класс (скажем, WeirdLine) для представления каждой строки, в основном с полем String для содержимого строки и полем byte [] для конца строки.

    class WeirdLine { final String line; final byte[] term; }

  2. Вам нужен класс (скажем, WeirdLineReader), чтобы обернуть InputStream. Он может предоставлять метод readWeirdLine(), который возвращает экземпляр WeirdLine или null, когда поток пуст

  3. WeirdLineReader потребуется поддерживать внутренний байтовый буфер. Когда вызывается readWeirdLine(), поместите байты в буфер (InputStream.read()), увеличивая его по мере необходимости, до

    а. read() возвращает -1, конец файла. readWeirdLine() возвращает экземпляр с нулевым полем-терминатором и все содержимое String, полученное из new String(buffer[]).

    б. Метод findTerminator() сканирует, чтобы найти последовательность байтов \ r \ n или \ n или любые другие терминаторы, с которыми вы хотите справиться. Этот метод также должен возвращать WeirdLine или ноль, и должен оставить внутренний буфер очищенным / усеченным, если это так.

    с. Внутренний буфер просто пуст, возвращаем null

Затем вам нужно написать соответствующий механизм для записи WeirdLine s обратно, сохраняя окончания.

Возможно, проще всего использовать ByteBuffer вместо необработанного byte[] для внутреннего буфера.

Возможно, можно адаптировать код к BufferedReader, если это звучит устрашающе.

0 голосов
/ 16 октября 2010

Если вы хотите сохранить терминаторы строки, используйте InputStream вместо Reader. Вам нужно будет реализовать собственную функцию readLine(), которая ищет стандартный символ / пара новой строки и оставляет его в возвращаемом значении.

Если вы пытаетесь вывести файл, аналогичный вводу, который просто имеет окончания строки по умолчанию в хост-ОС, используйте Writer или добавьте найденный терминатор строки, используя System.getProperty("line.separator").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...