通过二维码传输少量文本文件

本文介绍了一种通过将文档压缩并转换为二维码来实现信息传递的方法。首先使用WinRAR压缩原始文件,接着将压缩后的文件转换为ASCII字符表示,以便生成二维码。文章提供了编码和解码的C/C++代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果公司电脑所有接口都锁上了,如何能传出一些文档呢?手抄?拍照后再文字识别?都不方便,要是能将文档转成二维码,扫描的结果再转成文档就方便了些。

一 思路

二维码能传输的信息量是很少的,直接将文档内容转成二维码很不现实,所以先用WinRAR对原文件进行压缩。
然后需要将rar转换成可打印字符,一个汉字的二维码比两个ascii字符的二维码复杂,这里考虑将rar转成可打印的ascii字符。标准ascii里有95个可打印字符,那就选64个,可表示6个比特位。

编码前编码后
6个比特位1个字符
24个比特位/3个字节4个字符

二 编码

将rar文件转换为可打印字符的代码:

// encode.c
// input: src.rar output: dest.txt
#include <stdio.h>
#include <string.h>

const unsigned char table[]=
{
	'0','1','2','3','4','5','6','7','8','9','<','>',
	'A','B','C','D','E','F','G','H','I','J','K','L','M',
	'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
	'a','b','c','d','e','f','g','h','i','j','k','l','m',
	'n','o','p','q','r','s','t','u','v','w','x','y','z'
};

// 当到达文件尾不足3个字符时, 末尾补0, 最多会有2个空字符, 对rar文件无影响
int read3chars(FILE *fin, unsigned char *re)
{
	int t;
	unsigned char buf[3];
	memset(buf, 0, 3*sizeof(unsigned char));

	t = fgetc(fin);
	if(t == EOF) return -1;
	buf[0] = t;
	t = fgetc(fin);
	if(t == EOF) goto last;
	buf[1] = t;
	t = fgetc(fin);
	if(t == EOF) goto last;
	buf[2] = t;

	unsigned char a,b,c,d;
last:
	a = (buf[0]&0xFC)>>2;
	b = (buf[0]&0x03)<<4 | (buf[1]&0xF0)>>4;
	c = (buf[1]&0x0F)<<2 | buf[2]>>6;
	d = buf[2]&0x3F;
	re[0] = table[a];
	re[1] = table[b];
	re[2] = table[c];
	re[3] = table[d];

	return 0;
}

int main()
{
	FILE *fin = fopen("src.rar", "rb");
	if(fin == NULL)
	{
		puts("cann't open src.rar!");
		getchar();
		return -1;
	}
	FILE *fout = fopen("dest.txt", "w");
	for(;;)
	{
		unsigned char buf[4];
		int ret = read3chars(fin, buf);
		if(ret != 0) break;
		fputc(buf[0], fout);
		fputc(buf[1], fout);
		fputc(buf[2], fout);
		fputc(buf[3], fout);
	}
	fclose(fin);
	fclose(fout);
	return 0;
}

三 解码

如果用记事本编辑文本文件,可能会出现BOM字符,这里并没有对其进行特殊处理。

// decode.cpp
// input: dest.txt output: dest.rar
#include <cstdio>
#include <map>

const char table[]=
{
	'0','1','2','3','4','5','6','7','8','9','<','>',
	'A','B','C','D','E','F','G','H','I','J','K','L','M',
	'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
	'a','b','c','d','e','f','g','h','i','j','k','l','m',
	'n','o','p','q','r','s','t','u','v','w','x','y','z'
};
std::map<unsigned char, unsigned char> retable;

// 一定是4字节的整数倍
int read4chars(FILE *fin, unsigned char *ret)
{
	unsigned char buf[4];
	int t = fgetc(fin);
	if(t == EOF) return -1;
	buf[0] = t;
	buf[1] = fgetc(fin);
	buf[2] = fgetc(fin);
	buf[3] = fgetc(fin);

	unsigned char a = retable[buf[0]];
	unsigned char b = retable[buf[1]];
	unsigned char c = retable[buf[2]];
	unsigned char d = retable[buf[3]];
	ret[0] = a<<2 | b>>4;
	ret[1] = b<<4 | c>>2;
	ret[2] = c<<6 | d;

	return 0;
}

int main()
{
	for(unsigned char i=0; i<64; ++i)
		retable[table[i]] = i;

	FILE *fin = fopen("dest.txt", "r");
	if(fin == NULL)
	{
		puts("cann't open dest.txt!");
		getchar();
		return -1;
	}
	FILE *fout = fopen("dest.rar", "wb");
	for(;;)
	{
		unsigned char buf[3];
		int res = read4chars(fin, buf);
		if(res != 0) break;
		fputc(buf[0], fout);
		fputc(buf[1], fout);
		fputc(buf[2], fout);
	}

	fclose(fin);
	fclose(fout);
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值