Min*_*ges 4 java pdf pdf-generation pdfbox
我正在尝试使用PDFBox Apache生成包含阿拉伯文本的PDF,但该文本会作为分隔的字符生成,因为Apache将给定的阿拉伯字符串解析为一系列常规的“正式” Unicode字符,等效于隔离的阿拉伯字符形式。
这是一个示例:
要在PDF中写入的目标文本“应该在PDF文件中输出”-> ???? ???????
我在PDF文件中得到的内容->
我尝试了一些方法,但这里没有用:
1.将String转换为位流并尝试提取正确的值
2.使用UTF-8 && UTF-16处理String字节序列并从中提取值
有一种方法看起来很有希望获得每个字符的“ Unicode”值,但是它会生成通用的“官方Unicode”,这就是我的意思。
System.out.println( Integer.toHexString( (int)(new String("????").charAt(1))) );
Run Code Online (Sandbox Code Playgroud)
输出为644,但fee0是预期的输出,因为此字符位于中间,那么我应该得到中间的Unicode fee0
所以我想要的是一种生成正确Unicode而不只是官方的方法
以下链接的第一个表中最左侧的列表示常规Unicode
阿拉伯语Unicode表Wikipedia
首先,我要感谢Tilman和M.Prokhorov向我展示了使使用PDFBox Apache编写阿拉伯语成为可能的库。
我们将使用ICU库。
ICU代表Unicode的国际组件,它是成熟的,广泛使用的C / C ++和Java库集,为软件应用程序提供Unicode和全球化支持。ICU具有广泛的可移植性,可以在所有平台上以及C / C ++和Java软件之间为应用程序提供相同的结果。
要下载库,请从此处转到下载页面。如下图所示,
选择最新版本的ICU4J。

您将转到另一个页面,您将找到一个包含所需组件直接链接的框。继续并下载三个文件,您将在下一张图片中找到突出显示的内容。
在Netbeans IDE中创建和添加库的以下说明
现在您可以使用库了,只需导入所需的内容即可
import com.ibm.icu.What_You_Want_To_Import;
Run Code Online (Sandbox Code Playgroud)
使用ArabicShaping类并反转字符串,我们可以编写正确的附加阿拉伯语LINE
这是代码请注意以下代码中的注释
import com.ibm.icu.text.ArabicShaping;
import com.ibm.icu.text.ArabicShapingException;
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.*;
public class Main {
public static void main(String[] args) throws IOException , ArabicShapingException
{
File f = new File("Arabic Font File of format.ttf");
PDDocument doc = new PDDocument();
PDPage Page = new PDPage();
doc.addPage(Page);
PDPageContentStream Writer = new PDPageContentStream(doc, Page);
Writer.beginText();
Writer.setFont(PDType0Font.load(doc, f), 20);
Writer.newLineAtOffset(0, 700);
//The Trick in the next Line of Code But Here is some few Notes first
//We have to reverse the string because PDFBox is Writting from the left but Arabic is RTL Language
//The output will be perfect except every line will be justified to the left "It's not hard to resolve this"
// So we have to write arabic string to pdf line by line..It will be like this
String s ="???? ??????? ?????? ?????? ????? ????? ??? ??? ?????? ???? ????";
Writer.showText(new StringBuilder(new ArabicShaping(reverseNumbersInString(ArabicShaping.LETTERS_SHAPE).shape(s))).reverse().toString());
// Note the previous line of code throws ArabicShapingExcpetion
Writer.endText();
Writer.close();
doc.save(new File("File_Test.pdf"));
doc.close();
}
}
Run Code Online (Sandbox Code Playgroud)
这是输出
我希望我已经解决了所有问题。
更新:反转后,请确保再次反转数字以获得相同的正确数字。
以下几个功能可能会有所帮助
public static boolean isInt(String Input)
{
try{Integer.parseInt(Input);return true;}
catch(NumberFormatException e){return false;}
}
public static String reverseNumbersInString(String Input)
{
char[] Separated = Input.toCharArray();int i = 0;
String Result = "",Hold = "";
for(;i<Separated.length;i++ )
{
if(isInt(Separated[i]+"") == true)
{
while(i < Separated.length && (isInt(Separated[i]+"") == true || Separated[i] == '.' || Separated[i] == '-'))
{
Hold += Separated[i];
i++;
}
Result+=reverse(Hold);
Hold="";
}
else{Result+=Separated[i];}
}
return Result;
}
Run Code Online (Sandbox Code Playgroud)
这是一个有效的代码。下载示例字体,例如trado.ttf
\n编辑:此后我一直在使用Amiri字体,可以从aliftype/amiriGithub存储库下载该字体。
确保pdfbox-app和icu4jjar 文件位于您的类路径中。
import java.io.File;\nimport java.io.IOException;\n\nimport com.ibm.icu.text.ArabicShaping;\nimport com.ibm.icu.text.ArabicShapingException;\nimport com.ibm.icu.text.Bidi;\n\nimport org.apache.pdfbox.pdmodel.PDDocument;\nimport org.apache.pdfbox.pdmodel.PDPage;\nimport org.apache.pdfbox.pdmodel.PDPageContentStream;\nimport org.apache.pdfbox.pdmodel.font.*;\n\npublic class Main {\n public static void main(String[] args) throws IOException , ArabicShapingException\n {\n File f = new File("Amiri-Regular.ttf");\n PDDocument doc = new PDDocument();\n PDPage Page = new PDPage();\n doc.addPage(Page);\n PDPageContentStream Writer = new PDPageContentStream(doc, Page);\n Writer.beginText();\n Writer.setFont(PDType0Font.load(doc, f), 20);\n Writer.newLineAtOffset(0, 700);\n String s ="\xd8\xac\xd9\x85\xd9\x84\xd8\xa9 \xd8\xa8\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a \xd9\x84\xd8\xaa\xd8\xac\xd8\xb1\xd8\xa8\xd8\xa9 \xd8\xa7\xd9\x84\xd9\x83\xd9\x84\xd8\xa7\xd8\xb3 \xd8\xa7\xd9\x84\xd9\x84\xd8\xb0\xd9\x8a \xd9\x8a\xd8\xb3\xd8\xa7\xd8\xb9\xd8\xaf \xd8\xb9\xd9\x84\xd9\x8a \xd9\x88\xd8\xb5\xd9\x84 \xd8\xa7\xd9\x84\xd8\xad\xd8\xb1\xd9\x88\xd9\x81 \xd8\xa8\xd8\xb4\xd9\x83\xd9\x84 \xd8\xb5\xd8\xad\xd9\x8a\xd8\xad";\n Writer.showText(bidiReorder(s));\n Writer.endText();\n Writer.close();\n doc.save(new File("File_Test.pdf"));\n doc.close();\n }\n\n private static String bidiReorder(String text)\n {\n try {\n Bidi bidi = new Bidi((new ArabicShaping(ArabicShaping.LETTERS_SHAPE)).shape(text), 127);\n bidi.setReorderingMode(0);\n return bidi.writeReordered(2);\n }\n catch (ArabicShapingException ase3) {\n return text;\n }\n }\n \n}\nRun Code Online (Sandbox Code Playgroud)\n