LZW 文本压缩及解压

LZW就是通过建立一个字符串表,用较短的代码来表示较长的字符串来实现压缩。

压缩算法如下

#include <iostream>
#include <fstream>

std::ifstream fin;
std::ofstream fout;
using namespace std;

const int D = 4096,
		alpha = 256,
		ByteSize = 8,
		HalfByte = 4,
		AllBit = 255,
		HalfBit = 15;
int used, state = 0;
char LastChar, LeftHalf;
unsigned long outch;
struct
{
	long int code;
}ht[D];
bool search(long int cd, int& tk)
{
	for (int i = 0; i < used; i++)
		if (ht[i].code == cd)
		{
			tk = i;
			return true;
		}
	return false;
}
bool openfile()
{
	fin.open("123.txt", std::ios_base::binary);
	fout.open("123.lzw", std::ios_base::binary | std::ios_base::out);
	if (fin.fail() || fout.fail())
		return false;
	else
		return true;
}
void output(long val)
{
	unsigned char ch, ck;
	if (state)
	{
		ch = (val >> ByteSize & HalfBit) | (LeftHalf << HalfByte);
		ck = val & AllBit;

		fout.put(ch);
		fout.put(ck);
		state = 0;
	}
	else
	{
		ch = val >> HalfByte;
		fout.put(ch);

		LeftHalf = val & HalfBit;
		state = 1;
	}
}
void compress()
{
	int i;
	for (i = 0; i < alpha; i++)	//用256个字符进行初始化
		ht[i].code = i;
	used = alpha; //已使用

	char ch;
	unsigned long cd, pcode;
	int tk;
	fin.get(ch);
	pcode = ch;
	while(!fin.eof())
	{
		fin.get(ch);

		cd = (pcode << ByteSize) + (unsigned char)ch;
		if (fin.eof())
		{
			//break;
		}
		if (search(cd, tk))
		{
			pcode = tk;
		}
		else
		{
			output(pcode);
			if (used < D)
			{
				ht[used].code = (pcode << ByteSize | ((unsigned)ch));
				used++;
			}
			pcode = ch;
		}
	}
	output(pcode);
	if (state)
	{
		cout <<"error\n";
		ch = LeftHalf << HalfByte;
		fout.put(ch);
	}
}
int main()
{

	if (openfile())
		cout <<"file ready!\n";
	compress();
	cout <<"ok\n";
	int i;
	/*
	for (i = 0; i < 256; i++)
		cout <<i <<"\t"<< ht[i].key <<"\t" <<char(ht[i].code) <<endl;
		*/
	for (i = 256; i < used; i++)
		//cout <<i  <<"\t" <<(ht[i].code>>8) <<"  "<<char(ht[(ht[i].code>>8)].code)<<"  "<<char(ht[i].code & AllBit) <<endl;
	fin.close();
	fout.close();
	return 0;
}

解压算法如下

hashlist.h

/********************************************************************
    purpose:    链表散列
    author:     xianyun1230
    QQ:         836663997
    e-mail:     [email protected]
    created:    2014/02/23
*********************************************************************/
template<typename K, typename T>
class hashlist
{
	public:
		hashlist(int num);
		~hashlist();
		bool search(const K k, T& val);
		bool insert(const K k, T val);
		bool del(const K k);
		void show()const;
	private:
		typedef struct _node
		{
			K key;
			T data;
			struct _node *next;
		}node;
		node* hsearch(K k);
		int D;
		node **lst;
};
template<typename K, typename T>
hashlist<K,T>::hashlist(int num)
{
	D = num;
	lst = new node *[D];
	for (int i = 0; i < D; i++)
	{
		lst[i] = new node;
		lst[i]->next = NULL;
	}
}
template<typename K, typename T>
hashlist<K,T>::~hashlist()
{
	node *tmp, *ph;
	for (int i = 0; i < D; ++i)
	{
		tmp = lst[i]->next;
		while (tmp)
		{
			ph = tmp->next;
			delete tmp;
			tmp = ph;
		}
		delete lst[i];
	}
	delete lst;
}
template<typename K, typename T>
hashlist<K,T>::node* hashlist<K,T>::hsearch(K k)
{
	node *tmp = lst[k % D];
	while(tmp->next)
	{
		if (tmp->next->key == k)
			return tmp;
		tmp = tmp->next;
	}
	return tmp;
}
template<typename K, typename T>
bool hashlist<K,T>::search(const K k, T& val)
{
	node* pt = hsearch(k);
	if (pt->next == NULL)
		return false;
	if (pt->next->key == k)
	{
		val = pt->next->data;
		return true;
	}
	else
		return false;
}
template<typename K, typename T>
bool hashlist<K,T>::insert(const K k,T val)
{
	node* pt = hsearch(k);
	if (pt)
	{
		node* tmp = new node;
		tmp->key = k;
		tmp->data = val;
		tmp->next = pt->next;
		pt->next = tmp;
		return true;
	}
	return false;
}
template<typename K, typename T>
bool hashlist<K,T>::del(const K k)
{
	node* pt = hsearch(k);
	if (pt->next != NULL)
	{
		node* tmp = pt->next;
		pt->next = tmp->next;
		delete tmp;
		if (pt == lst[k%D])
			pt->next = NULL;
		return true;
	}
	return false;
}
template<typename K, typename T>
void hashlist<K,T>::show() const
{
	node* tmp;
	for (int i = 0; i < D; ++i)
	{
		tmp = lst[i]->next;
		while (tmp)
		{
			std::cout <<tmp->data <<"  ";
			tmp = tmp->next;
		}
	}
	std::cout <<std::endl;
}

