- UID
- 2
- 精华
- 积分
- 7750
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
看看题目,可能会觉得,这个有点太简单了吧,全磁盘都是啊,其实不然,看似最简单的东西,想做好是很难的。
首先,纯文本格式可以有很多后缀,比如java h cpp hpp c txt rtf 源代码基本上都是纯文本。如何区分呢,我看到有的软件应该是利用特定标志,比如Java的import h的include rtf的rtf 。这种文本的结束符是_T('\0') 因此很容易判断大小。不过区分后缀这个我并没做,因为我都把他们看成txt。
其次,每种格式又有编码方式,比如最常用的UNICODE ANSI UTF-8 如何区分,如何在恢复的时候认为他们都是纯文本呢。
再次,如果在磁盘上进行纯文本检索,搜到的数据势必是海量的,如何找到真正有用的也就是真正的用户文件而不是垃圾数据和无关数据呢。
最后,如何保证高效性,因为很多数据都看似合法的,每簇都要进入txt的循环判断,如何能最大程度保证效率
昨天针对这些问题我实现了一种比较优秀的方法,照代码讲解:
- BOOL GetComplexFileType(CONST FORMAT_DATA DiskInfo[MAX_FILESIGLEN])
- { //此函数判断是否为合法纯文本文件,以及判断其编码方式
- if(*(WORD*)DiskInfo == 0xFEFF)//如果是UNICODE_LITTLE_ENDIAN
- return TRUE;
- else if(*(WORD*)DiskInfo == 0xFFFE)//如果是UNICODE_BIG_ENDIAN
- return TRUE;
- else if((*(DWORD*)DiskInfo & 0xFFFFFF) == 0xBFBBEF)//如果是UTF_8
- return TRUE;
- else
- { //否则判断是否是ANSI编码
- //下面8行跳过无关字符
- if(*(WORD*)DiskInfo == '\n\r' || *DiskInfo == '\t')//'\n\r' == \r\n//换行的时候产生的字符是连着的\r+\n 制表符产生\t
- {
- do
- {
- DiskInfo++;
- }
- while (*DiskInfo == '\n' || *DiskInfo == '\r' || *DiskInfo == '\t');
- }
- for(int i=0;i<64;i++)//64个字符大概有3行以上,如果3行都没有的话,恢复他干啥。。。
- {
- //这一句是我的精华所在,分析可打印的字符,你会发现除了\r\n\t以外,其他可打印字符ascii码值都在32以上,
- //因此这里使用移位运算
- BYTE bit1=(DiskInfo[0]>>5),bit2=(DiskInfo[1]>>5);//单个32-127(1-3) 或者 两个128-255(4-7)
- //ascii可能字符组合,这里简略说一下ANSI编码方式,英语字母 数字 普通符号都是一个字节的,范围是32-127(自己查ascii码表)
- //汉字 日本字和其他一些国家的字是2字节,且2字节的ascii码都是大于128的,知道了这个下面代码就好理解了
- if((bit1>=1 && bit1 <4) || DiskInfo[0] == '\r' || DiskInfo[0] == '\n' || DiskInfo[0] == '\t')//跳过单个合法字符
- {
- DiskInfo++;
- }
- else if(bit1 >=4 && bit2 >=4)//跳过汉字
- {
- DiskInfo+=2;
- }
- else//如果3行都没有的话,恢复他干啥。。。
- return FALSE;
- }
- return TRUE;
- }
- return FALSE;
- }
- TEXT_FILE_FORMAT_API BOOL GetFileSig(PVOID pData)
- {
- *(DWORD*)pData=(DWORD)GetComplexFileType;
- return TRUE;
- }
- TEXT_FILE_FORMAT_API BOOL GetRawFileInfo(FORMAT_DATAPOINTER& pData,FORMAT_FILEINFO* pfileinfo)
- {
- pfileinfo->bitmap=0;
- pfileinfo->IsFileValid=FALSE;
- FORMAT_DATA* DiskInfo=(FORMAT_DATA*)pData;
- if(*(WORD*)DiskInfo == 0xFEFF || *(WORD*)DiskInfo == 0xFFFE)//UNICODE
- {
- WORD* ptr=(WORD*)DiskInfo;
- while(*ptr++);
- pfileinfo->bitmap |= 0x01;
- pfileinfo->filesize=(BYTE*)ptr-(BYTE*)DiskInfo-2;
- pfileinfo->bitmap |= 0x08;
- if(*(WORD*)DiskInfo == 0xFEFF)
- strcpy_s(pfileinfo->Description,"UNICODE_LITTLE_ENDIAN_TXT");
- else
- strcpy_s(pfileinfo->Description,"UNICODE_BIG_ENDIAN_TXT");
- }
- else
- {
- BYTE* ptr=(BYTE*)DiskInfo;
- while(*ptr++);
- pfileinfo->bitmap |= 0x01;
- pfileinfo->filesize=(BYTE*)ptr-(BYTE*)DiskInfo-1;
- pfileinfo->bitmap |= 0x08;
- if((*(DWORD*)DiskInfo & 0xFFFFFF) == 0xBFBBEF)
- strcpy_s(pfileinfo->Description,"UTF8_TXT");
- else
- strcpy_s(pfileinfo->Description,"ANSI_TXT");
- }
- pfileinfo->bitmap |= 0x04;
- pfileinfo->IsFileValid=TRUE;
- return TRUE;
- }
复制代码 |
|