| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > Чары файлов |
| Автор: Platon 25.4.2006, 20:35 | ||
Я тут пытался реализовать метод сжатия LZ78 на моем любимом Java. Вроде все понятно, но проблемы, кажется, с сохранением в файл. Наверное, проблемы с переводом из класса Record в строку и обратно. Напомню людям, что каждая запись содержит номер записи, с которой начинается данная и символ, который к ней дописывается. Запись состоит из одного чара и 1-го int'а. Как понимаете, int в файл может записываться с разной длиной, а мне надо с фиксированой. Я выбрал 2 байта. Вот код:
Код работает для ультра-коротких файлов, и дает сбои со сравнительно средними файлами. Вероятно, это происходит из-за увеличения размера словаря. Если не сохранять в файл и раскодировать сразу из values, то все прекрасно для всех файлов умеренных размеров, а вот раскодировать архив уже не получается. |
| Автор: LSD 25.4.2006, 22:20 |
| С LZ78 я незнаком, поэтому пока объясни поподробней, что именно там происходит. Дело в том, что char это UTF-16, он хранит 65536 различных символов. А запись в файл идет в системной кодировке, как правило это однобайтовые кодировки, т.е. 256 символов. И подобное преобразование конечно не может пройти без потерь. Так что сам принцип сохранения не верен. |
| Автор: jimur 25.4.2006, 22:59 |
| А out.flush() не пробовал ставить? |
| Автор: LSD 25.4.2006, 23:02 |
close() - выполняет flush(). |
| Автор: jimur 25.4.2006, 23:07 | ||
|
| Автор: LSD 25.4.2006, 23:16 |
| Не понял. Ты предлагаешь вызвать именно flushBuffer() вместо flush()? И чем это поможет, если перед закрытием буффер все равно очищается? |
| Автор: jimur 25.4.2006, 23:35 | ||
| Предлагаю попробовать вызывать вместо out.close(); вызывать out.flush(); out.close(); выдержка из исходников в сочетании с приведенными выше фрагментами объясняет почему
|
| Автор: Platon 26.4.2006, 06:07 |
| Ээээ, люди со flush() и close() все отлично, дело в другом. LSD, значит с байтами. А я чего-то не пойму, ведь смотрю в архивный файл и вижу все нормально: 1 байт под символ, 2 байта под int. И как-бы чары и без этого жмутся в 1 байт. А с байтами очень уж неудобно работать. Ну, это не очень важно, но если требуешь попробую объяснить: В общем начинаем. Фраза, записываемая в файл, будет состоять из 3-х байт: 1 под символ, 2 под число. В методе есть строчный вектор словарь и фразный вектор значения. Каждый цикл считываем по 1-му чару. И прибавляем его к исследуемой строке curString. Ищем эту строку в словаре, если она есть, то запоминаем номер ее позиции, если нет, надо занести в словарь и добавить новую запись с последним прочитанным символом и позицией последней совпавшей строки. Фу... вроде ничего не упустил, правда пока не проверял, но хвост может оставаться, я там такую пришпандорку сделал. Прошу прощения за бестактный вопрос, но как байты то в BufferedWriter записывать? |
| Автор: jimur 26.4.2006, 06:22 | ||
дак он для этого не предназначен - он для чаров. |
| Автор: Platon 26.4.2006, 08:16 |
| Так. Я выяснил в чем ошибка. Проблема в том, что выражение return new Record(str[0], ((int)str[1] << 8) | str[2]); работает некорректно. В случае когда int равен 128 оно естественно представляется в виде 0x0080 в двухбайтной системе. Хе а когда обратно перевожу у меня два байта один равен нулю, а второй -128, второй приводится к int, причем знак сохраняется!!! И получается все равно -128 вместо 128. Козалось бы чего сложного. В С++ это решается просто, а в Java как? |
| Автор: Platon 26.4.2006, 20:27 | ||
Тупейшим образом решил свою проблему:
Как проще-то? |
| Автор: jimur 27.4.2006, 06:53 | ||
Да, согласен, при работе с FileWriter'ом достаточно close(). |
| Автор: Platon 27.4.2006, 08:14 | ||
LSD, да согласен уже перешел. Но загвоздка в переводе 2-х байтов в int. Я решил ее одним методом, но уж больно кривенький он. Неужели в Java нет unsigned byte?
Добавлено @ 08:15 И еще. Можно ли порции битов из файла читать? Или свой класс разрабатывать? |
| Автор: batigoal 27.4.2006, 10:00 |
Нет, беззнаковых типов нету. |
| Автор: Platon 27.4.2006, 10:50 |
| Lamer George, и что? Мне в таком же духе продолжать? |
| Автор: LSD 29.4.2006, 12:00 | ||||||||
Очень странный код... 1. Ты делаешь из byte - char, при этом расширение будет знаковое. Т.е. для ASCII кодов (0-127) у тебя будет вполне осмысленный результат. А вот для кодов более 127 будет фигня, например byte - 0xFF, будет преобразован в char - \uFFF3 - которй вообще непонятно какой символ дает. char - предназначен для хранения символов, если тебе нужно читать символы из файла используй CharsetDecoder. А если нет, то используй просто byte, short или int. 2. Затем вот эта странная конструкция:
ее смысл я вообще не понял. Если тебе надо прочитать байты в int то делай так:
для big-endian и
для little-endian |