chinajoy上的照片有一半挂掉了,无法读取,我的相机基本还是全新的,这让我很不爽。而copy照片的时候,我用chkdsk查了下记忆卡,当我发现记忆卡被写,知道这下sb了。然后开始恢复数据。
找了好多软件,EasyRecovery 易我数据恢复一类的,结果100多张照片大概只恢复了10张。其中易我数据恢复这个软件恢复出一堆无用文件,我怀疑是文件表挂掉了。
查了下jpg文件格式,JPEG的每个标记都是由 2个字节组成,其前一个字节是固定值0xFF。每个标记之前还可以添加数目不限的0xFF填充字节(fill byte)。而图像开始标记是0xD8。也就是文件开始标记SOI是0xFFD8,而那些无用文件开头使一些无用的数据,基本没规律可言。后来我无意中发现在这些无用文件中间有SOI标记,也就是这些文件是前一张照片的后半部分和后一张照片的前半部分拼接成的。那么这就很简单,把文件重新拼接一下,果然就能正常显示。但我发现这却是已有的照片。
既然软件不管用,那么我准备自己写个程序来恢复数据。先把记忆卡做成一个磁盘映像文件,然后查找0xFFD8 FFE1(jpg文件开头4位数据),然后查找0xFFD9(文件结束标记),这两个标记中间的就是jpg文件。注意0xFFD9有2个,FIF应用数据块APPn(开始标记0xFFEn,n为0到F)结束的地方有个0xFFD9标记。结果发现恢复的照片和用EasyRecovery恢复的一样,因为程序算法有点小问题,恢复的照片还少了几张。我还不死心,查找照片EXIF信息中的拍照时间,结果还是一样,有3个小时的照片数据丢失。
我觉得虽然chkdsk写了记忆卡,但可能本来记忆卡上的数据就已经破坏了,应该是接触不良。唉,奥林巴斯,实在是太烂了。
程序代码,在边界处理上有些问题,也懒得改了。
#include <iostream.h> #include <fstream.h> #define BUF_SIZE 1024 * 100//buff要小于照片大小 #define OFFSET 4 void main() { ifstream datafile; ofstream* jpg; int file_no = 0; char name[32]; char buf[BUF_SIZE]; int i = 0; int tmp[BUF_SIZE]; bool find_ffd8ffe1 = false;//文件头 bool open_status = false;//文件打开标记 int ffd8ffe1_num; bool find_ffd9ffdb = false;//第一个0xffd9标记 int ffd9ffdb_num; bool find_ffd9 = false;//文件结束标记 int ffd9_num; int j = 0; // char * str; //short int int_buf [BUF_SIZE / 2]; datafile.open("e://pic.img",ios::in|ios::binary); //打开磁盘映像 if(datafile.fail()) { cout<<"Open File Failed."<<endl; return ; } // while(!datafile.eof()) while(j < 10000)//j为读取文件的大小 { //find_status = false; j++; datafile.read(buf,BUF_SIZE); if(datafile.eof()) return; datafile.seekg(-OFFSET, ios::cur); //vfData.push_back(fTemp); for(i = 0; i < BUF_SIZE ; i++) { tmp[i] = (unsigned char)buf[i]; } for(i = 0; i < BUF_SIZE - 3 ; i++) { if((tmp[i] == 255) && (tmp[i + 1] == 216) && (tmp[i + 2] == 255) && (tmp[i + 3] == 225)) { find_ffd8ffe1 = true; ffd8ffe1_num = i; // cout<<"begin"<<endl; } if((tmp[i] == 255) && (tmp[i + 1] == 217) && (tmp[i + 2] == 255) && (tmp[i + 3] == 219)) { if(open_status == true) find_ffd9ffdb = true; //ffd8ffe1_num = i; } if(find_ffd9ffdb == true) { if((tmp[i] == 255) && (tmp[i + 1] == 217) && ((tmp[i + 2] != 255) || (tmp[i + 3] != 219))) { if(open_status == true) { find_ffd9 = true; ffd9_num = i; find_ffd9ffdb = false; } } } } if(find_ffd9 == true) { if(open_status == true) { jpg->write(buf,ffd9_num + 2); jpg->close; delete jpg; cout<< "colse"<<endl; find_ffd9 = false; open_status = false; find_ffd9 = false; ffd9_num = 0; } } if(find_ffd8ffe1 == true) { if(open_status == false ) { strcpy(name,""); sprintf(name,"dic-%d.jpg",file_no); cout<< name<<endl; jpg = new ofstream; jpg->open(name, ios::binary|ios::out|ios::trunc); open_status = true; file_no++; cout<< jpg->fail()<<endl; jpg->write(buf + ffd8ffe1_num,BUF_SIZE - ffd8ffe1_num - OFFSET); find_ffd8ffe1 = false; } } else if((open_status == true) && (find_ffd9 == false)) { jpg->write(buf , BUF_SIZE - OFFSET); } } }