【问题标题】:Android PDF Writer(APW) EncondingAndroid PDF Writer(APP) 编码
【发布时间】:2013-10-12 02:15:59
【问题描述】:

我正在使用 Android PDF Write(APW) 创建 PDF,但它不适用于某些特殊字符(葡萄牙语)。

mypdf.addText(170, 50, 40,"Coração");

标准的编码是:

mypdf.setFont(StandardFonts.SUBTYPE, StandardFonts.COURIER, StandardFonts.WIN_ANSI_ENCODING);
outputToFile("helloworld.pdf",pdfcontent,"ISO-8859-1");

我试过了

outputToFile("helloworld.pdf",pdfcontent,"UTF-8");
outputToFile("helloworld.pdf",pdfcontent,"UTF-16");
outputToFile("helloworld.pdf",pdfcontent,"Cp1252");

并没有成功。 有什么想法我应该怎么做?

编辑

方法 outputToFile 定义为:

    private void outputToFile(String fileName, String pdfContent, String encoding) {
    File newFile = new File(Environment.getExternalStorageDirectory() + "/" + fileName);
    try {
        newFile.createNewFile();
        try {
            FileOutputStream pdfFile = new FileOutputStream(newFile);
            pdfFile.write(pdfContent.getBytes(encoding));
            pdfFile.close();
        } catch(FileNotFoundException e) {
            //
        }
    } catch(IOException e) {
        //
    }
}

方法addText定义为:

    public void addText(int leftPosition, int topPositionFromBottom, int fontSize, String text, String transformation) {
    addContent(
        "BT\n" +
        transformation + " " + Integer.toString(leftPosition) + " " + Integer.toString(topPositionFromBottom) + " Tm\n" +
        "/F" + Integer.toString(mPageFonts.size()) + " " + Integer.toString(fontSize) + " Tf\n" +
        "(" + text + ") Tj\n" +
        "ET\n"
    );
}

此外,我将字体颜色更改为白色,添加以下原始内容:

mypdf.addRawContent("1 1 1 rg\n"); 

然后我回到黑色字体颜色:

    mypdf.addRawContent("0 0 0 rg\n");

【问题讨论】:

  • outputToFile 做什么?有人要求快速查看 APW 的来源,这似乎表明它在字体和编码方面不是很灵活。
  • 啊,我假设来自 PDFWriterDemo。首先:因为字符串包含偏移量引用,您不得使用多字节或可变字节数编码。实际上,APW 在这里返回的是字符串而不是字节数组,这是相当荒谬的。 Pdf 文档不是文本。话虽如此,您应该显示实际添加特殊字符的代码,包括用于创建和选择字体对象的代码。
  • 好的,但是如何设置在mypdf.addText(170, 50, 40,"Coração") 行之前使用的字体?我问这个的原因是,根据您选择的字体,您的字符串所需的编码可能会有所不同,并且您的字符可能根本无法选择!例如。 ã (atilde) 在内置编码中可能有八进制值 213、343 或 343(MacRomanEncoding、WinAnsiEncoding、PDFDocEncoding,参见 PDF 的附件 D specification),并且您使用的字体必须包含字符开始。

标签: android pdf encoding


【解决方案1】:

我将提供的所有信息,编写了以下简单的单元测试方法并运行它。

public void test19192108()
{
    PDFWriter mPDFWriter = new PDFWriter(PaperSize.FOLIO_WIDTH, PaperSize.FOLIO_HEIGHT);
    mPDFWriter.setFont(StandardFonts.SUBTYPE, StandardFonts.COURIER, StandardFonts.WIN_ANSI_ENCODING);
    mPDFWriter.addText(170, 50, 40,"Coração");

    String pdfcontent = mPDFWriter.asString();
    outputToFile("helloworld19192108.pdf",pdfcontent,"ISO-8859-1");
}

outputToFile是 APW PDFWriterDemo 类的辅助方法)

结果如下:

这似乎满足了预期。

因此,无论以何种方式它不适用于 OP 的某些特殊字符(葡萄牙语),都会丢失一些用于重现问题的重要信息。

PS:根据开发环境的设置,源代码中的非 ASCII 字符可能存在问题。因此,替换可能是个好主意

    mPDFWriter.addText(170, 50, 40,"Coração");

    mPDFWriter.addText(170, 50, 40,"Cora\u00e7\u00e3o");

PPS:Adobe Reader 在查看像这样生成的文件后想要修复它。原因是交叉引用表坏了。为它生成条目的代码是这样的:

public void addObjectXRefInfo(int ByteOffset, int Generation, boolean InUse) {
    StringBuilder sb = new StringBuilder();
    sb.append(String.format("%010d", ByteOffset));
    sb.append(" ");
    sb.append(String.format("%05d", Generation));
    if (InUse) {
        sb.append(" n ");
    } else {
        sb.append(" f ");
    }
    sb.append("\r\n");
    mList.add(sb.toString());
}

(来自CrossReferenceTable.java

计算这个条目中的字符,我们得到 10 + 1 + 5 + 3 + 2 = 21。

但根据规范:

每个条目的长度应为 20 个字节,包括行尾标记

(来自第 7.5.4 节ISO 32000-1 的交叉引用表

在使用(当前版本)Android PDF Writer 时,您也应该修复此代码。

【讨论】:

  • 我没有提到的是我改变了颜色,将rawcontent添加到文件中,像这样:mypdf.addRawContent("1 1 1 rg\n");对吗?
  • 您尚未提及的内容,还包括完全不适合您的内容。到目前为止,我只看到只要不计算交叉引用问题,事情就会起作用。
  • 我不知道你是否可以改变颜色,因为你不知道究竟是什么不适合你
  • 您,先生,是圣人!我对 Adob​​e 添加的元信息非常着迷,以至于我什至没有注意到交叉引用表的错误!非常感谢您的出色回答!我真的因为压力太大而变老了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 1970-01-01
  • 2022-11-13
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 2015-09-09
相关资源
最近更新 更多