main.cpp

#include <iostream>
#include <fstream>
#include "hashlist.h"

std::ifstream fin;
std::ofstream fout;

const int D = 4096,
		alpha = 256,
		ByteSize = 8,
		HalfByte = 4,
		AllBit = 255,
		HalfBit = 15;
int used, state = 0;
char LastChar, LeftHalf;
unsigned long outch;
char s[D];
int slen;
struct
{
	int pre;
	char ch;
}ht[D];

bool openfile()
{
	fin.open("123.lzw", std::ios_base::binary);
	fout.open("123-lzw.txt", std::ios_base::binary | std::ios_base::out);
	if (fin.fail() || fout.fail())
		return false;
	else
		return true;
}
bool getcode(int &code)
{
	char tch, tck;
	unsigned char ch, ck;
	fin.get(tch);
	ch = tch;
	if (fin.eof())
		return false;
	code = ch;
	if (state)
	{
		code = (LeftHalf << ByteSize) | ch;
		state = 0;
	}
	else
	{
		fin.get(tck);
		//if (fin.eof())
		//	return false;
		ck = tck;
		code = (code << HalfByte) | (ck >> HalfByte);
		LeftHalf = ck & HalfBit;
		state = 1;
	}
	return true;
}
void output(int code)
{
	slen = -1;
	while (code >= alpha)
	{
		s[++slen] = ht[code].ch;
		code = ht[code].pre;
	}
	s[++slen] = code;
	for (int i = slen; i >= 0; --i)
		fout.put(s[i]);
}
void decompress()
{
	int i, pcode, ccode;
	for (i = 0; i < alpha; i++)	//用256个字符进行初始化
		ht[i].ch = i;
	used = alpha; //已使用

	if (getcode(pcode))
	{
		s[0] = pcode;
		fout.put(s[0]);
		slen = 0;

		while (getcode(ccode))
		{
			if (ccode < used)
			{
				output(ccode);
				if (ccode < D)
				{
					ht[used].pre = pcode;
					ht[used].ch = s[slen];
					used++;
				}
			}
			else
			{
				ht[used].pre = pcode;
				ht[used].ch = s[slen];
				used++;
				output(ccode);
			}
			pcode = ccode;
		}
	}
}
int main()
{
	using namespace std;
	if (openfile())
		cout <<"file ready!\n";
	decompress();
	cout <<"ok\n";
	for (int i = 0; i < used; i++)
		cout <<i <<"\t"<< ht[i].pre <<" "<<ht[ht[i].pre].ch<<" " <<ht[i].ch <<endl;
	fin.close();
	fout.close();
	return 0;
}

另外这段代码疑似有些错误,此代码仅供大家参考使用,同时也希望各路大神能给与指导~

时间: 2024-08-01 18:42:40

LZW 文本压缩及解压的相关文章

shell脚本中if与case使用,查找文件locate与find的使用,压缩,解压及归档工具

shell脚本中if与case使用 查找文件locate与find的使用 压缩,解压及归档工具 执行的循序  顺序执行  选择执行  循环执行 条件语句if if只是一个有含义的词,不能单独作为指令使用. 单分支 if 条件判断:then 条件为真的分支代码 fi 双分支 if 判断条件:then 条件为真的分支代码 else 条件为假的分支代码 fi 多分支 if 判断条件1, if-true elif 判断条件2,then if-ture elif 判断条件3,then if-ture ..

Zip 压缩、解压技术在 HTML5 浏览器中的应用

