【问题标题】:How to get values out of these callbacks when reading a PDF?阅读 PDF 时如何从这些回调中获取值?
【发布时间】:2017-05-30 12:31:16
【问题描述】:

我正在尝试阅读 PDF 文件。下面的回调也打印消息,但我无法从 PDF 中获取任何信息。

    let pdfBundlePath = Bundle.main.path(forResource: "sample", ofType: "pdf")
    let pdfURL = URL.init(fileURLWithPath: pdfBundlePath!)
    let pdf = CGPDFDocument(pdfURL as CFURL)        

    let operatorTableRef = CGPDFOperatorTableCreate()

    CGPDFOperatorTableSetCallback(operatorTableRef!, "BT") { (scanner, info) in
        print("Begin text object")
    }
    CGPDFOperatorTableSetCallback(operatorTableRef!, "ET") { (scanner, info) in
        print("End text object")
    }
    CGPDFOperatorTableSetCallback(operatorTableRef!, "Tf") { (scanner, info) in
        print("Select font")
    }
    CGPDFOperatorTableSetCallback(operatorTableRef!, "Tj") { (scanner, info) in
        print("Show text")
    }
    CGPDFOperatorTableSetCallback(operatorTableRef!, "TJ") { (scanner, info) in
        print("Show text, allowing individual glyph positioning")
    }

        let page = pdf!.page(at: 1)
        let stream = CGPDFContentStreamCreateWithPage(page!)
        let scanner = CGPDFScannerCreate(stream, operatorTableRef, nil)
        CGPDFScannerScan(scanner)
        CGPDFScannerRelease(scanner)
        CGPDFContentStreamRelease(stream)

输出:

Begin text object
Select font
Show text, allowing individual glyph positioning
End text object

// the same output for at least 10 or more times.

但我不确定如何从中获取实际的字符串?任何建议将不胜感激。

【问题讨论】:

  • 是的,我有同样的麻烦,即使我想在 pdf 文档中搜索。我建议您阅读 Adob​​e 规范以了解我们正在尝试做什么,以及为什么它不那么容易:-) 创建一个 pdf paser 要复杂得多,正如我之前想象的那样。看到这个slideshare.net/KazYoshikawa/extracting-text-from-pdf-ios有一个想法:-)。对不起。我现在无法做出更好的答案,但我很早就开始“研究”如何做同样的事情,就像你想做的那样。
  • 感谢您的提示。但是,至少您可以从中打印出一些东西?这是目前最重要的。
  • 如果你能阅读 ObjC,Apple 发布了一份关于如何做到这一点的指南:developer.apple.com/library/content/documentation/…不确定它离解决你的问题有多近
  • @Hemang 不幸的是,不是:-(。我决定使用“天真的”方法。在 TextEdit 中我写了 Hello, World!。接下来我将它导出为 pdf 并尝试再次在 TextEdit 中打开它.过去两天我试图了解那里有什么:-),遵循Adobe规范......接下来,我对“空”文档和只有一个“空格”的文档做了同样的事情。结果“令人惊讶”。 Code Different 提到的指南对我没有任何帮助。
  • @user3441734:每个操作员接受扫描仪“堆栈”上的一些操作数。这是另一个演示如何解析内容的项目:github.com/KurtCode/PDFKitten。它也在 Objective-C 中,但应该看到总体思路。例如,“显示文本”运算符采用字符串操作数,该操作数可以通过CGPDFScannerPopString 获得。 – 但是您必须阅读 PDF 规范才能了解哪个运算符采用哪种操作数,这是没有办法的。

标签: ios swift cgpdf


【解决方案1】:

我有带有“hello, world”文本的 pdf(通过从 TextEdit 导出为 pdf 创建)

这个回调函数

CGPDFOperatorTableSetCallback(operatorTableRef!, "TJ") { (scanner, info) in
    print("Show text, allowing individual glyph positioning")
    var pa: CGPDFArrayRef?
    withUnsafeMutablePointer(to: &pa, { (ppa) -> () in
        let r = CGPDFScannerPopArray(scanner, ppa)
        print("TJ", r)
        if r {
            let count = CGPDFArrayGetCount(ppa.pointee!)
            var j = 0
            for i in 0..<count {
                var str: CGPDFStringRef?
                let r = CGPDFArrayGetString(ppa.pointee!, i, &str)
                if r {
                    let string = String(cString: CGPDFStringGetBytePtr(str!)!)
                    print(string, i, j)
                    j += 1
                }
            }
        }
    })
}

打印我

Show text, allowing individual glyph positioning
TJ true
h 0 0
e 2 1
l 4 2
l 6 3
o 8 4
, 10 5
  12 6
w 14 7
o 16 8
rl 18 9
d 20 10

我认为这表明,获取字符串是可能的 :-),至少对于拉丁字母而言。

对于Tj算子,回调函数可以很简单

CGPDFOperatorTableSetCallback(operatorTableRef!, "Tj") { (scanner, info) in
        print("Show text")
        var text: CGPDFStringRef?
        withUnsafeMutablePointer(to: &text, { (p) -> () in
            let r = CGPDFScannerPopString(scanner, p)
            if r {
                let string = String(cString: CGPDFStringGetBytePtr(p.pointee!)!)
                print(string)
            }
        })
    }

警告! 要正确显示所有字符,必须使用字体信息,但这是另一回事。对于拉丁字符,此解决方案应按原样工作。

为了能够“提取”所有字符串,必须实现所有文本显示运算符

更新 因为 PDFKit 在两个苹果平台上都可用(从 iOS11) 我建议使用它来提取文本。这个过程非常简单

【讨论】:

    猜你喜欢
    • 2019-11-16
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多