Как посчитать количество слов в файле java

Обновлено: 07.07.2024

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

2. Использование StringTokenizer

Простой способ подсчета слов в строке в Java - использовать класс StringTokenizer :

Обратите внимание, что StringTokenizer автоматически обрабатывает пробелы , например табуляции и возврат каретки.

Но в некоторых местах это может быть глупо, например дефисы:

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

К счастью, StringTokenizer поставляется с другим конструктором. Мы можем передать в конструктор разделитель, чтобы это работало:

Это удобно при попытке подсчитать количество слов в строке из чего-то вроде файла CSV:

Итак, StringTokenizer прост, и он помогает нам в этом.

Давайте посмотрим, какую дополнительную мощность могут дать нам регулярные выражения.

3. Регулярные выражения

Чтобы придумать осмысленное регулярное выражение для этой задачи, нам нужно определить, что мы считаем словом: слово начинается с буквы и заканчивается либо пробелом, либо знаком препинания .

Имея это в виду, для данной строки мы хотим разделить эту строку в каждой точке, где встречаются пробелы и знаки препинания, а затем подсчитать полученные слова.

Давайте немного поработаем, чтобы увидеть мощь регулярного выражения:

Непрактично решать эту проблему, просто передавая разделитель в StringTokenizer, поскольку нам пришлось бы определить действительно длинный разделитель, чтобы попытаться перечислить все возможные знаки препинания.

