Какой символ можно использовать для разбора абзацев с Java? - PullRequest
7 голосов
/ 03 февраля 2010

Я уверен, что люди будут смеяться над этим, но для жизни я не могу найти разделитель, который будет указывать, когда новый текст в начале строки начинается.Слово, а строка?Легко peasy, но абзац, кажется, гораздо сложнее найти.Я пробовал два разрыва строки подряд, Unicode-представление разрыва параграфа и разрыва строки, но безуспешно.

РЕДАКТИРОВАТЬ: Я прошу прощения за неопределенность моего первоначального вопроса.Чтобы ответить на некоторые вопросы, это основной текстовый файл, изначально созданный в Windows.Я тестирую некоторый код для открытия и анализа его содержимого с помощью Blackberry JDE 4.5 с помощью плагина RIM eclipse.Хотя источником файла будут окна (по крайней мере, в обозримом будущем) и основной текст, я не могу контролировать, как они создаются (это сторонний источник, к которому у меня нет доступа к тому, как он создается).

Ответы [ 6 ]

5 голосов
/ 03 февраля 2010

В обычном использовании такого символа разрыва абзаца нет.

Возможно, вам удастся предположить, что два или более разрывов строки подряд (с необязательным горизонтальным пробелом) указывают на разрыв абзаца. Но есть множество исключений из этого «правила». Например, когда абзац

  • прерывается плавающей цифрой или
  • содержит маркеры

и затем продолжается ... как этот. Для такого рода вещей, вероятно, нет решения.

РЕДАКТИРОВАТЬ за @ комментарий Эйдена ниже. (Теперь ясно, что это не относится к ОП, но это может относиться и к другим, кто находит вопрос через Google и т. Д.)

Вместо того чтобы пытаться реконструировать абзацы из текста, возможно, вам следует подумать о том, чтобы указать, что ваш ввод должен быть (например) Markdown синтаксис; т.е. как поддерживается StackOverflow. Markdown Wiki содержит ссылки на реализации анализатора разметки на многих языках, включая Java.

(Предполагается, что вы имеете некоторый контроль над форматом ввода текста, который вы пытаетесь разобрать в абзацы и т. Д.)

3 голосов
/ 03 февраля 2010

Абзацы в текстовых документах обычно разделяются двумя или более разделителями строк.Разделителем строк может быть перевод строки (\n), возврат каретки (\r) или возврат каретки, за которым следует перевод строки (\r\n).Эти три вида разделителей обычно связаны с операционными системами, но любое приложение может свободно писать текст, используя любой тип разделителя строк.Фактически, текст, собранный из разных источников (например, веб-страницы), может содержать два или более вида разделителя.Когда ваше приложение читает текст, независимо от того, на какой платформе оно работает, оно всегда должно проверять все три вида разделителя строк.

BufferedReader#readLine() делает это, но, конечно, он читает только одну строку за раз.Простая проза обычно возвращается в виде чередующейся последовательности непустых строк, представляющих абзацы, и пустых строк, представляющих пробелы между ними.Но не рассчитывай на это;следите за несколькими пустыми строками и помните, что «пустые» строки могут фактически содержать пробельные символы, такие как пробел (\u0020) и TAB (\u0009).

Если вы решите не использовать BufferedReader, возможно, вам придется написать код обнаружения с нуля.Java ME не включает поддержку регулярных выражений, поэтому split() и java.util.Scanner недоступны;и StringTokenizer не делает различий между одним символом-разделителем и несколькими символами подряд, если вы не используете опцию returnDelims.Затем он возвращает разделители по одному символу за раз, поэтому вам все равно нужно написать собственный код, чтобы выяснить, какой тип разделителя вы просматриваете, если таковой имеется.

3 голосов
/ 03 февраля 2010

Возможно, что вместо перевода строки вам нужно искать последовательность CR LF (\ r \ n) - очевидно, ответ будет зависеть от формата текста.

2 голосов
/ 03 февраля 2010

