技术0
经验159
魅力0
人气18
分享2
原创2
注册时间2023-1-5
最后登录2023-1-23
阅读权限15
在线时间5 小时
主题1
回帖14
初出茅庐
- 积分
- 238
- 人气
- 18
- 分享
- 2
|
楼主 |
发表于 2023-1-13 02:53:59
|
显示全部楼层
这次发一个压缩解压缩功能的代码,它使用了StoneValley库里边的Huffman Coding Tree。
源码由三部分组成:
1.svcompress.c
[C] 纯文本查看 复制代码
/*
* Name: svcompress.c
* Description: Compress files.
* Author: cosh.cage#hotmail.com
* File ID: 0120211637B0120211637L00208
* License: Public Domain.
*/
#include <stdlib.h>
#include <string.h>
#include "svcompress.h"
#include "svtree.h"
/* Buffer size incremental. */
#define INITIAL_BUFFER_SIZE (1024)
/* Magical number that used to distinguish file type. */
UCHART magicNumber[] = { 'S', 'V', 'C', 'F' };
/* SVCF_File_structure:_________________
* |Length: |Name: |
* |---------|-------------------------|
* |UCHART[4]|Magical number. |
* |UCHART |Platform integer length. |
* |UCHART |Symbol table length. |
* |N/A |Symbol table. |
* | | |
* |size_t |Compressed data length. |
* |UCHART |Remaining bits. |
* |N/A |Compressed data. |
* |_________|_________________________|
*/
/* Function name: svcCompressFile
* Description: Compress a file to a file.
* Parameters:
* fpout Pointer to the output file.
* fpin Pointer to the input file.
* Return value: Error code.
* Please refer to the SVCERROR enumeration at file 'svcompress.h'.
*/
SVCERROR svcCompressFile(FILE * fpout, FILE * fpin)
{
int c;
UCHART uc;
size_t i = 0, j, k;
P_BITSTREAM pbstm;
ARRAY_Z arrInBuffer, * parrTable = NULL;
SVCERROR rtn = SVC_NONE;
if (NULL == fpin || NULL == fpout)
return SVC_FILE_OPEN;
if (NULL == strInitArrayZ(&arrInBuffer, INITIAL_BUFFER_SIZE, sizeof(UCHART)))
return SVC_ALLOCATION;
/* Read fpin into buffer in the memory. */
while ((c = fgetc(fpin)) != EOF)
{
arrInBuffer.pdata[i] = (UCHART)c;
if (++i >= strLevelArrayZ(&arrInBuffer))
if (NULL == strResizeArrayZ(&arrInBuffer, strLevelArrayZ(&arrInBuffer) + INITIAL_BUFFER_SIZE, sizeof(UCHART)))
{
rtn = SVC_ALLOCATION;
goto Lbl_Compress_Error;
}
}
if (NULL == strResizeArrayZ(&arrInBuffer, i, sizeof(UCHART)))
{
rtn = SVC_ALLOCATION;
goto Lbl_Compress_Error;
}
/* Compress data. */
if (NULL == (pbstm = treHuffmanEncoding(&parrTable, arrInBuffer.pdata, i)))
{
rtn = SVC_COMPRESS;
goto Lbl_Compress_Error;
}
if (NULL == parrTable)
{ /* Can not output symbol table. */
strDeleteBitStream(pbstm);
rtn = SVC_COMPRESS;
goto Lbl_Compress_Error;
}
/* Free in-buffer-array. */
strFreeArrayZ(&arrInBuffer);
/*
{
P_BITSTREAM pbsout;
pbsout = treHuffmanDecoding(parrTable, pbstm);
strDeleteBitStream(pbsout);
}
*/
/* Write magical number. */
fwrite(magicNumber, sizeof magicNumber / sizeof magicNumber[0], sizeof magicNumber[0], fpout);
/* Write file header which is a UCHART variable that indicates platform integer length. */
uc = sizeof(size_t);
fwrite(&uc, sizeof uc, 1, fpout);
/* Write symbol table length. */
uc = (UCHART)parrTable->num;
fwrite(&uc, sizeof uc, 1, fpout);
/* Write symbol table. */
k = strLevelArrayZ(parrTable) * sizeof(HFM_SYMBOL);
for (j = 0; j < k; ++j)
fputc(parrTable->pdata[j], fpout);
/* Delete symbol table. */
strDeleteArrayZ(parrTable);
/* Write compressed data length. */
j = strLevelArrayZ(&(pbstm->arrz));
fwrite(&j, sizeof j, 1, fpout);
/* Write remaining bits. */
uc = (UCHART)pbstm->bilc;
fwrite(&uc, sizeof uc, 1, fpout);
/* Write compressed data. */
for (j = 0; j < strLevelArrayZ(&(pbstm->arrz)); ++j)
fputc(pbstm->arrz.pdata[j], fpout);
/* Cleanup. */
strDeleteBitStream(pbstm);
return SVC_NONE;
Lbl_Compress_Error:
fclose(fpin);
fclose(fpout);
strFreeArrayZ(&arrInBuffer);
return rtn;
}
/* Function name: svcDecompressFile
* Description: Decompress a file to a file.
* Parameters:
* fpout Pointer to the output file.
* fpin Pointer to the input file.
* Return value: Error code.
* Please refer to the SVCERROR enumeration at file 'svcompress.h'.
*/
SVCERROR svcDecompressFile(FILE * fpout, FILE * fpin)
{
int c;
UCHART uc;
size_t i, j, k;
P_ARRAY_Z parrTable;
BITSTREAM bsin, * pbsout;
UCHART magicBuffer[sizeof magicNumber / sizeof magicNumber[0]];
if (NULL == fpin || NULL == fpout)
return SVC_FILE_OPEN;
/* Read magical number. */
fread(magicBuffer, sizeof magicNumber[0], sizeof magicNumber / sizeof magicNumber[0], fpin);
if (0 != memcmp(magicBuffer, magicNumber, sizeof magicNumber))
return SVC_FILE_TYPE;
/* Read platform length. */
fread(&uc, sizeof(UCHART), 1, fpin);
if (sizeof(size_t) != (size_t)uc)
return SVC_PLATFORM;
/* Read symbol table length. */
fread(&uc, sizeof(UCHART), 1, fpin);
j = uc * sizeof(HFM_SYMBOL);
/* Read symbol table. */
parrTable = strCreateArrayZ(uc, sizeof(HFM_SYMBOL));
for (i = 0; i < j; ++i)
{
if ((c = fgetc(fpin)) == EOF)
{
strDeleteArrayZ(parrTable);
return SVC_FILE_TYPE;
}
parrTable->pdata[i] = (UCHART)c;
}
/* Read compressed data length. */
fread(&k, sizeof(size_t), 1, fpin);
/* Read remaining bits. */
fread(&uc, sizeof uc, 1, fpin);
bsin.bilc = (size_t)uc;
if (NULL == strInitArrayZ(&bsin.arrz, k, sizeof(UCHART)))
{
strDeleteArrayZ(parrTable);
return SVC_ALLOCATION;
}
/* Read compressed data. */
for (i = 0; i < k; ++i)
{
if ((c = fgetc(fpin)) == EOF)
{
strDeleteArrayZ(parrTable);
strFreeBitStream(&bsin);
return SVC_FILE_TYPE;
}
bsin.arrz.pdata[i] = (UCHART)c;
}
/* Decompress. */
if (NULL == (pbsout = treHuffmanDecoding(parrTable, &bsin)))
{
strDeleteArrayZ(parrTable);
strFreeBitStream(&bsin);
return SVC_DECOMPRESS;
}
/* Cleanup. */
strDeleteArrayZ(parrTable);
strFreeBitStream(&bsin);
/* Output result. */
for (i = 0; i < pbsout->arrz.num; ++i)
fputc(pbsout->arrz.pdata[i], fpout);
/* Cleanup. */
strDeleteBitStream(pbsout);
return SVC_NONE;
}
2.svcompress.h
[C] 纯文本查看 复制代码 /*
* Name: svcompress.h
* Description: Compress files.
* Author: cosh.cage#hotmail.com
* File ID: 0120211637A0120211640L00028
* License: Public Domain.
*/
#ifndef _SVCOMPRESS_H_
#define _SVCOMPRESS_H_
#include <stdio.h>
typedef enum en_SVCERROR {
SVC_NONE, /* No error. */
SVC_FILE_OPEN, /* File pointer is NULL. */
SVC_ALLOCATION, /* Allocation failure. */
SVC_COMPRESS, /* Compressing error. */
SVC_FILE_TYPE, /* Data file error. */
SVC_PLATFORM, /* Platform intger length mismatch. */
SVC_DECOMPRESS /* Decompressing error. */
} SVCERROR;
SVCERROR svcCompressFile (FILE * fpout, FILE * fpin);
SVCERROR svcDecompressFile(FILE * fpout, FILE * fpin);
#endif
3.test_svcf.c
[C] 纯文本查看 复制代码
/*
* Name: test_svcf.c
* Description: Launcher of compress/Decompress files.
* Author: cosh.cage#hotmail.com
* File ID: 0120211637C0120211656L00034
* License: Public Domain.
*/
#include <stdio.h>
#include <string.h>
#include "svcompress.h"
int main(int argc, char ** argv)
{
int i;
for (i = 0; i < argc; ++i)
{
if (0 == strcmp(argv[i], "-c") || 0 == strcmp(argv[i], "--compress"))
{
return svcCompressFile(stdout, stdin);
}
if (0 == strcmp(argv[i], "-d") || 0 == strcmp(argv[i], "--decompress"))
{
return svcDecompressFile(stdout, stdin);
}
if (0 == strcmp(argv[i], "-?") || 0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
{
printf("Usage:\n\tsvcf [-c|--compress] Compress stdin.\n\tsvcf [-d|--decompress] Decompress stdin as a svcf file.\n\tsvcf [-?|-h|--help] Show this help content.\n");
break;
}
}
return 0;
}
使用的时候将文件全部添加到StoneValley库内的src目录下,编译即可。
使用svcf -?命令查看svcf的使用方法。(注:svcf是StoneValley compress file的意思。)
在Linux/Unix平台下编译使用效果更佳。
|
|