Использование метода split() для большого текстового файла
У меня есть огромный файл можно сказать книга, и я хочу сделать split чтоб смог посчитать сколько раз каждое слово встречается в файле. Но непонятно как использовать метод split(), потому что в тексте огромное количество знаков пробелов. Это не помогает String[] words = line.split(" ");
BufferedReader br = new BufferedReader(new FileReader("D:\\customer1.txt"))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine().toLowerCase();
String[] words = line.split(" ");
Ответы (2 шт):
Я в java не силен, но возможно вы сможете найти ответ на примере Python кода:
from collections import defaultdict
with open("text.txt") as file_book:
for line in file_book:
words = line
word_list = words.split()
word_count_dict = defaultdict(int)
for word in word_list:
word_count_dict[word] += 1
print(word, word_count_dict[word])
Во-первых, String::split помогает.
Во-вторых, для исключения нескольких пробельных символов, идущих подряд, следует использовать регулярное выражение .split("\\s+"), однако оно не исключает знаки пунктуации, которые будут включаться в слова. Можно применять разбиение по другим POSIX-классам символов:
.split("\\P{L}+")- разбить по всем символам, не являющимся буквами (\\P- отрицание).split("\\P{Alnum}+")- разбить по всем символам, не являющимися буквами или цифрами.split("[\\p{Space}\\p{Punct}]+")- разбить по всем символам, являющимися пробельными символами или знаками пунктуации
В-третьих, для подсчета частоты слов следует использовать словарь/хэш-таблицу слов Map<String, Long>, где слово является ключом, частота -- значением.
Используя NIO API для чтения файлов и Java Stream API, можно написать такую реализацию:
public static Map<String, Long> wordFreqMap(String filename) throws IOException {
return Files.lines(Paths.get(filename)) // Stream<String> - поток строк
.map(line -> line.split("\\P{Alnum}+")) // Stream<String[]> - массивы слов
.flatMap(Arrays::stream) // Stream<String> - поток слов
.collect(Collectors.groupingBy(
word -> word, // сгруппировать по ключам-словам
Collectors.counting() // подсчитать частоту
));
}
Операции .map + flatMap можно объединить в одну:
return Files.lines(Paths.get(filename)) // Stream<String> - поток строк
.flatMap(line -> Arrays.stream(line.split("\\P{Alnum}+")))
// ...