我有一些C代碼將ASCII字符串存儲在內存中,其長度爲4個字節,後面跟着字符串。字符串長度在10-250字節範圍內。C中的ASCII字符串的壓縮
爲了減少佔用率,我希望逐個壓縮每個字符串,仍然存儲壓縮字符串的長度(壓縮字符串的長度)。
我不想在比單個字符串更大的範圍壓縮,因爲任何字符串都可以隨時讀取/寫入。
什麼庫/算法可用於做到這一點?
感謝您的幫助。 NickB
我有一些C代碼將ASCII字符串存儲在內存中,其長度爲4個字節,後面跟着字符串。字符串長度在10-250字節範圍內。C中的ASCII字符串的壓縮
爲了減少佔用率,我希望逐個壓縮每個字符串,仍然存儲壓縮字符串的長度(壓縮字符串的長度)。
我不想在比單個字符串更大的範圍壓縮,因爲任何字符串都可以隨時讀取/寫入。
什麼庫/算法可用於做到這一點?
感謝您的幫助。 NickB
ZLib始終爲您服務 - 當字符串包含不可壓縮的數據時,它的開銷很小,它相對快速,免費且可以輕鬆集成到C和C++程序中。
Zlib絕對是您的朋友,但請務必執行一些測試來檢測壓縮開始有益的平均字符串長度,因爲壓縮標題的開銷很小。
例如,您可能會發現,在20個字符以下,壓縮字符串實際上更大,因此只能壓縮更長的字符串。
爲什麼在字符串長度爲10-250字節時使用4字節長度,使用1字節長度可以爲每個字符串單獨保存3個字節。
只是數據文本,即0-9 A-Z或某些子集?如果是這樣的話,重新編碼它以使用該子集並保存每個字符幾位。
現在看看霍夫曼編碼部分和lempel-zev部分中的http://gnosis.cx/publish/programming/compression_primer.html。
這應該讓你開始。
我不確定zlib或LZW壓縮方法在個別壓縮小於250字節的短字符串的情況下可以正常工作。兩者通常都需要創建一個相當大的字典,才能看到顯着的壓縮增益。
也許簡單的霍夫曼編碼與一個固定的編碼樹,或一個字符串的所有實例之間共享?另外,你是否看到過80年代用於在內存受限的微型計算機上壓縮短串的ZSCII編碼?
大多數壓縮算法不短字符串工作得很好。 下面是一些壓縮算法,旨在壓縮短英文文本字符串。 雖然它們可以處理任何明文字符串中的任意字節,但這些字節通常使「壓縮」數據比明文長。 因此,壓縮機不改變地存儲「不可壓縮」數據,並在這些數據上設置一個「文字」標誌(如Steve Jessop建議的)。
當使用多個字符串這樣有可能通過與\0
S(1個字節)一起串接它們並使用查找功能,以避免爲每個串(每個4或8個字節)的指針開銷。
#include <stdio.h>
static const char strings[]="hello\0world\0test";
char * nthstring(const char *s, unsigned n){
while(n--)
while(*s++)
;
return s;
}
int main(void) {
printf("%s\n",nthstring(strings,1));
return 0;
}
但是如果字符串長度小於UCHAR_MAX您可以用零字節佔位存儲長度(加上開頭加1),這將花費只有1個額外的數據字節優化查找,但節省了大量條件跳轉和增量查找功能。
#include <stdio.h>
/* each "string" is prefixed with its octal length */
static const char lenstrings[]="\05hello\05world\04test";
char * ithstring(const char *s, unsigned n){
while(n--){
s+=*s+1;
}
return s;
}
int main(void) {
char *s=ithstring(lenstrings,1);
/* use the length because we don't have terminating \0 */
printf ("%.*s",(unsigned char)*s,s+1);
//write(1,s+1,(unsigned char)*s); //POSIX variation via <unistd.h>
return 0;
}
對於這兩種變化,最好先保留最常用的字符串;但是,只要將長度分隔符調整爲壓縮長度,第二種方法將允許您使用壓縮數據(挑選最適合您數據的數據 - David Cary's answer包含可行解決方案列表)。
注:爲了獲得最大的壓縮超出標準的壓縮機,你可能會需要修改他們的頭的長度字段是unsigned char
(或unsigned short
如果字符串長度超過256個,但不是65536字節),因爲大多數人都會嘗試以支持大文件的壓縮(這可以節省每個字符串3-7個字節)
如果您可以備份大小字段的1位來標記字符串是否被壓縮,那麼您甚至不必猜測:只是試圖壓縮每個字符串。如果它變小,請將其壓縮。如果沒有,請將其存儲爲未壓縮。這大概是PKZIP允許的(並且我假定其他壓縮容器,它只是我碰巧實現過的一個PKZIP)。不幸的是,大小範圍10-250不能有效地承認8位體系結構上的「備用」位。 – 2009-07-08 10:39:37