Продолжение. Первая
часть.
int BZ2_bzRead (int *bzerror, BZFILE *b, void *buf, int len);
Читает до len (восстановленных) байт из сжатого потока BZFILE *b в буфер void *buf. Если чтение прошло успешно, bzerror устанавливается в BZ_OK и функция возвращает число прочитанных байт. Если логический конец сжатого файла был достигнут, bzerror устанавливается в BZ_STREAM_END, и функция также возвращает число успешно прочитанных байт. Любые другие коды bzerror означают ошибку.
По такому поведению функции BZ2_bzRead можно определять, не закончился ли сжатый файл (если возвращённый функцией код меньше числа ожидаемых байт), но делать этого не рекомендуется: bzerror следует проверять после каждого вызова BZ2_bzRead (ровно как и после каждого вызова верхнеуровневого интерфейса).
На самом деле, BZ2_bzRead копирует данные из сжатого файла кусками по BZ_MAX_UNUSED байт перед тем, как восстановить их. Если логический конец сжатого потока был достигнут, bzerror устанавливается в BZ_SEQUENCE_END и, для того, чтобы собрать прочитанные, но не использованные остатки данных, необходимо вызвать функцию BZ2_bzReadGetUnused перед тем, как закрыть сжатый файл с помощью BZ2_bzReadClose.
void BZ2_bzReadGetUnused ( int *bzerror,
BZFILE *b,
void **unused,
int *nUnused );
Возвращает данные, которые были прочитаны из сжатого файла, но не потребовались для достижения логического конца сжатого потока. *unused устанавливается в адрес
считанных данных, а *nUnused - в число считанных байт. *nUnused может принимать значения от 0 до BZ_MAX_UNUSED включительно. Эта функция может быть вызвана лишь единожды и только в том случае, если BZ2_bzRead вернула
BZ_STREAM_END.
void BZ2_bzReadClose (int *bzerror, BZFILE *b);
Высвобождает все ресурсы, связанные с BZFILE *b. Эта функция не закрывает файл, связанный с BZFILE *b, и ты можешь делать с ним дальше всё что угодно. BZ2_bzReadClose должна быть вызвана после любой исключительной (ошибочной) ситуации.
BZFILE *BZ2_bzWriteOpen ( int *bzerror,
FILE *f,
int blockSize100k,
int verbosity,
int workfactor );
Эта функция совершает подготовку к чтению сжатых данных из файла FILE *f. f должен быть заранее открыт на чтение в двоичном режиме. Параметры blockSize100k, verbosity и workFactor были уже рассмотрены ранее. Вся память под необходимые последующие операции выделяется в этой функции, поэтому, BZ2_bzWrite не может возвратить
BZ_MEM_ERROR.
void BZ2_bzWrite (int *bzerror, BZFILE *b, void *buf, int len);
Поглощает len байт из буфера buf для того, чтобы они впоследствии были сжаты и сброшены в сжатый файл.
void BZ2_bzWriteClose ( int *bzerror,
BZFILE *f,
int abandon,
unsigned int *nbytes_in,
unsigned int *nbytes_out );
void BZ2_bzWriteClose64 (int *bzerror,
BZFILE *f,
int abandon,
unsigned int *nbytes_in_lo32,
unsigned int *nbytes_in_hi32,
unsigned int *nbytes_out_lo32,
unsigned int *nbytes_out_hi32 );
Обе эти функции сжимают и сбрасывают в BZFILE *f данные, собранные прежде вызовами BZ2_bzWrite. Дописывается признак логического конца сжатого потока и последующие вызовы BZ2_bzWrite недопустимы. Все ресурсы, занятые под BZFILE *f и связанные с ним структуры, освобождаются, но файловый дескриптор FILE *f, "на" котором был открыт BZFILE *f, не закрывается.
Если BZ2_bzWriteClose вызывается после возникновения ошибки, BZ2_bzWriteClose не делает ничего, кроме высвобождения занятых ресурсов. Ты можешь форсировать это поведение, если выставишь ненулевое значение в параметре abandon.
Если nbytes_in ненулевой, то, после возврата, *nbytes_in будет содержать
количество несжатых данных. Аналогичным образом, *nbytes_out будет содержать размер сжатых данных в байтах. Если ты хочешь получить 64-битные значения (для файлов более размеров более 4 гигабайт =))), то используй BZ2_bzWriteClose64.
Ниже приведен пример использования функций записи уровня high level interface:
FILE* f;
BZFILE* b;
int nBuf;
char buf[ /* whatever size you like */ ];
int bzerror;
int nWritten;
f = fopen ( "myfile.bz2", "w" );
if (!f) {
/* handle error */
}
b = BZ2_bzWriteOpen ( &bzerror, f, 9 );
if (bzerror != BZ_OK) {
BZ2_bzWriteClose ( b );
/* handle error */
}
while ( /* condition */ ) {
/* get data to write into buf, and set nBuf appropriately */
nWritten = BZ2_bzWrite ( &bzerror, b, buf, nBuf );
if (bzerror == BZ_IO_ERROR) {
BZ2_bzWriteClose ( &bzerror, b );
/* handle error */
}
}
BZ2_bzWriteClose ( &bzerror, b );
if (bzerror == BZ_IO_ERROR) {
/* handle error */
}
и чтения:
BZFILE* b;
int nBuf;
char buf[ /* whatever size you like */ ];
int bzerror;
int nWritten;
f = fopen ( "myfile.bz2", "r" );
if (!f) {
/* handle error */
}
b = BZ2_bzReadOpen ( &bzerror, f, 0, NULL, 0 );
if (bzerror != BZ_OK) {
BZ2_bzReadClose ( &bzerror, b );
/* handle error */
}
bzerror = BZ_OK;
while (bzerror == BZ_OK && /* arbitrary other conditions */) {
nBuf = BZ2_bzRead ( &bzerror, b, buf, /* size of buf */ );
if (bzerror == BZ_OK) {
/* do something with buf[0 .. nBuf-1] */
}
}
if (bzerror != BZ_STREAM_END) {
BZ2_bzReadClose ( &bzerror, b );
/* handle error */
} else {
BZ2_bzReadClose ( &bzerror );
}
LOW-LEVEL INTERFACE
Помимо вышеописанных, существуют шесть функций низкого уровня, BZ2_bzCompressInit, BZ2_bzCompress, BZ2_bzCompressEnd, BZ2_bzDecompressInit, BZ2_bzDecompress и BZ2_bzDecompressEnd. Я не буду здесь описывать эти функции и их возможности. Если ты решишь овладеть ими, то обратись к документации из комплекта libbzip2.