Во-первых, вам лучше всего определить абзац. Будь то разрыв строки, двойной разрыв строки или разрыв строки с последующей вкладкой. Предполагая, что вы не можете контролировать ввод и хотите определить количество абзацев в различных образцах текста, может возникнуть любая из этих ситуаций. Кроме того, они могут быть использованы для той же цели в том же документе. Поэтому для этого необходим некоторый анализ, и имейте в виду, что он не будет на 100% точным все время.

Начните с инициализации различных возможных разрывов абзаца:

  • "\ г"
  • "\ п \ г"
  • "\ п"
  • System.getProperty ( "line.seperator")

и все эти, но дважды, и все эти варианты с дополнительным символом табуляции ('\ t') в конце.

Неэффективный способ сделать это - загрузить входные данные в строку, а затем вызвать buffer.split().length, чтобы определить количество абзацев. Эффективный, масштабируемый способ - использовать поток и просматривать входные данные, принимая во внимание длину абзаца и выбрасывая эти абзацы ниже заданного «порога». Более продвинутый алгоритм может даже переключать то, что он считает абзацем, после того, как он встречает изменение в способе обработки разрывов строк (например, несколько очень коротких строк или несколько очень длинных).

И все это предполагает, что вы имеете дело с неформатированным текстом без заголовков разделов и т. Д. Суть вопроса в том, чтобы спросить, сколько параграфов в конкретном фрагменте текста, это как вопрос, сколько недель год. Это не совсем 52, но это где-то там.

2 голосов
/ 03 февраля 2010

Я предполагаю, что у вас есть текстовый файл, а не сложный документ, такой как MS-Word или RTF.

Понятие абзаца в текстовом документе недостаточно четко определено. В большинстве случаев новый абзац будет распознаваться тем, что при открытии документа в текстовом редакторе вы увидите следующий набор текста, начинающийся со следующей строки.

Есть два специальных символа, а именно. символ новой строки (LF - '\n') и возврат каретки (CR - '\r'), в результате чего текст начинается со следующей строки. Какой символ используется для следующей строки, зависит от используемой вами операционной системы. Более того, иногда комбинация обоих также используется как CRLF ('\r\n').

В Java вы можете определить символ или набор символов, используемых для разделения строк / абзацев, используя System.getProperty("line.separator");. Но это приносит новую проблему. Что если вы создадите текстовый файл в MS Windows, а затем откроете его в Unix? Строковый разделитель в текстовом файле в данном случае - это Windows, но Java работает в Unix.

.

Моя рекомендация:

ЕСЛИ длина текста (документа) равна нулю, ТОГДА абзацы = 0.

ЕСЛИ длина текста (документа) НЕ равна нулю, ТО

  • Рассмотрим '\n' и '\r' как строку символы разрыва .
  • Сканирование текста на наличие разрыва строки выше символы.
  • Любые символы непрерывного разрыва строки в любом порядке следует рассматривать как один разрыв абзаца .
  • Количество абзацев = 1 + (количество разрывы абзацев)

Обратите внимание, что исключения, указанные Стивеном, все еще применимы и здесь.

.

public class ParagraphTest {

    public static void main(String[] args) {
        String document = 
                    "Hello world.\n" + 
                    "This is line 2.\n\r" + 
                    "Line 3 here.\r" + 
                    "Yet another line 4.\n\r\n\r" + 
                    "Few more lines 5.\r";
        printParaCount(document);
    }

    public static void printParaCount(String document) {
        String lineBreakCharacters = "\r\n";
        StringTokenizer st = new StringTokenizer(
                    document, lineBreakCharacters);
        System.out.println("ParaCount: " + st.countTokens());
    }

}

выход

ParaCount: 5
2 голосов
/ 03 февраля 2010
String lineSeparator = System.getProperty("line.separator");

Возвращает разделитель строки платформы по умолчанию.

Таким образом, например, должно работать следующее:

String[] paragraphs = text.split(lineSeparator);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...