使用 PDFBOX 以正确的字符呈现形式书写阿拉伯语而不被分离
Writing Arabic with PDFBOX with correct characters presentation form without being separated
我正在尝试使用 PDFBox Apache 生成包含阿拉伯文本的 PDF,但文本生成为分隔字符,因为 Apache 将给定的阿拉伯字符串解析为一系列通用 'official' Unicode 字符,等同于阿拉伯字符的孤立形式。
这是一个例子:
以 PDF 格式写入的目标文本 "Should be expected output in PDF File" -> Passion Text
我在 PDF 文件中得到的内容 ->
我尝试了一些方法,但没有用,这里有一些方法:
1. 将字符串转换为比特流并尝试提取正确的值
2. 使用 UTF-8 && UTF-16 处理字符串字节序列并从中提取值
有一些方法似乎很有希望获得每个字符的值 "Unicode" 但它生成一般 "official Unicode" 这就是我的意思
System.out.println( Integer.toHexString( (int)(new String("كلمة").charAt(1))) );
输出是 644 但 fee0 是预期的输出,因为这个字符在中间,从那时起我应该得到中间的 Unicode fee0
所以我想要的是一些生成正确 Unicode 的方法,而不仅仅是官方的
后面第一个table最左边的一列link表示通用Unicode
Arabic Unicode Tables Wikipedia
通知:
此答案中的示例代码可能已过时,请参阅 以获取工作示例代码
首先,我要感谢 Tilman Hausherr and M.Prokhorov 向我展示了使使用 PDFBox Apache 编写阿拉伯语成为可能的库。
本回答将分为两部分:
- 正在下载并安装库
- 如何使用图书馆
正在下载并安装库
我们将使用 ICU 库。
ICU 代表 Unicode 国际组件,它是一套成熟的、广泛使用的 C/C++ 和 Java 库,为软件应用程序提供 Unicode 和全球化支持。 ICU 具有广泛的可移植性,并在所有平台上以及 C/C++ 和 Java 软件之间为应用程序提供相同的结果。
要下载库,请转到 here 的下载页面。
选择最新版本的 ICU4J 如下图所示。
您将转到另一个页面,您会发现一个框,其中包含所需组件的直接链接。继续下载三个文件,您会在下一张图片中找到突出显示的文件。
- icu4j-docs.jar
- icu4j-src.jar
- icu4j.jar
下面对在Netbeans中创建和添加库的解释IDE
- 导航到工具栏并单击工具
- 选择库
- 在左下方您会找到新的库按钮创建您的
- 导航到您在库列表中创建的库
- 点击它并像那样添加 jar 文件夹
- 在class路径中添加icu4j.jar
- 在源中添加 icu4j-src.jar
- 在 Javadoc
中添加 icu4j-docs.jar
- 从最右边查看您打开的项目
- 在
中展开要使用库的项目
- 右键单击库文件夹并选择添加库
- 最后选择刚刚创建的库。
现在您可以使用该库了,只需导入您想要的内容即可
import com.ibm.icu.What_You_Want_To_Import;
如何使用图书馆
使用 ArabicShaping Class 并反转字符串,我们可以写出正确的附加阿拉伯语 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();
}
}
这是输出
我希望我已经了解了所有内容。
更新 : 反转后确保再次反转数字以获得相同的正确数字
这里有几个功能可以帮助
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;
}
这是一个有效的代码。下载示例字体,例如trado.ttf
确保 pdfbox-app
和 icu4j
jar 文件在您的类路径中。
import java.io.File;
import java.io.IOException;
import com.ibm.icu.text.ArabicShaping;
import com.ibm.icu.text.ArabicShapingException;
import com.ibm.icu.text.Bidi;
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("trado.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);
String s ="جملة بالعربي لتجربة الكلاس اللذي يساعد علي وصل الحروف بشكل صحيح";
Writer.showText(bidiReorder(s));
Writer.endText();
Writer.close();
doc.save(new File("File_Test.pdf"));
doc.close();
}
private static String bidiReorder(String text)
{
try {
Bidi bidi = new Bidi((new ArabicShaping(ArabicShaping.LETTERS_SHAPE)).shape(text), 127);
bidi.setReorderingMode(0);
return bidi.writeReordered(2);
}
catch (ArabicShapingException ase3) {
return text;
}
}
}
我正在尝试使用 PDFBox Apache 生成包含阿拉伯文本的 PDF,但文本生成为分隔字符,因为 Apache 将给定的阿拉伯字符串解析为一系列通用 'official' Unicode 字符,等同于阿拉伯字符的孤立形式。
这是一个例子:
以 PDF 格式写入的目标文本 "Should be expected output in PDF File" -> Passion Text
我在 PDF 文件中得到的内容 ->
我尝试了一些方法,但没有用,这里有一些方法:
1. 将字符串转换为比特流并尝试提取正确的值
2. 使用 UTF-8 && UTF-16 处理字符串字节序列并从中提取值
有一些方法似乎很有希望获得每个字符的值 "Unicode" 但它生成一般 "official Unicode" 这就是我的意思
System.out.println( Integer.toHexString( (int)(new String("كلمة").charAt(1))) );
输出是 644 但 fee0 是预期的输出,因为这个字符在中间,从那时起我应该得到中间的 Unicode fee0
所以我想要的是一些生成正确 Unicode 的方法,而不仅仅是官方的
后面第一个table最左边的一列link表示通用Unicode
Arabic Unicode Tables Wikipedia
通知:
此答案中的示例代码可能已过时,请参阅
首先,我要感谢 Tilman Hausherr and M.Prokhorov 向我展示了使使用 PDFBox Apache 编写阿拉伯语成为可能的库。
本回答将分为两部分:
- 正在下载并安装库
- 如何使用图书馆
正在下载并安装库
我们将使用 ICU 库。
ICU 代表 Unicode 国际组件,它是一套成熟的、广泛使用的 C/C++ 和 Java 库,为软件应用程序提供 Unicode 和全球化支持。 ICU 具有广泛的可移植性,并在所有平台上以及 C/C++ 和 Java 软件之间为应用程序提供相同的结果。
要下载库,请转到 here 的下载页面。
选择最新版本的 ICU4J 如下图所示。
您将转到另一个页面,您会发现一个框,其中包含所需组件的直接链接。继续下载三个文件,您会在下一张图片中找到突出显示的文件。
- icu4j-docs.jar
- icu4j-src.jar
- icu4j.jar
下面对在Netbeans中创建和添加库的解释IDE
- 导航到工具栏并单击工具
- 选择库
- 在左下方您会找到新的库按钮创建您的
- 导航到您在库列表中创建的库
- 点击它并像那样添加 jar 文件夹
- 在class路径中添加icu4j.jar
- 在源中添加 icu4j-src.jar
- 在 Javadoc 中添加 icu4j-docs.jar
- 从最右边查看您打开的项目
- 在 中展开要使用库的项目
- 右键单击库文件夹并选择添加库
- 最后选择刚刚创建的库。
现在您可以使用该库了,只需导入您想要的内容即可
import com.ibm.icu.What_You_Want_To_Import;
如何使用图书馆
使用 ArabicShaping Class 并反转字符串,我们可以写出正确的附加阿拉伯语 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();
}
}
这是输出
我希望我已经了解了所有内容。
更新 : 反转后确保再次反转数字以获得相同的正确数字
这里有几个功能可以帮助
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;
}
这是一个有效的代码。下载示例字体,例如trado.ttf
确保 pdfbox-app
和 icu4j
jar 文件在您的类路径中。
import java.io.File;
import java.io.IOException;
import com.ibm.icu.text.ArabicShaping;
import com.ibm.icu.text.ArabicShapingException;
import com.ibm.icu.text.Bidi;
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("trado.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);
String s ="جملة بالعربي لتجربة الكلاس اللذي يساعد علي وصل الحروف بشكل صحيح";
Writer.showText(bidiReorder(s));
Writer.endText();
Writer.close();
doc.save(new File("File_Test.pdf"));
doc.close();
}
private static String bidiReorder(String text)
{
try {
Bidi bidi = new Bidi((new ArabicShaping(ArabicShaping.LETTERS_SHAPE)).shape(text), 127);
bidi.setReorderingMode(0);
return bidi.writeReordered(2);
}
catch (ArabicShapingException ase3) {
return text;
}
}
}