Как записать числа как 4-битные элементы в файл? - PullRequest
4 голосов
/ 28 ноября 2011

Я хочу сэкономить место при записи моих данных в файл.То есть я хочу хранить свои целые числа как полубайты (4 бита) только для каждой цифры.Я не могу написать числа в виде символов, так как это будет стоить один байт для каждой цифры (соответствующий код ASCII)

Я использую следующий код, чтобы избавиться от первой половины байта и записать только 4 бита:

String key= "1234567890"
char[] chars = key.toCharArray();
System.out.println(key+";");
dos.writeLong(l);
for ( int i = 0 ; i < chars.length ; i+= 2 ) {
    byte b1 = (byte) (chars[i] - (byte) '0');
    byte b2 = (byte) (i < chars.length-1 ? chars[i+1] - (byte) '0': 0xf);
    fos.write((byte) ((b1 << 4) | b2 ));

и этот код для чтения обратно:

String encoded = stt.nextToken( );
StringBuffer result = new StringBuffer();
byte[] buf = encoded.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
for ( int i = 0 ; i < 11 ; i++ ) {
    byte both = (byte) bais.read();
    byte b1 = (byte) ((both >> 4 ) & 0xf);
    byte b2 = (byte) (both  & 0xf) ;
    result.append( Character.forDigit(b1, 10));
    if ( b2 != 0xf ) {
        result.append(Character.forDigit(b2,10));
    }
}   

Это не работает.Как я могу улучшить это?

Ответы [ 3 ]

2 голосов
/ 28 ноября 2011

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

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

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

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

В двух словах: попробуйте и выберите тот, который лучше всего соответствует вашим потребностям.

2 голосов
/ 28 ноября 2011
  1. Во-первых, вы абсолютно уверены, что вам нужно это сделать? Дисковое пространство дешево. Вы должны работать буквально с миллиардами ценностей, прежде чем это того стоит. Даже если вы загружаете эти данные, мегабайты по сути тривиальны.
  2. Если вам нужно сделать это, самый простой способ - записать числа в удобном формате - даже в кодировке ASCII - и затем использовать сжатие, чтобы уменьшить размер. Эти методы почти наверняка дадут вам файл меньшего размера, чем все, что вы кодируете сами - иногда так и есть. Записать в выходной поток .zip или просто записать обычный файл и запустить утилиту сжатия, в зависимости от того, что проще.
  3. Если по какой-либо причине ни один из вариантов 1 или 2 не работает для вас, то ваш подход является правильным. Запишите два значения в байт, используя битовое смещение, а затем запишите байтовый массив.

Что касается того, почему ваш код не работает, вам нужно предоставить нам больше информации о том, что именно идет не так.

2 голосов
/ 28 ноября 2011

Сделав небольшое сжатие потока данных, я бы предложил другой подход: открыть поток вывода ZIP и записать в него свои полные данные. Алгоритм сжатия будет отвечать за удаление ненужных битов (включая те, которые вы не определили). В качестве бонуса ваш код будет легче читать.

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