JSZip 是一款可以创建.读取.修改 .zip 文件的 javaScript 工具.在 web 应用中,免不了需要从 web 服务器中获取资源,如果可以将所有的资源都合并到一个 .zip 文件中,这时候只需要做一次请求,这样既减少了服务器的压力,同时也可以加快 web 应用的呈现速度. 今天就来探讨下 JSZip 如何与 HT 拓扑应用结合.先来看看这期 Demo 的效果图: 第一步.需要将应用对相关资源打包成 .zip 文件, 这是我要压缩的文件列表,把响应的资源文件存放到对应的文件夹下,然

HttpClient与APS.NET Web API:请求内容的压缩与解压

首先说明一下,这里的压缩与解压不是通常所说的http compression——那是响应内容在服务端压缩.在客户端解压,而这里是请求内容在客户端压缩.在服务端解压. 对于响应内容的压缩,一般Web服务器(比如IIS)都提供了内置支持,只需在请求头中包含 Accept-Encoding: gzip, deflate ,客户端浏览器与HttpClient都提供了内置的解压支持.HttpClient中启用这个压缩的代码如下: var httpClient = new HttpClient(new Ht

WP移动设备压缩与解压控件Xceed Zip for .NET Compact Framework控件下载及详细介绍使用方法

Xceed Zip for .NET Compact Framework 控件是一款健全的文件压缩和解压缩控件,提供了灵活的ZIP.gZip.流压缩,分割和合并ZIP,创建自定义解压文件. 具体功能: 完全支持.NET Compact Framework 2.0以及以上 100%可管理的代码,由C#编写,面向对象设计 支持在硬盘.内存.FTP站点里创建新的ZIP文件,或者更新存在的ZIP文件 完全兼容WinZip12,支持LZMA算法 支持Zip64 Zip文件格式,对文件大小没有限制 支持从硬

PAT 1078. 字符串压缩与解压

PAT 1078. 字符串压缩与解压 文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示.例如 ccccc 就用 5c 来表示.如果字符没有重复,就原样输出.例如 aba 压缩后仍然是 aba. 解压方法就是反过来,把形如 5c 这样的表示恢复为 ccccc. 本题需要你根据压缩或解压的要求,对给定字符串进行处理.这里我们简单地假设原始字符串是完全由英文字母和空格组成的非空字符串. 输入格式: 输入第一行给出一个字符,如果

PAT Basic 1078 字符串压缩与解压 (20 分)

文本压缩有很多种方法,这里我们只考虑最简单的一种:把由相同字符组成的一个连续的片段用这个字符和片段中含有这个字符的个数来表示.例如 ccccc 就用 5c 来表示.如果字符没有重复,就原样输出.例如 aba 压缩后仍然是 aba. 解压方法就是反过来,把形如 5c 这样的表示恢复为 ccccc. 本题需要你根据压缩或解压的要求,对给定字符串进行处理.这里我们简单地假设原始字符串是完全由英文字母和空格组成的非空字符串. 输入格式: 输入第一行给出一个字符,如果是 C 就表示下面的字符串需要被压缩:

Linux简单介绍与基本使用(文件操作、压缩与解压、常用shell命令)

文件管理(查找+操作) 使用图形界面 使用文本命令行 精确查找 查找find命令,递归的方式在目录下面层次查找 find 查找路径  [ 命令选项 ] [ 动作 ] 常用命令选项 按文件属性查找命令选项 -name 按文件名查找,区分大小写 -iname 按文件名查找,不区分大小写 -empty 查找空文件或目录 -maxdepth 查找最大深度 /第一级 /var/tmp/ 就是三级 / var tmp -mindepth 从哪个深度开始查找 /var 第二级 -perm 文件权限 比如477

linux中常用的压缩、解压命令详解

不管在windows中还是在linux中,我们会经常看到各种压缩的文件,此刻我们需要使用就得解压,在这就介绍介绍linux中解压.压缩的命令. 在做实验之前,我们先创建几个文件,大小都是100M,方便我们更能清晰理解. 一.compress[选项]file(不是太常用,而且tab键还不能补齐) ①compress file 压缩文件,其中我们可以看到compress压缩的文件是.Z结尾的压缩包. ② -d file 解压文件,但压缩文件会丢失,相当于uncompress 在这我们可以看到,不管是

iOS开发中的压缩以及解压

事实上,在iOS开发中,压缩与解压,我都是采用第三方框架SSZipArchive实现的 gitHub地址:   https://github.com/ZipArchive/ZipArchive 上面有详细的使用方法 因为ZipArchive不支持ARC,所以如果你的工程开启了ARC,那么就需要对ZipArchive设置一下.在ZipArchive.mm编译选项中,增加-fno-objc-arc即可. 最后,需要为工程链接libz.dylib动态链接库. 使用示范(压缩): // 获得mainBu