Java pdfbox snapshot 2.0中的PDFTextStripper等效于什么

Java pdfbox snapshot 2.0中的PDFTextStripper等效于什么,java,pdf,pdfbox,Java,Pdf,Pdfbox,我目前正在使用pdfbox 1.8分析PDF文档。下面是我正在做的一个非常简单的例子 import java.util.List; import java.io.IOException; import javax.swing.JFileChooser; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmode

我目前正在使用pdfbox 1.8分析PDF文档。下面是我正在做的一个非常简单的例子

 import java.util.List;
 import java.io.IOException;
 import javax.swing.JFileChooser;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.pdfbox.pdmodel.common.PDStream;

 public class Main 
 {
   private static PDDocument reader;

   public static void main(String[] args)
   {
       JFileChooser chooser = new JFileChooser();
       int result = chooser.showOpenDialog(null);
       if(result == JFileChooser.APPROVE_OPTION)
       {
           try
           {
               reader = PDDocument.load(chooser.getSelectedFile());
               for(int pagenum = 1; pagenum <= reader.getNumberOfPages(); pagenum++)
               {
                   System.out.println("===== Page:" + pagenum + " ======");
                   System.out.println(extract(pagenum));
               }

           }
           catch(Exception e) { e.printStackTrace(); }

       }
   }

   public static String extract(int pagenum) throws IOException
   {
       List allPages = reader.getDocumentCatalog().getAllPages();
       PDPage page = (PDPage) allPages.get(pagenum-1);
       PDStream contents = page.getContents();
       CustomPDFTextStripper stripper = new CustomPDFTextStripper();        
       if (contents != null) 
       {
           stripper.processStream(page, page.findResources(), page.getContents().getStream());
       }
       return stripper.getContents();
   }
 }
我似乎无法在PDFBOX2.0快照中找到等效的解决方案(我知道它不稳定,尚未发布)。我试着使用类似于:

 CustomPDFTextStripper stripper = new CustomPDFTextStripper();        
 StringWriter dummy = new StringWriter();
 stripper.setPageStart(""+(pagenum-1));
 stripper.setPageEnd(""+(pagenum-1));
 stripper.writeText(reader, dummy);
但在ProcessTextPosition方法中,它不处理空间或提供准确的textPos数据

关于如何获得与2.0中的1.8相同的所有TextPostion数据,有什么想法吗

=========编辑2015年6月26日下午8:00中央标准时间===========

好的,我花了一些时间来研究它,发现了问题。getWidthOfSpace()返回1.8和2.0之间截然不同的结果

在1.8中,字符宽度约为2.49-字符宽度约为5

在2.0中,字符的宽度约为27.5-字符的宽度约为5

显然27.5在2.0中是错误的

只需运行以下测试,您将看到

 @Override
 protected void processTextPosition(TextPosition textPos)
 {
    float spaceWidth = textPos.getWidthOfSpace();
    float width = textPos.getWidth();
    System.out.println(textPos.getCharacter() + " - Width of Space=" + spaceWidth + " - width=" + width);
    builder.append(textPos.getCharacter());
 }
(当然是2.0的getUnicode()而不是getCharacter())

====编辑2015年6月27日下午8:00中央标准时间======

以下是测试中使用的PDF的链接:

当前对空间宽度的计算确实存在错误
PDFTextStreamEngine.showGlyph(矩阵、PDFont、int、字符串、向量)
当前(这是一个快照,今晚的情况可能有所不同)计算的宽度如下:

float horizontalScalingText = getGraphicsState().getTextState().getHorizontalScaling()/100f;
[...]
// the space width has to be transformed into display units
float spaceWidthDisplay = spaceWidthText * fontSizeText * horizontalScalingText *
        textRenderingMatrix.getScalingFactorX()  * ctm.getScalingFactorX();
(修订版1688116)

但是
textRenderingMatrix
是在
PDFStreamEngine.showText(byte[])
中使用以下方法计算的:

float horizontalScaling = textState.getHorizontalScaling() / 100f;
[...]
Matrix parameters = new Matrix(
        fontSize * horizontalScaling, 0, // 0
        0, fontSize,                     // 0
        0, textState.getRise());         // 1
[...]
Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);
(修订版1688116)

因此,字体大小和水平缩放都会乘以两倍的空间宽度。此外,当前转换矩阵被完全乘以
textrendingmatrix
,部分用作
ctm.getScalingFactorX()
;这可能是最有趣的组合结果

PDFTextStreamEngine.showGlyph(矩阵、PDFont、int、字符串、向量)


在版本1.8.9中,文本空间宽度的计算方法如下所示:在
PDFStreamEngine.processEncodedText(byte[])


对于有趣的当前转换和文本矩阵,这也会产生有趣的结果,但上述有趣的因素并没有在结果中乘以两次

如果这适用于1.8而不适用于2.0(尤其是PrintTextLocations示例),那么请与JIRA一起打开一个问题并附上您的PDF。如果您今天刚刚下载,这也将是一个临时错误。尝试使用2天前的修订版。或者,使用当前版本,恢复文件BaseParser.java中的最后一个更改(版本1687653),然后重新构建它。或者看看PDFBOX-2301中的评论,它可能会在本周末修复。我没有用上面的代码检查2.0-用我复杂的原始代码和TextPosition数据检查是错误的。明天晚上,我将检查上述代码并按照您的建议进行操作。请指出您所说的TextPosition数据是错误的。此外,关于:我没有用上面的代码检查2.0-请提供可用于重现该问题的代码。您可以共享一个示例PDF来重现该问题吗?感谢您提供的信息-我能够通过以下内容获得正确的空格宽度:float spaceWidth=textPos.getFont().getSpaceWidth()*textPos.getTextMatrix().getScaleX()/1000;我会将您的答案标记为解决方案,并密切关注未来的快照-谢谢*我能够通过以下内容获得正确的空间宽度*-恐怕这只在某些情况下有效,因为它忽略了几个因素。
float horizontalScaling = textState.getHorizontalScaling() / 100f;
[...]
Matrix parameters = new Matrix(
        fontSize * horizontalScaling, 0, // 0
        0, fontSize,                     // 0
        0, textState.getRise());         // 1
[...]
Matrix textRenderingMatrix = parameters.multiply(textMatrix).multiply(ctm);
float spaceWidthDisp = spaceWidthText * fontSizeText * horizontalScalingText 
                        * textMatrix.getXScale() * ctm.getXScale();