用PDFBOX写阿拉伯语并使用正确的字符表示形式而不分开

时间:2018-01-16 15:39:16

标签: java pdf pdf-generation pdfbox

我正在尝试使用PDFBox Apache生成包含阿拉伯语文本的PDF,但文本生成为单独的字符,因为Apache将给定的阿拉伯字符串解析为一系列通用的“官方”Unicode字符,这些字符等同于孤立形式的阿拉伯字符。

这是一个例子:
目标文本以PDF格式写入“应该是PDF文件中的预期输出” - > جملةبالعربي
我在PDF文件中获得的内容 - >

incorrect text

我尝试了一些方法,但这里有一些方法没用:
1.将字符串转换为比特流并尝试提取正确的值
2.使用UTF-8&&amp ;;处理String一个字节序列。 UTF-16并从中提取值

有一些方法看起来非常有希望获得每个字符的值“Unicode”但是它生成一般的“官方Unicode”这就是我的意思

System.out.println( Integer.toHexString( (int)(new String("كلمة").charAt(1))) );  

输出是644但是fee0是预期的输出,因为这个字符在中间从那时起我应该得到中间的Unicode费用

所以我想要的是一些生成正确Unicode的方法,而不仅仅是官方的

以下链接中第一个表中的“Left”列表示常规Unicode Arabic Unicode Tables Wikipedia

2 个答案:

答案 0 :(得分:5)

首先,我要感谢Tilman和M.Prokhorov向我展示了使用PDFBox Apache编写阿拉伯语的库。

<小时/> 本答案将分为两个部分:

  1. 下载库并安装它
  2. 如何使用图书馆
  3. 下载库并安装

    我们将使用ICU图书馆 ICU代表Unicode的国际组件,它是一组成熟的,广泛使用的C / C ++和Java库,为软件应用程序提供Unicode和全球化支持。 ICU具有广泛的可移植性,可以在所有平台上以及C / C ++和Java软件之间为应用程序提供相同的结果。

    要下载图书馆,请转到here的下载页面 选择最新版本的 ICU4J ,如下图所示 Downloads Page
    您将被转移到另一个页面,您将找到一个包含所需组件的直接链接的框。请继续下载三个文件,您将在下一个图像中找到突出显示的文件。

    1. icu4j-docs.jar
    2. icu4j-src.jar
    3. icu4j.jar
    4. Files

      以下有关在 Netbeans IDE

      中创建和添加库的说明
      1. 导航到工具栏并单击工具
      2. 选择图书馆
      3. 在左下方,您会看到新的库按钮创建你的
      4. 导航到您在库列表
      5. 中创建的库
      6. 点击它并添加像这样的jar文件夹
      7. 在课程路径中添加icu4j.jar
      8. 在Sources
      9. 中添加icu4j-src.jar
      10. 在Javadoc中添加icu4j-docs.jar
      11. 从最右侧查看已打开的项目
      12. 展开要在
      13. 中使用库的项目
      14. 右键单击libraries文件夹,然后选择添加库
      15. 最后选择刚刚创建的库。
      16. 现在您已准备好使用该库,只需导入您想要的内容

        import com.ibm.icu.What_You_Want_To_Import;
        

        <小时/>

        如何使用库

        使用ArabicShaping Class并反转String,我们可以编写正确的附加阿拉伯语 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();
            }
        }
        

        这是输出

        Output

        我希望我已经完成了所有事情。

        更新:倒车后请务必再次拨回号码以获得相同的正确号码
        这里有几个可以提供帮助的功能

        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;
        }
        

答案 1 :(得分:2)

这是一个有效的代码。下载示例字体,例如trado.ttf

确保pdfbox-appicu4j 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;
    }
    }

}