我的目标是从。pdf文件中提取文本,并将其写入Excel文件,而不会丢失文本格式。此时,我已经成功地从二维数组中提取了具有字体、大小和坐标的文本,但是我有一个小问题:同一行中的不同单词被组合成一个单词。
例如:020 | 0542 | CD45
它将在同一个单词中提取:0200542CD45
我找不到我的错误在哪里。我需要你的帮助。
这是我的代码:
public class PrintTextLocations extends PDFTextStripper {
public static StringBuilder tWord = new StringBuilder();
public static String[][] coordTab;
public static int p = 0;
public static String seek;
public static String[] seekA;
public static List<String> wordList = new ArrayList();
public static boolean is1stChar = true;
public static boolean lineMatch;
public static int pageNo = 1;
public static double lastYVal;
public PrintTextLocations() throws IOException {
super.setSortByPosition(true);
}
public static void main(String[] args) throws Exception {
PDDocument document = null;
PDFTextParser pdftext = new PDFTextParser();
String file_name = "d:/test.pdf";
seekA = pdftext.pdftoText(file_name).split(" ");
seek = pdftext.pdftoText(file_name);
coordTab = new String [seekA.length*2][6];
try {
File input = new File(file_name);
document = PDDocument.load(input);
if (document.isEncrypted()) {
document.decrypt("");
}
PrintTextLocations printer = new PrintTextLocations();
List allPages = document.getDocumentCatalog().getAllPages();
for (int i = 0; i < allPages.size(); i++) {
PDPage page = (PDPage) allPages.get(i);
PDStream contents = page.getContents();
if (contents != null) {
printer.processStream(page, page.findResources(), page.getContents().getStream());
}
pageNo += 1;
}
} finally {
if (document != null) {
for (int k = 0; k<= p;k++){
System.out.println(k+" : "+coordTab[k][0]+" | "+coordTab[k][1]+" | "+coordTab[k][2]+" | "+coordTab[k][3]+" | "+coordTab[k][4]+" | "+coordTab[k][5]);
}
myxls.close();
document.close();
}
}
}
@Override
protected void processTextPosition(TextPosition text) {
String tChar = text.getCharacter();
String REGEX = "'' ";
char c = tChar.charAt(0);
lineMatch = matchCharLine(text);
if (!Character.isWhitespace(c)) {
if ((!is1stChar) && (lineMatch == true)) {
appendChar(tChar);
} else if (is1stChar == true) {
setWordCoord(text, tChar);
}
} else {
endWord();
}
}
protected void appendChar(String tChar) {
tWord.append(tChar);
coordTab[p][3] = String.valueOf(tWord);
is1stChar = false;
}
protected void setWordCoord(TextPosition text, String tChar) {
tWord.append(tChar);
coordTab[p][0] = ""+ pageNo;
coordTab[p][1] = ""+ roundVal(Float.valueOf(text.getX()));
coordTab[p][2] = ""+ roundVal(Float.valueOf(text.getY()));
coordTab[p][3] = String.valueOf(tWord);
coordTab[p][4] = ""+text.getFontSize();
coordTab[p][5] = ""+text.getFont().getBaseFont();
is1stChar = false;
}
protected void endWord() {
String newWord = tWord.toString().replaceAll("[^\x00-\x7F]", "");
String sWord = newWord.substring(newWord.lastIndexOf(' ') + 1);
if (!"".equals(sWord)) {
if (Arrays.asList(seekA).contains(sWord)) {
wordList.add(newWord);
} else {
wordList.add(newWord);
}
}
tWord.delete(0, tWord.length());
is1stChar = true;
p++;
}
protected boolean matchCharLine(TextPosition text) {
Double yVal = roundVal(Float.valueOf(text.getY()));
if (yVal.doubleValue() == lastYVal) {
return true;
}
lastYVal = yVal.doubleValue();
endWord();
return false;
}
protected Double roundVal(Float yVal) {
DecimalFormat rounded = new DecimalFormat("###.##");
String st = rounded.format(yVal);
Double yValDub = Double.parseDouble(st.replace(",", "."));
return yValDub;
}
}
缺失的空格
在这方面的错误是,您假设单词之间的空白是由作为空格字符提取的空符号创建的。这是不需要的!
也可以通过显式转发x位置来创建这些间隙。
由于您只查看文本原点(matchCharLine
中的TextPosition.getY()
)的y坐标,而忽略了它的x坐标(TextPosition.getX()
),因此您错过了这样的间隙。
您假定检索TextPosition
实例的顺序是"正确的"顺序。
这是不需要的!
文本的符号可能以随机顺序绘制,因此您可能以随机顺序接收它们。
完全随机的顺序很少出现,但偶尔会使用某种程度的重新排序。
该怎么做
PDFBox PDFTextStripper
类实际上已经使用了经过充分测试的例程来添加空格,并对无序的字形进行排序。但是,通过重写processTextPosition
,您阻止了该代码的使用。
因此,您不应该替换processTextPosition
方法,而应该覆盖writeString(String, List<TextPosition>)
和writeWordSeparator()
方法。
对于自动排序的字形只需使用setSortByPosition(true)
。