C++ PDF fin Acrobat不显示简单文本,但可在Firefox和MicrosoftEdge中使用
更新:我已经更新了正确的代码,它的工作100% 我已经写了一个程序,生成一个单词搜索,它的工作非常完美。我想输出到没有任何第三方软件的PDF文件。我会发布C++例程和生成的PDF文件。 为什么这在浏览器和Acrobat中起作用?它打开了,但页面是空白的。 PDF文件非常简单C++ PDF fin Acrobat不显示简单文本,但可在Firefox和MicrosoftEdge中使用,c++,pdf,C++,Pdf,更新:我已经更新了正确的代码,它的工作100% 我已经写了一个程序,生成一个单词搜索,它的工作非常完美。我想输出到没有任何第三方软件的PDF文件。我会发布C++例程和生成的PDF文件。 为什么这在浏览器和Acrobat中起作用?它打开了,但页面是空白的。 PDF文件非常简单 void SavePdf(const string& fileName, vector<vector<char>>& board, vector<string>&
void SavePdf(const string& fileName, vector<vector<char>>& board, vector<string>& words)
{
const string eol = "\r\n";
const string version = "1.0";
const auto heightPerLine = 20;
const auto topMargin = 300;
const auto pages = 1;
const auto width = 800;
const auto height = max(board.size() * heightPerLine + topMargin, 1200ull);
vector<unsigned long long>offsets;
stringstream pdfBuffer;
pdfBuffer <<
"%PDF-" << version << eol << eol;
offsets.push_back(pdfBuffer.tellp());
pdfBuffer <<
"1 0 obj" << eol <<
"<< /Type /Catalog" << eol <<
"/Pages 2 0 R" << eol <<
">>" << eol <<
"endobj" << eol << eol;
offsets.push_back(pdfBuffer.tellp());
pdfBuffer <<
"2 0 obj" << eol <<
"<< /Type /Pages" << eol <<
"/Kids[3 0 R]" << eol <<
"/Count " << pages << eol <<
"/MediaBox[0 0 " << width << ' ' << height << "]" << eol <<
">>" << eol <<
"endobj" << eol << eol;
offsets.push_back( pdfBuffer.tellp());
pdfBuffer <<
"3 0 obj" << eol <<
"<< /Type /Page" << eol <<
"/Parent 2 0 R" << eol <<
"/Resources" << eol <<
"<< /Font" << eol <<
"<< /F1" << eol <<
"<< /Type /Font" << eol <<
"/Subtype /Type1" << eol <<
"/BaseFont /Courier" << eol <<
">>" << eol <<
">>" << eol <<
">>" << eol <<
"/Contents 4 0 R" << eol <<
">>" << eol <<
"endobj" << eol << eol;
stringstream boardStream;
auto yPos = height - 30;
const auto xPos = (width - static_cast<double>(board[0].size()) * 2 * 6.5) / 2;
for (auto& row : board)
{
boardStream <<
"BT" << eol <<
"/F1 12 Tf" << eol <<
xPos << ' ' << yPos << " Td" << eol << '(';
for (auto& c : row)
boardStream << c << ' ';
boardStream << ") Tj" << eol <<
"ET" << eol;
yPos -= heightPerLine;
}
offsets.push_back( pdfBuffer.tellp());
pdfBuffer <<
"4 0 obj" << eol <<
"<< /Length " << static_cast<int>(boardStream.tellp()) << " >>" << eol <<
"stream" << eol <<
boardStream.str() << eol <<
"endstream" << eol <<
"endobj" << eol << eol;
auto xRefOffset = pdfBuffer.tellp();
pdfBuffer <<
"xref" << eol <<
"0 " << offsets.size() + 1 << eol <<
"0000000000 65535 f" << eol;
for (auto& offset : offsets)
pdfBuffer << setw(10) << setfill('0') << offset << ' ' << setw(5) << 0 << " n" << eol;
pdfBuffer << eol;
pdfBuffer <<
"trailer" << eol <<
"<<" << eol <<
"/Root 1 0 R" << eol <<
"/Size " << offsets.size() + 1 << eol <<
">>" << eol << eol <<
"startxref" << eol <<
xRefOffset << eol <<
"%%EOF" << eol;
ofstream outFile;
outFile.open(fileName, ofstream::out | ofstream::trunc | ofstream::binary);
if (outFile.is_open())
{
outFile << pdfBuffer.str();
outFile.close();
}
else
{
cout << "Error creating output file " << fileName << '.' << endl;
return;
}
}
void SavePdf(常量字符串和文件名、向量和板、向量和单词)
{
常量字符串eol=“\r\n”;
常量字符串版本=“1.0”;
const auto heightPerLine=20;
const auto topMargin=300;
const auto pages=1;
常数自动宽度=800;
常数自动高度=最大值(board.size()*heightPerLine+topMargin,1200ull);
矢量偏移量;
stringstream pdfBuffer;
pdfBuffer正如@PaulMcKenzie已经提到的,您的交叉引用条目和startxref偏移是错误的。同样,流的长度也不正确
这很可能是由于您从stringstream pdfBuffer
中的位置计算这些偏移量和长度,忽略将字符写入文件时单个字符可能变成多个字节,特别是endl
很可能只在pdfBuffer
中添加一个“\n”字符,这将成为Windows上的文件中有两个字节0x0d 0x0a
使用十六进制编辑器,我通过替换流字典在您的文件中修复了这个问题
>
借
>
以及您的交叉引用表条目
00000000 10 00000n
00000000 7200000N
0000000 17600000N
0000000446000000N
借
00000001200000n
00000000 80000000N
000000019200000N
000000047800000N
最后是startxref条目
startxref
2502
借
startxref
2654
此外,在交叉引用中,您删除了对象4,0 4
表示从对象0开始,有4个对象的条目,即仅看到0、1、2和3的条目,忽略了对象4的条目。同样,拖车中的尺寸条目太小,小于1
我在你的文件中通过进一步替换
xref
0 4
借
xref
0 5
在拖车里
/Size 4
借
/Size 5
在这些更改之后,Acrobat Reader还可以正确显示您的字母网格。此外,Adobe Reader不必修复文件,因此它不会再询问是否应在关闭时保存更改。正如@PaulMcKenzie已经提到的,您的交叉引用条目和开始外部参照偏移是错误的。类似地流的长度不正确
这很可能是由于您从stringstream pdfBuffer
中的位置计算这些偏移量和长度,忽略将字符写入文件时单个字符可能变成多个字节,特别是endl
很可能只在pdfBuffer
中添加一个“\n”字符,这将成为Windows上的文件中有两个字节0x0d 0x0a
使用十六进制编辑器,我通过替换流字典在您的文件中修复了这个问题
>
借
>
以及您的交叉引用表条目
00000000 10 00000n
00000000 7200000N
0000000 17600000N
0000000446000000N
借
00000001200000n
00000000 80000000N
000000019200000N
000000047800000N
最后是startxref条目
startxref
2502
借
startxref
2654
此外,在交叉引用中,您删除了对象4,0 4
表示从对象0开始,有4个对象的条目,即仅看到0、1、2和3的条目,忽略了对象4的条目。同样,拖车中的尺寸条目太小,小于1
我在你的文件中通过进一步替换
xref
0 4
借
xref
0 5
在拖车里
/Size 4
借
/Size 5
在这些更改之后,Acrobat Reader还可以正确地显示您的字母网格。此外,Adobe Reader不必修复文件,因此它不会再询问是否应在关闭时保存更改。您的pdf格式不正确。有一件事--您的xref
偏移似乎由于回车而关闭。我建议您使用get打开二进制编辑器并验证这些对象是否从这些交叉引用号开始。其次,PDF文件通常在PDF-1.0
之后有某种二进制短引线文本,您缺少这些文本。最后,Acrobat(和Nitro PDF)检测到文件已损坏,并尝试“更正”它--web浏览器不是用来确定文件是否损坏的工具,因为该工具本身可能正试图在幕后纠正您的错误。正如@PaulMcKenzie已经提到的,您的交叉引用条目和startxref偏移量是错误的。同样,流的大小也是错误的。此外,在交叉引用中u drop object 4,0 4
表示从0开始有4个条目,即只看到0、1、2和3的条目,忽略您对object 4的条目。同样,您在预告片中的大小条目太小,小于1。纠正所有这些问题后,Acrobat Reader上的结果也会显示良好。@PaulBaxter--再次需要强调这一点--如果您我们将从头开始创建PDF文件,拥有一个好的二进制编辑器是必不可少的,几乎是强制性的。您无法通过直观地查看文件内容来验证交叉引用号是否正确。这就是为什么最初您在文本窗口中发布的文件内容对诊断问题毫无用处的原因,我们要么需要实际文件来验证偏移量和其他方面,要么您给我们