我创建了一个Java程序来翻译PDF。我正在使用Google API进行翻译。我在Eclipse IDE控制台上获得正确的翻译,但是当我检查新创建的pdf时,要么没有按原样进行翻译和复制,要么翻译了很少的单词,或者新的pdf变成空白,有时甚至损坏了。
我想它与编码和字体类型有关。
我已经浏览了Itext页面和所有相关问题,但没有一个适合我的情况。我正在尝试将葡萄牙语,西班牙语,芬兰语,法语,匈牙利语等翻译成英语。
这是我的代码:
public static final String SRC = "5587309Finnish.pdf";
public static final String DEST = "changed.pdf";
public static void main(String[] args) throws java.io.IOException, DocumentException {
Translate translate = TranslateOptions.getDefaultInstance().getService();
PdfReader reader = new PdfReader(SRC);
int pages = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST));
for(int i=1;i<=pages;i++) {
PdfDictionary dict = reader.getPageN(i);
PdfObject object = dict.getDirectObject(PdfName.CONTENTS);
if (object instanceof PRStream) {
String pageContent =
PdfTextExtractor.getTextFromPage(reader, i);
String[] word = pageContent.split(" ");
PRStream stream = (PRStream) object;
byte[] data = PdfReader.getStreamBytes(stream);
String dd = new String(data, BaseFont.CP1252);
for (int j=0; j < word.length; j++)
{
Translation translation = translate.translate(word[j],Translate.TranslateOption.sourceLanguage("fi"),
Translate.TranslateOption.targetLanguage("en"));
System.out.println(word[j]+"-->>"+translation.getTranslatedText());//here i can check the translation is correct.
dd = dd.replace(word[j],translation.getTranslatedText());
}
stream.setData(dd.getBytes());
}
}
stamper.close();
reader.close();
}
请帮助。
根据评论,您已经改善了代码,并且是
正确获取带有替换文本的更新dd(即我正在打印的内容流)。我不知道为什么我会得到空白的pdf
因此,我假设您的(具有代表性的)测试PDF具有所有感兴趣的字体都以ANSI'ish编码编码,并且文本绘图指令的文本参数包含整个单词甚至短语,可以正确处理它们,因为否则将替换文本不可能的。
因此,这里是一个示例,说明了如何在这种良性情况下用类似长的文本替换文本片段而不破坏内容流语法。在此示例中,我仅使用包含替换字符串的Map
。您可以在那里进行翻译。
首先是一帧加载源,创建一个压模,遍历页面,并调用一个助手来创建内容流替换:
Map<String, String> replacements = new HashMap<>();
replacements.put("Förfallodatum", "Ablaufdatum");
try ( InputStream resource = SOURCE_INPUTSTREAM;
OutputStream result = new FileOutputStream(RESULT_FILE) ) {
PdfReader pdfReader = new PdfReader(resource);
PdfStamper pdfStamper = new PdfStamper(pdfReader, result);
for (int pageNum = 1; pageNum <= pdfReader.getNumberOfPages(); pageNum++) {
PdfDictionary page = pdfReader.getPageN(pageNum);
byte[] pageContentInput = ContentByteUtils.getContentBytesForPage(pdfReader, pageNum);
page.remove(PdfName.CONTENTS);
replaceInStringArguments(pageContentInput, pdfStamper.getUnderContent(pageNum), replacements);
}
pdfStamper.close();
}
([EditPageContentSimple test testReplaceInStringArgumentsForklaringAvFakturan
)
方法replaceInStringArguments
现在解析给定内容流中的指令,隔离字符串参数,并为每个字符串参数调用另一个助手进行替换。
void replaceInStringArguments(byte[] contentBytesBefore, PdfContentByte canvas, Map<String, String> replacements) throws IOException {
PRTokeniser tokeniser = new PRTokeniser(new RandomAccessFileOrArray(new RandomAccessSourceFactory().createSource(contentBytesBefore)));
PdfContentParser ps = new PdfContentParser(tokeniser);
ArrayList<PdfObject> operands = new ArrayList<PdfObject>();
while (ps.parse(operands).size() > 0){
for (int i = 0; i < operands.size(); i++) {
PdfObject pdfObject = operands.get(i);
if (pdfObject instanceof PdfString) {
operands.set(i, replaceInString((PdfString)pdfObject, replacements));
} else if (pdfObject instanceof PdfArray) {
PdfArray pdfArray = (PdfArray) pdfObject;
for (int j = 0; j < pdfArray.size(); j++) {
PdfObject arrayObject = pdfArray.getPdfObject(j);
if (arrayObject instanceof PdfString) {
pdfArray.set(j, replaceInString((PdfString)arrayObject, replacements));
}
}
}
}
for (PdfObject object : operands)
{
object.toPdf(canvas.getPdfWriter(), canvas.getInternalBuffer());
canvas.getInternalBuffer().append((byte) ' ');
}
canvas.getInternalBuffer().append((byte) '\n');
}
}
([EditPageContentSimple辅助方法)
[C0方法反过来检索单个字符串操作数(replaceInString
实例),对其进行操作,然后返回操作的字符串版本:
PdfString
([PdfString replaceInString(PdfString string, Map<String, String> replacements) {
String value = PdfEncodings.convertToString(string.getBytes(), PdfObject.TEXT_PDFDOCENCODING);
for (Map.Entry<String, String> entry : replacements.entrySet()) {
value = value.replace(entry.getKey(), entry.getValue());
}
return new PdfString(PdfEncodings.convertToBytes(value, PdfObject.TEXT_PDFDOCENCODING));
}
辅助方法)
而不是这里的EditPageContentSimple循环,您将调用翻译例程并翻译for
。
如前所述,此代码仅在某些良性情况下有效。不要指望它可以用于野外的任意文档,特别是不适用于除西欧字形以外的其他文档。