Распределение количества/частоты появления символов в файле, включая невидимые

Моя цель — создать частотное распределение каждого символа в больших плоских файлах (1 ГБ+) для последующего импорта в базу данных. В идеале на выходе должен быть список символов ASCII, за каждым из которых следует число.

В настоящее время я использую хэш-карту для создания распределения каждого значения в строке, и это работает, я просто не уверен, как реализовать это в большом файле. Кроме того, в моем выводе символы CR и LF (или / r / n) приводят к новой строке со счетчиком на следующем.

Вот текущий код:

public class CharCount{
public static void main(String[] args) {

String s = "abcdefghijklmnopqrstuvwxyz1234567890,.)(/\\<>?!@#$%^&*_-+=\r\n";

char[] arr = s.toCharArray();

HashMap <Character,Integer> count = new HashMap<Character, Integer>();

for (char c : arr) {

try {
count.put(c, count.get(c)+1);
} catch (NullPointerException e) {

count.put(c, 1);
}
}

for (Character c: count.keySet()) {
System.out.println(c + " = " + (int)c + " = " + count.get(c));
}
}
}

Идеальный вывод будет выглядеть примерно так:

000 NUL 4124435 001 SOH 0
002 STX 0
003 ETX 0
.....
253 ý 0
254 þ 0
255 ÿ 0

Определенно ценю любую помощь!


person Hart CO    schedule 04.01.2012    source источник
comment
И в чем конкретно проблема, с которой вы столкнулись? (например, как ваш фактический результат отличается от вашего идеального?)   -  person maerics    schedule 05.01.2012
comment
Не используйте catch(NullPointerException) для обработки случая, когда char отсутствует на карте. Проверьте, возвращает ли count.get(c) значение null вместо этого. Это намного легче читать, а также быстрее. Исключения для исключительных случаев.   -  person JB Nizet    schedule 05.01.2012
comment
Основная проблема заключается в применении этой логики к большому файлу, а не к короткой строке. Что касается вывода, мой кажется перемешанным, в идеале было бы заказать его. Спасибо за совет (NullPointerException), JB!   -  person Hart CO    schedule 05.01.2012
comment
Логика будет точно такой же. Просто используйте BufferedReader, обертывающий FileReader, и читайте файл char за char, изменяя карту для каждого char. Прочтите docs.oracle.com/javase/tutorial/essential/io/charstreams. .html. Чтобы отсортировать карту, используйте SortedMap, а не HashMap.   -  person JB Nizet    schedule 05.01.2012
comment
Отличная информация JB, не знаю, как пометить это как мое решение, но это все, что мне нужно, спасибо!   -  person Hart CO    schedule 05.01.2012
comment
В качестве альтернативы проверке на нуль (символ отсутствует на карте) вы можете предварительно поставить каждый символ со счетчиком 0 на карте. например for (char c=0; c<256; c++) map.put(c, Integer.valueOf(0));   -  person user949300    schedule 05.01.2012


Ответы (2)


Если вы обрабатываете только символы ASCII, т. е. в диапазоне 0-255, было бы проще просто иметь целочисленный (или, возможно, длинный) массив [256], а затем читать файл, по сути, символ в время (конечно, вы бы использовали буферизацию или NIO для скорости) и увеличиваете соответствующий бин.

Тем не менее, ваш код HashMap выглядит разумным, и я не уверен, в чем ваш вопрос или проблема ???

person user949300    schedule 04.01.2012
comment
Я не уверен, как читать файл по одному символу за раз, и я не был уверен, что метод HashMap будет работать для очень больших файлов (1 ГБ+). Довольно новое для этого, спасибо за отзыв! - person Hart CO; 05.01.2012
comment
Как также отметил @JB Niznet, ваши результаты не упорядочены, потому что HashMap не упорядочен. (или, по крайней мере, не так, как вы ожидаете). Он также описал, как читать по одному символу за раз при буферизации для повышения производительности. - person user949300; 05.01.2012

Если вы уверены, что будете иметь дело только с данными ASCII, будет гораздо реализовать это с помощью массива int[256], а не хэш-карты.

Что касается \r и \n, просто обращайтесь с ними так же, как с другими символами ниже пробела. (Возможно, вам также следует обращаться с пробелом, печатая его имя, а не сам символ.)

person Ted Hopp    schedule 04.01.2012