在本文中主要实现了以下功能:
本代码是在linux下运行的。三个代码是叠加的,可以直接用第三个代码。
1、找到startxref 的值。
2、根据startxref 的值找到 交叉引用表(xref),并将其条目保存在文件xref_data.txt文件中。
3、根据找到的交叉引用表(xref)条目,找到obj,并将其字典保存在obj_data.txt文件中。
1、找到startxref 的值:
实现该步骤,我们的思路是,先定位到文件末尾,再回退3行,即可找到startxref,下一行便是startxref 的值。(这里对源文件进行了处理,因为在linux下我导入的PDF文件是乱码的,换行符有时检测不到,导致多行在一行显示。故在最后的几行我手动进行换行)
下图是我随便生成的一个PDF文件,用记事本打开后的文件尾部截图:
代码(name:lastline.cpp):
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::ifstream File("p11.pdf", std::ios::ate |std::ios::binary);
//std::ifstream fin("/var/log/test.log", std::ios::ate);
if (!File)
{
cout << "cannot open file!";
return -1;
}
// 先倒回文件末尾两个字符
File.seekg(0, File.cur);
// 假定反向读第3行的记录
int lineCount = 3;
for (int i = 0; i < lineCount; i++)
{
// 查看前一个字符是否为回车符
while (File.peek() != File.widen('\n'))
{
File.seekg(-1, File.cur);
}
// 走到这里表示跳过一行了,所以继续向前跳直到到3行
File.seekg(-1, File.cur);
}
File.seekg(0, File.cur);
std::string line;
//如果想将倒数lineCount行都输出,咋加入循环while
getline(File, line);//输出为‘\n’
//while (getline(File, line))
//{
getline(File,line);
cout << line << endl;
//startxref 用于保存xref的偏移量
int startxref = stoi(line);
cout << startxref << endl;
//printf("%02");
//}
File.clear();
File.close();
system("pause");
return 0;
}
运行结果:
2、找到xref 并将其条目保存在文件xref_data.txt文件中
根据上文1中找到的startxref的值(其值表示xref 的偏移),找到xref的位置。在其后一行是条目的数量,我们需要将该值提取出来,并转换为int类型。如何for()将条目数据保存到xref_data.txt文件中。
下图为交叉引用表(windows下的截图):
代码(name: find_xref.cpp):
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//找到startxref
std::ifstream File("p11.pdf", std::ios::ate |std::ios::binary);
if (!File)
{
cout << "cannot open file!";
return -1;
}
// 先倒回文件末尾两个字符
File.seekg(0, File.cur);
// 假定反向读第3行的记录
int lineCount = 3;
for (int i = 0; i < lineCount; i++)
{
// 查看前一个字符是否为回车符
while (File.peek() != File.widen('\n'))
{
File.seekg(-1, File.cur);
}
// 走到这里表示跳过一行了,所以继续向前跳直到到3行
File.seekg(-1, File.cur);
}
File.seekg(0, File.cur);
std::string line;
//如果想将倒数lineCount行都输出,咋加入循环while
getline(File, line);//输出为‘\n’
getline(File,line);
//cout << line << endl;
//startxref 用于保存xref的偏移量
int startxref = stoi(line);
cout << startxref << endl;
//---------------------------保存xref的条目数据------------------------------------------
//std::ifstream File("p11.pdf", std::ios::ate |std::ios::binary);
ofstream File_xref("xref_data.txt",std::ios::out);
if (!File_xref)
{
cout << "cannot open file!";
return -1;
}
//string line;
//找到xref的位置
File.seekg(startxref,File.beg);
getline(File,line);
cout << line<< endl;
//找到条目数量
getline(File,line);
cout << line<< endl;
string temp;
for(int i = 0 ; i < 100;i++){
if(line[i] == ' '){
temp = line.substr(i+1);
break;
}
}
//xrefOfNumber 用于保存xref的条目数
int xrefOfNumber = stoi(temp);
cout << xrefOfNumber << endl;
for(int i = 0 ; i < xrefOfNumber ;i++){
getline(File,line);
File_xref << line <<endl;
cout << line<< endl;
}
File_xref.close();
File.clear();
File.close();
system("pause");
return 0;
}
运行结果:
3、根据找到的交叉引用表(xref)条目,找到obj,并将其字典保存在obj_data.txt文件中。
xref 的条目前10位表示的是obj 的偏移(任然需要将其转换为 int 类型),可以根据其找到 obj 的位置。再将obj 字典保存到文件obj_data.txt文件中。
代码(name: find_obj_by_xref.cpp):
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//---------------------------找到startxref的值------------------------------------------
//找到startxref
std::ifstream File("p11.pdf", std::ios::ate |std::ios::binary);
if (!File)
{
cout << "cannot open file!";
return -1;
}
// 先倒回文件末尾两个字符
File.seekg(0, File.cur);
// 假定反向读第3行的记录
int lineCount = 3;
for (int i = 0; i < lineCount; i++)
{
// 查看前一个字符是否为回车符
while (File.peek() != File.widen('\n'))
{
File.seekg(-1, File.cur);
}
// 走到这里表示跳过一行了,所以继续向前跳直到到3行
File.seekg(-1, File.cur);
}
File.seekg(0, File.cur);
std::string line;
//如果想将倒数lineCount行都输出,咋加入循环while
getline(File, line);//输出为‘\n’
getline(File,line);
//cout << line << endl;
//startxref 用于保存xref的偏移量
int startxref = stoi(line);
//cout << startxref << endl;
//---------------------------保存xref的条目数据------------------------------------------
ofstream File_xref("xref_data.txt",std::ios::out);
if (!File_xref)
{
cout << "cannot open file!";
return -1;
}
//找到xref的位置
File.seekg(startxref,File.beg);
getline(File,line);
//cout << line<< endl;
//找到条目数量
getline(File,line);
//cout << line<< endl;
string temp;
for(int i = 0 ; i < 100;i++){
if(line[i] == ' '){
temp = line.substr(i+1);
break;
}
}
//xrefOfNumber 用于保存xref的条目数
int xrefOfNumber = stoi(temp);
//cout << xrefOfNumber << endl;
for(int i = 0 ; i < xrefOfNumber ;i++){
getline(File,line);
File_xref << line <<endl;
//cout << line<< endl;
}
File_xref.close();
//File.clear();
//File.close();
//---------------------------找到obj 并保存------------------------------------------
std::ifstream File_xref2("xref_data.txt", std::ios::ate |std::ios::binary);
//将obj保存到obj_data.txt中
ofstream File_obj("obj_data.txt",std::ios::out);
//int xrefOfNumber = 17;
//string temp = "";
//string line = "" ;
if (!File_xref)
{
cout << "cannot open file!";
return -1;
}
File_xref2.seekg(0, File_xref2.beg);
//string line;
for(int i = 0 ; i < xrefOfNumber ;i++){
getline(File_xref2, line);
int objStart = 0;
//交叉表的前10位表示偏移
temp = line.substr(0,10);
objStart = stoi(temp);
//cout << objStart << endl;
if(objStart == 0){
continue;
}
string lineObj;
File.seekg(objStart,File.beg);
//PDF文件的换行符好像是('\r\n')
//将obj编号以及obj字典写入obj_data.txt文件
getline(File,lineObj,'\r');
File_obj << lineObj << endl;
cout << lineObj << endl;
getline(File,lineObj,'\r');
File_obj << lineObj << endl;
cout << lineObj << endl;
}
File_xref2.close();
//File.clear();
File.close();
File_obj.close();
system("pause");
return 0;
}
运行结果:
gitee代码地址:C++学习: C++的学习记录 - Gitee.com
代码在文件: 找到xref以及 obj 中
以上三个代码可独立运行。