gpt4 book ai didi

java - 用PDFBox插入NULL字符

转载 作者:太空宇宙 更新时间:2023-11-04 07:28:21 25 4
gpt4 key购买 nike

让我们考虑以下代码:

public class Test1{

public static void CreatePdf(String src) throws IOException, COSVisitorException{
PDRectangle rec= new PDRectangle(400,400);
PDDocument document= null;
document = new PDDocument();
PDPage page = new PDPage(rec);
document.addPage(page);
PDDocumentInformation info=document.getDocumentInformation();
PDStream stream= new PDStream(document);
info.setAuthor("PdfBox");
info.setCreator("Pdf");
info.setSubject("Stéganographie");
info.setTitle("Stéganographie dans les documents PDF");
info.setKeywords("Stéganographie, pdf");
content= new PDPageContentStream(document, page, true, false );
font= PDType1Font.HELVETICA;

String hex = "4C0061f"; // shows "La"
//Notice that we have 00 between 4C and 61 where 00 =null character


StringBuilder sb = new StringBuilder();
for (int count = 0; count < hex.length() - 1; count += 2)
{
String output = hex.substring(count, (count + 2));
int decimal = Integer.parseInt(output, 16);
StringBuilder ae= sb.append((char)decimal);
}
String tt=sb.toString();
content.beginText();
content.setFont(font, 12);
content.appendRawCommands("15 385 Td\n");
content.appendRawCommands("("+tt+")"+"Tj\n");
content.endText();
content.close();
document.save("doc.pdf");
document.close();
}


我的问题是:为什么在PDF文档中用空格代替“ 00”而不是空字符?
注意,该空字符的宽度为0.0,但在PDF文档中显示为空格!
因此我得到:“ L a”而不是“ La”

最佳答案

为什么将“ 00”替换为PDF文档中的空格而不是空字符?


如果您查看PDF,则会发现用于文本的字体定义为:

9 0 obj
<<
/Type /Font
/Subtype /Type1
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
>>
endobj


因此,您可以使用带有WinAnsiEncoding的字体。如果查看 PDF specification附件D中该编码的定义,您会发现没有32(十进制)以下的代码映射到任何内容。因此,您想要做的是使用手头编码中未定义的字符。因此,行为没有定义。对于那些未定义的代码点,Acrobat Reader似乎使用正宽度。

如果要确保隐藏的字符根本不会引起任何移位,则应在字体字典中添加一个显式的宽度数组,参见。 PDF specification中的9.6.2节,并确保不可见字符的宽度为0。(顺便说一句,几年前,不建议像PDFBox那样不嵌入widths数组)。


  请注意,此空字符的宽度为0.0


一旦您进入未定义的范围,任何事情都可能发生,并且不同的程序具有不同的假设。

PS一些代码...行之间

font= PDType1Font.HELVETICA;




String hex = "4C0061f";  // shows "La"


我添加了以下代码:

InputStream afmStream = ResourceLoader.loadResource("org/apache/pdfbox/resources/afm/Helvetica.afm");
AFMParser afmParser = new AFMParser(afmStream);
afmParser.parse();
FontMetric afmMetrics = afmParser.getResult();
List<Float> newWidths = new ArrayList<Float>();
for (CharMetric charMetric : afmMetrics.getCharMetrics())
{
if (charMetric.getCharacterCode() < 0)
continue;
while (charMetric.getCharacterCode() >= newWidths.size())
newWidths.add(0f);
newWidths.set(charMetric.getCharacterCode(), charMetric.getWx());
}
font.setFirstChar(0);
font.setLastChar(newWidths.size() - 1);
font.setWidths(newWidths);


此代码应读取PDFBox中包含的Helvetica.afm字体指标资源,并从中创建FirstChar,LastChar和Widths条目。可以在这里正常使用,但是如果您的安装中没有安装,只需从PDFBox罐中提取afm文件,然后使用 FileInputStream.读取

由于某些原因,00字符似乎仍然认为它具有一定的宽度,但是可以使用低于32(十进制)的其他字符,例如

String hex = "4C0461f";


无间隙显示“ La”。如果我正确地解释了您以前关于1C和1D的问题(现在已删除),那么这已经可以帮助您继续。

PPS:关于评论中的问题:


  您能告诉我这种方法的所有缺点吗?以及为什么此方法不与重音符匹配,例如(Lé),您的代码仅与不带重音符的字符匹配,但是当我们带有重音符时,我们得到Lé而不是Le ..我只想知道有什么缺点您的代码:)


我无法告诉所有人(因为我对字体问题并不真正了解),但是从本质上讲,上述方法并不完整。

如开头所述,您使用的字体带有WinAnsiEncoding,其中没有32(十进制)以下的代码映射到任何内容。通过添加FirstChar,LastChar和Widths条目,我们尝试为代码低于32的那些字符定义零宽度。

尽管如此,尽管如此,我们既不关心这些代码的编码信息(编码仍然是纯WinAnsiEncoding),也没有考虑字体是否实际上包含那些代码的任何信息。此外,为了使事情仍然难以控制,我们正在谈论Helvetica,即PDF浏览器必须始终携带其自身信息的标准14种字体之一。无论明确给出的信息与查看者带来的信息有何矛盾,PDF查看器都可能倾向于偏向于自己的信息。

为什么特别是带有重音符号的字符有麻烦?我不确定。不过,我想这与以下事实有关:字体通常不会将带重音符号的字符作为单独的实体,而是将带重音字符和无重音字符组合在一起。也许在内部,查看者使用的字体具有一些映射到低于32的代码点的此类组合字符的信息,因此,当您的低于32的显式代码与字体对此类代码的隐式使用并排出现时,显示将变得古怪。

基本上,我通常建议不要这样做。对于普通的PDF文档,根本没有必要。

但是,就您的情况而言,在为文档Stéganographiedans les文档PDF命名时,您显然确实希望以某种方式隐藏PDF中的信息。使用看不见的,无法打印的字符似乎是一种方法。因此,您可以朝那个方向尝试。但是PDF确实提供了许多其他方式,可以将任何数量的信息放入PDF中而不会直接可见。

因此,根据您的特定目标,我认为其他方法可能会更安全地隐藏信息,例如私有PieceInfo部分或其他一些词典中的自定义标签...

关于java - 用PDFBox插入NULL字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18184254/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com