找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3221|回复: 1

论纯文本格式的文件恢复(本人最新研究成果)

[复制链接]

307

主题

228

回帖

7335

积分

用户组: 真·技术宅

UID
2
精华
76
威望
291 点
宅币
5585 个
贡献
253 次
宅之契约
0 份
在线时间
947 小时
注册时间
2014-1-25
发表于 2014-1-26 20:55:05 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
看看题目,可能会觉得,这个有点太简单了吧,全磁盘都是啊,其实不然,看似最简单的东西,想做好是很难的。
  首先,纯文本格式可以有很多后缀,比如java h cpp hpp c txt rtf 源代码基本上都是纯文本。如何区分呢,我看到有的软件应该是利用特定标志,比如Java的import h的include rtf的rtf 。这种文本的结束符是_T('\0') 因此很容易判断大小。不过区分后缀这个我并没做,因为我都把他们看成txt。
  其次,每种格式又有编码方式,比如最常用的UNICODE ANSI UTF-8 如何区分,如何在恢复的时候认为他们都是纯文本呢。
  再次,如果在磁盘上进行纯文本检索,搜到的数据势必是海量的,如何找到真正有用的也就是真正的用户文件而不是垃圾数据和无关数据呢。
  最后,如何保证高效性,因为很多数据都看似合法的,每簇都要进入txt的循环判断,如何能最大程度保证效率
  昨天针对这些问题我实现了一种比较优秀的方法,照代码讲解:

  1. BOOL GetComplexFileType(CONST FORMAT_DATA DiskInfo[MAX_FILESIGLEN])
  2. {  //此函数判断是否为合法纯文本文件,以及判断其编码方式
  3.         if(*(WORD*)DiskInfo == 0xFEFF)//如果是UNICODE_LITTLE_ENDIAN
  4.                 return TRUE;
  5.         else if(*(WORD*)DiskInfo == 0xFFFE)//如果是UNICODE_BIG_ENDIAN
  6.                 return TRUE;
  7.         else if((*(DWORD*)DiskInfo & 0xFFFFFF) == 0xBFBBEF)//如果是UTF_8
  8.                 return TRUE;
  9.         else
  10.         { //否则判断是否是ANSI编码
  11.                 //下面8行跳过无关字符
  12.                 if(*(WORD*)DiskInfo == '\n\r' || *DiskInfo == '\t')//'\n\r' == \r\n//换行的时候产生的字符是连着的\r+\n 制表符产生\t
  13.                 {
  14.                         do
  15.                         {
  16.                                 DiskInfo++;
  17.                         }
  18.                         while (*DiskInfo == '\n' || *DiskInfo == '\r' || *DiskInfo == '\t');
  19.                 }
  20.                 for(int i=0;i<64;i++)//64个字符大概有3行以上,如果3行都没有的话,恢复他干啥。。。
  21.                 {
  22.                         //这一句是我的精华所在,分析可打印的字符,你会发现除了\r\n\t以外,其他可打印字符ascii码值都在32以上,
  23.                         //因此这里使用移位运算
  24.                         BYTE bit1=(DiskInfo[0]>>5),bit2=(DiskInfo[1]>>5);//单个32-127(1-3) 或者 两个128-255(4-7)
  25.                         //ascii可能字符组合,这里简略说一下ANSI编码方式,英语字母 数字 普通符号都是一个字节的,范围是32-127(自己查ascii码表)
  26.                         //汉字 日本字和其他一些国家的字是2字节,且2字节的ascii码都是大于128的,知道了这个下面代码就好理解了
  27.                         if((bit1>=1 && bit1 <4) || DiskInfo[0] == '\r' || DiskInfo[0] == '\n' || DiskInfo[0] == '\t')//跳过单个合法字符
  28.                         {
  29.                                 DiskInfo++;
  30.                         }
  31.                         else if(bit1 >=4 && bit2 >=4)//跳过汉字
  32.                         {
  33.                                 DiskInfo+=2;
  34.                         }
  35.                         else//如果3行都没有的话,恢复他干啥。。。
  36.                                 return FALSE;
  37.                 }
  38.                 return TRUE;
  39.         }
  40.         return FALSE;
  41. }
  42. TEXT_FILE_FORMAT_API BOOL GetFileSig(PVOID pData)
  43. {
  44.         *(DWORD*)pData=(DWORD)GetComplexFileType;
  45.         return TRUE;
  46. }
  47. TEXT_FILE_FORMAT_API BOOL GetRawFileInfo(FORMAT_DATAPOINTER& pData,FORMAT_FILEINFO* pfileinfo)
  48. {
  49.         pfileinfo->bitmap=0;
  50.         pfileinfo->IsFileValid=FALSE;
  51.         FORMAT_DATA* DiskInfo=(FORMAT_DATA*)pData;
  52.         if(*(WORD*)DiskInfo == 0xFEFF || *(WORD*)DiskInfo == 0xFFFE)//UNICODE
  53.         {
  54.                 WORD* ptr=(WORD*)DiskInfo;
  55.                 while(*ptr++);
  56.                 pfileinfo->bitmap |= 0x01;
  57.                 pfileinfo->filesize=(BYTE*)ptr-(BYTE*)DiskInfo-2;
  58.                 pfileinfo->bitmap |= 0x08;
  59.                 if(*(WORD*)DiskInfo == 0xFEFF)
  60.                         strcpy_s(pfileinfo->Description,"UNICODE_LITTLE_ENDIAN_TXT");
  61.                 else
  62.                         strcpy_s(pfileinfo->Description,"UNICODE_BIG_ENDIAN_TXT");
  63.         }
  64.         else
  65.         {
  66.                 BYTE* ptr=(BYTE*)DiskInfo;
  67.                 while(*ptr++);
  68.                 pfileinfo->bitmap |= 0x01;
  69.                 pfileinfo->filesize=(BYTE*)ptr-(BYTE*)DiskInfo-1;
  70.                 pfileinfo->bitmap |= 0x08;
  71.                 if((*(DWORD*)DiskInfo & 0xFFFFFF) == 0xBFBBEF)
  72.                         strcpy_s(pfileinfo->Description,"UTF8_TXT");
  73.                 else
  74.                         strcpy_s(pfileinfo->Description,"ANSI_TXT");
  75.         }
  76.         pfileinfo->bitmap |= 0x04;
  77.         pfileinfo->IsFileValid=TRUE;
  78.         return TRUE;
  79. }
复制代码
回复

使用道具 举报

0

主题

19

回帖

51

积分

用户组: 小·技术宅

UID
158
精华
0
威望
1 点
宅币
30 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-3-26
发表于 2014-3-26 16:38:21 | 显示全部楼层
厉害。学习了
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-20 10:37 , Processed in 0.040387 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表