上一个
下一个

C++如何按位写入数据到文件?

0.前言

在做数据结构课程设计的霍夫曼编码时,想起了老师课上说的一句话:

有的同学编码完了以后啊,原来一个字符比如说a,编码为了10011111,但是保存的时候不会写入了,结果编码完的文件比原来还长。

一开始我觉得哈哈哈还有这么蠢的人,结果发现蠢的人居然是我自己!想要按位写入文件可不是一件简单的事情哦。也许有的同学会觉得这有什么难的,不就是ios::binary吗,要是有这个想法的话只能说同学你的基本功不太扎实了。我们使用sizeof,f.write,f.read等函数时,传入的都是字节,不是比特。

也许有的人还会想那么我用bool会小一点,遗憾的bool是1个字节,char也是1个字节,很容易推断出的事实是一篇文章的字符编码不可能只有一个1或0。

下面给出一个测试代码,从这可以看出按位写入似乎是一件不那么简单的事了。

				
					fstream f1("1.txt",ios::out);
	fstream f2("2.bin",ios::out|ios::binary);
	fstream f3("3.bin",ios::out|ios::binary);
	cout<<sizeof(int)<<endl;
	cout<<sizeof(bool)<<endl;
	for(int i=0;i<257;i++)
	{
		f1<<1;
		int a=1;
		bool b=true;
		f2.write((char*)&a,sizeof(int));
		f3.write((char*)&b,sizeof(bool));
	}
	f1.close();
	f2.close();
	f3.close();
				
			

最后三个文件大小分别是:

1.txt     1kb,          2.bin     2kb,                 3.bin     1kb

网上有学长热心的分享了博客,也许你也看到过,但遗憾的是这位学长没有注意到这个问题,给出了“越压缩越长的答案”,网络上其他的答案写的也不是很清晰,方法也比较复杂。在这里我给出一个方案,我们可以看到虽然额外使用了大概27位到58位的空间,但是我们的确做到了按位写入文件。

事实上我们可以做的更好,极限情况下可以做到只额外使用2bit到9bit空间,但这是没有必要的,理论上兼顾代码可读性和空间使用率,8bit到15bit是合理的方案。

代码已经写完了,先占个坑,有空写完。

1.设计思路

既然我们无法直接对比特进行写入,那么很容易想到的一个事实是攒够1个字节一起写入,这样子会带来一个问题,我们无法得知有多少位是不需要的——这个问题是常见的,因为无法保证输入的信息正好是整数——我是指1024这样的整数。

所以我们将文件的第一块信息用于记录应该丢弃多少位的数据。

有了大概的思路就是写代码了,需要注意的是,写入信息后的处理以及读取数据的预读处理——因为C++的eof机制是要读到文件尾后再读一点。

我设计了两个类,一个是BitWriter,一个是BitReader,可以看到在这个设计规则下它们运行的很好。需要指出的是我使用了4个字节的int所以有一定空间浪费——不过4字节左右,所以为了代码可读性我还是这么做了。优化的方案可以使用short int等。

2.全部代码

老师要看数据结构课设,全部代码等1月左右上传。

订阅评论
提醒
0 评论
内联反馈
查看所有评论

《C++如何按位写入数据到文件?》

0
希望看到您的想法,请您发表评论x