Java pdfbox snapshot 2.0中的PDFTextStripper等效于什么
我目前正在使用pdfbox 1.8分析PDF文档。下面是我正在做的一个非常简单的例子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
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();