Оказывается, нам действительно не нужно много делать, передача регулярного выражения [\ pP \ s && [^ ']] + в метод split класса String сделает свое дело :

Регулярное выражение [\ pP \ s && [^ ']] + находит любую длину знаков препинания или пробелов и игнорирует знак препинания апострофа.

Чтобы узнать больше о регулярных выражениях, обратитесь к Регулярным выражениям на Baeldung.

4. Циклы и String API

Другой метод - установить флаг, отслеживающий встреченные слова.

Мы устанавливаем флаг в WORD, когда встречаем новое слово, и увеличиваем счетчик слов, а затем возвращаемся в SEPARATOR, когда мы встречаем неслово (знаки пунктуации или пробелы).

Этот подход дает те же результаты, что и с регулярными выражениями:

Мы должны быть осторожны в особых случаях, когда знаки препинания не являются разделителями слов , например:

Здесь мы хотим считать «фермерское» одним словом, хотя апостроф «'» - это знак препинания.

В версии с регулярным выражением у нас была возможность определить, что не квалифицируется как символ, с помощью регулярного выражения. Но теперь, когда мы пишем нашу собственную реализацию, мы должны определить это исключение в отдельном методе :

Итак, что мы сделали здесь, так это разрешить одним словом все символы и допустимые знаки препинания, в данном случае апостроф.

Теперь мы можем использовать этот метод в нашей реализации:

Первое условие отмечает слово, когда оно встречается, и увеличивает счетчик. Второе условие проверяет, не является ли символ буквой, и устанавливает флаг в SEPARATOR .

5. Заключение

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

Определение лимитов персонажей становится критически важным, когда обновления через твиты и посты в Facebook выполняются через API.

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

// Java-программа для подсчета
// количество символов в файле

public class Test

public static void main(String[] args) throws IOException

File file = new File( "C:\\Users\\Mayank\\Desktop\\1.txt" );

FileInputStream fileStream = new FileInputStream(file);

InputStreamReader input = new InputStreamReader(fileStream);

BufferedReader reader = new BufferedReader(input);

int countWord = 0 ;

int sentenceCount = 0 ;

int characterCount = 0 ;

int paragraphCount = 1 ;

int whitespaceCount = 0 ;

// Чтение построчно из

// файл, пока ноль не будет возвращен

while ((line = reader.readLine()) != null )

// // s + это разделитель пространства в java

String[] wordList = line.split( "\\s+" );

whitespaceCount += countWord - 1 ;

// [. ] + это разделитель предложений в java

String[] sentenceList = line.split( "[. ]+" );

System.out.println( "Total word count plain">+ countWord);

System.out.println( "Total number of sentences plain">+ sentenceCount);

System.out.println( "Total number of characters plain">+ characterCount);

System.out.println( "Number of paragraphs plain">+ paragraphCount);

System.out.println( "Total number of whitespaces plain">+ whitespaceCount);

Используемые встроенные функции

  1. File (String pathname): java.io.File: Создает новый экземпляр File путем преобразования указанной строки пути в абстрактный путь.
    Синтаксис:
  2. FileInputStream (File file): java.io.FileInputStream: Создает FileInputStream, открывая соединение с реальным файлом, именем файла которого является объектный файл File в файловой системе.
    Синтаксис:
  3. InputStreamReader (InputStream in): java.io.InputStreamReader: создает InputStreamReader, который использует кодировку по умолчанию.
    Синтаксис:
  4. BufferedReader (Reader in): java.io.BufferedReader: Создает буферный поток ввода символов, который использует размер буфера ввода по умолчанию.
    Синтаксис:

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

В эти дни я выпустил Wordcounter , библиотеку Java и утилиту командной строки для подсчета слов в текстовых файлах и выполнения анализа количества слов, в котором интенсивно используются конструкции функционального программирования и подходы параллельных вычислений. Это моя четвертая запись для конкурса «Geeky Quickies» в SAP , после Feeder , Todor и Hanoier .

Библиотека использует лямбды JDK 8, а также новые функции JDK 7, такие как Fork / Join и NIO.2 . Он построен и может использоваться только с ранней версией JDK 8 с поддержкой лямбды .

С появлением лямбд и их вспомогательных функций в JDK 8 способ, которым мы создаем программное обеспечение на Java, изменится. Если вы хотите получить представление о том, как может выглядеть ваш Java-код через несколько лет, вы можете взглянуть на Wordcounter. В отличие от большинства доступных на данный момент ресурсов, это не простой учебник, а реально работающий проект.

Конкурсное задание попросило реализовать алгоритм с использованием Fork / Join и lambdas, который анализирует все файлы в каталоге и находит десять наиболее часто используемых слов в файлах вместе с тем, сколько раз они встречаются. Вместо того, чтобы просто придерживаться Fork / Join, я попытался найти наиболее подходящий параллельный подход для этой конкретной задачи, что привело меня к выбору Producer / Consumer для основной логики подсчета слов.

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

Последние бинарные, javadoc и исходные пакеты можно найти в разделе загрузок GitHub. Если будет достаточно интереса, я опубликую Javadoc онлайн и сделаю библиотеку доступной также в центральных репозиториях Maven.

Отзывы, комментарии и комментарии приветствуются!

обзор

Особенности библиотеки

  • Подсчитайте все слова в строке, отдельном текстовом файле или дереве каталогов, содержащем текстовые файлы.
  • Проанализируйте количество слов, чтобы найти первые N наиболее употребляемых слов, нижние N наименее употребляемых слов или общее количество слов.
  • Укажите, является ли символ символом слова с помощью внешнего предиката.
  • Укажите необязательную операцию, выполняемую над словами, например, преобразование в нижний регистр через внешнего оператора.
  • Выберите между непараллельными и параллельными реализациями, чтобы сравнить их производительность.
  • Если нужно, укажите уровень параллелизма, который будет отличаться от количества ядер.

Основные моменты программирования

  • Использует Producer / Consumer для чтения файлов и параллельного подсчета слов в каждом файле. Фактический механизм инкапсулирован в общей, многократно используемой реализации.
  • Использует Fork / Join для выполнения анализа количества слов. Здесь снова фактический механизм заключен в общую, многократно используемую реализацию.
  • Использует NIO.2 для обхода каталогов и чтения файлов.
  • Интенсивно использует функциональные интерфейсы и лямбда-выражения для передачи функций, а не данных, где это уместно.
  • Для двух наиболее важных классов существуют комплексные тесты модулей и производительности.
  • Как обычно, код чистый, хорошо структурированный и легко читаемый. Форматирование, наименование и комментарии единообразны и последовательны. Большое внимание было уделено надлежащему использованию как методов объектно-ориентированного, так и функционального программирования.

Интерфейс командной строки

Чтобы запустить программу командной строки, выполните следующую команду:

Все параметры имеют разумные значения по умолчанию, поэтому ни один из них не является обязательным. Использование значений по умолчанию для всех параметров приводит к нахождению 10 самых популярных слов в текущем каталоге и его подкаталогах. Задание значений не по умолчанию позволяет указывать разные каталоги, режимы анализа, символы слов, количество слов и уровень параллелизма, а также игнорировать регистр или использовать последовательные, а не параллельные вычисления, например:

Найдите 10 самых популярных слов в каталоге «words»: -p words
Найдите нижние 5 наименее употребляемых слов в каталоге «wordsx», считая числа как символы слова, игнорируя регистр, с регистрацией информации: -p wordsx -m bottom -d 1234567890 -i -n 5 -l info

Для получения дополнительной информации об опциях интерфейса командной строки см. Интерфейс командной строки в README.

дизайн

Универсальные утилиты параллельной обработки

Класс ForkJoinComputer

Класс ForkJoinComputer<T> является универсальным компьютером Fork / Join. Он делит исходный размер на 2, пока либо не достигнет указанного уровня параллелизма, либо не опустится ниже указанного порогового значения, последовательно вычислит каждую часть с использованием указанного Computer<T> , а затем объединит результаты всех вычислений с использованием указанного Merger<T> . Здесь Computer и Merger являются функциональными интерфейсами, которые определены следующим образом:

Это код, который я написал для подсчета слов в строке.

Я пробовал это пару раз, но это только дает мне 0 в результате, что я сделал не так?

спросил(а) 2021-01-03T14:09:08+03:00 10 месяцев, 3 недели назад

Привет, я согласен, вам нужно использовать nextLine()
Но из того, что я понимаю, подсчет '' (пробел) не очень хороший способ подсчета слов
Лучше использовать

Таким образом, даже если ваша строка началась с пробела, все еще в порядке
Это также позволяет пропускать несколько пробелов

ответил(а) 2021-01-03T14:09:08+03:00 10 месяцев, 3 недели назад

Вы можете использовать split by white-space, а затем получить размер.

А также добавьте еще один символ для разделения.

ответил(а) 2021-01-03T14:09:08+03:00 10 месяцев, 3 недели назад

Замените next() на nextLine() иначе оно остановится на первом слове и не будет продолжено.

Находит и возвращает следующий полный токен из этого сканера. Перед первым токеном предшествует ввод, соответствующий шаблону разделителя. Этот метод может блокироваться при ожидании ввода для сканирования, даже если предыдущий вызов hasNext() возвратил true.

Разделители по умолчанию для сканера

[. ] Сканер разбивает свой вход на токены, используя шаблон разделителя, который по умолчанию соответствует пробелу. [. ]

Решение

ответил(а) 2021-01-03T14:09:08+03:00 10 месяцев, 3 недели назад

Причина, по которой генерируется ваш код 0 заключается в том, что при вызове

ваша строка получает первое слово, а затем останавливается. next() сканирует до первого разделителя, а затем возвращает.

читать всю строку.

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

Лучшим подходом было бы вызвать next раз до hasNext() пор, пока hasNext() вернет false и напечатает количество раз, которое вы могли бы назвать next успешно. Это будет количество слов, введенных пользователем.

Читайте также: