2013-07-03 3 views
0

Я выполняю проект класса, который является алгоритмом хаффмана. После прочтения файла и создания кода huffman (1s & 0s) мне нужно экспортировать его в новый файл с помощью побитовых операций. По какой-то причине, когда я экспортирую с помощью побитовых операций, файл заканчивается даже больше, чем раньше. С строкой из 1s и 0s, представляющей предыдущие символы, используя поразрядные данные, я должен сохранять каждый 1 и 0 в цепочках по 8 бит. Это код, который у меня есть:Побитовые мудрые операции

byte currentByte = 0; 
for (int i = 0, j = 0; i < binaryString.length(); i++, j++) { 
    if (binaryString.charAt(i) == '1') { 
     currentByte |= (byte) Math.pow(2, 7 - j); 
    } 
    if (i != 0 && (i % 8 == 0 || i == binaryString.length() - 1)) { 
     output.writeObject(currentByte); 
     if (i % 8 == 0) { 
      currentByte = 0; 
      j = 0; 
     } 
    } 
} 

Спасибо.

ответ

0

Вы используете ObjectOutputStream, который предназначен для переносимости сериализации объектов Java. Если вы хотите написать одиночные байты, вместо этого вы должны использовать FileOutputStream.

0

Проблема заключается в том, что вы используете метод writeObject вместо метода write.

Метод writeObject записывает информацию об объекте, а также сам объект, где метод записи предназначен для простого написания одного байта.

Вы должны также использовать FileOutputStream вместо ObjectOutputStream.

См: ObjectStream.write(byte)

0
public static void main(String[] args) throws IOException 
{ 
    FileOutputStream output = new FileOutputStream("C:\\temp\\t.dat"); 
    String inp = "1100110000110011"; 
    byte[] ar = new byte[1]; 
    int b = 0; 
    int j = 0; 
    int i = 0; 
    while(i < inp.length()) 
    { 
     if(inp.charAt(i) == '1') 
      b |= 1 << (7-j); 

     j++; 
     i++; 
     if(i % 8 == 0) 
     { 
      //StringBuilder sb = new StringBuilder(); 
      //sb.append(String.format("%02X ", b)); 
      //System.out.print(sb.toString()); 
      ar[0] = (byte)b; 
      output.write(ar); 
      j = 0; 
      b = 0; 
     } 
    } 
    output.close(); 
} 

Если писать более длинные последовательности, Вы могли бы рассмотреть возможность использования List<byte>, а затем добавить каждый байт, вместо того, чтобы писать каждый байт seperatly.

0

Почему бы вам даже создать строку из 1 и 0 в первую очередь? Это бесполезный дополнительный шаг, который может занять дополнительное время.

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

Например, (не проверял, но я сделал это раньше)

int buffer = 0, bufbits = 0; 
for (int i = 0; i < symbols.length(); i++) 
{ 
    int s = symbols[i]; 
    buffer <<= lengths[s]; // make room for the bits 
    bufbits += lengths[s]; // buffer got longer 
    buffer |= values[s]; // put in the bits corresponding to the symbol 

    while (bufbits >= 8) // as long as there is at least a byte in the buffer 
    { 
     bufbits -= 8;  // forget it's there 
     stream.write((byte)(buffer >>> bufbits)); // and save it 
     // note: bits are not removed from the buffer, just forgotten about 
     // so it will "overflow", but that is harmless. 
     // you will see weird values in the debugger though 
    } 
} 

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

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

Использование 32 бит означает, что максимальная длина символа равна 32 - 7 = 25, что обычно больше, чем другие границы, уже размещенные на длине символа (обычно 15 или 16). Если вам нужно больше, максимальная длина символа с использованием long составляет 57. Очень длинные длины неудобны при декодировании (поскольку используются таблицы - никто не декодирует, по ходу дерева побито), поэтому обычно они не используются.

0

Вы должны изменить if положение:

public static void main(String[] args) { 
    String binaryString = "1111111100000010"; 
    byte currentByte = 0; 
    for (int i = 0, j = 0; i < binaryString.length(); i++, j++) { 
     if (i != 0 && i % 8 == 0 || i == binaryString.length() - 1) { 
      System.out.println(currentByte); // for debug 
      currentByte = 0; 
      j = 0; 
     } 
     if (binaryString.charAt(i) == '1') { 
      currentByte |= 1 << 7 - j; 
     } 
    } 
} 

Выход для двоичной строки:

1 
2 

Обратите внимание, что если у вас есть 11111111, это в byte типа -1.