2010-07-08 7 views
51

के साथ पीडीएफ फाइलों (विशेष रूप से तालिकाओं के साथ) को पार्स करना मुझे एक पीडीएफ फाइल को पार्स करने की ज़रूरत है जिसमें टैब्यूलर डेटा शामिल है। मैं बाद में परिणाम (स्ट्रिंग) को पार्स करने के लिए फ़ाइल टेक्स्ट निकालने के लिए PDFBox का उपयोग कर रहा हूं। समस्या यह है कि टेक्स्ट निष्कर्षण काम नहीं करता है क्योंकि मुझे टैब्यूलर डेटा की उम्मीद है। उदाहरण के लिए, मैं एक फ़ाइल जो इस तरह एक मेज शामिल है तो फिरपीडीएफबॉक्स

+----------------------------------------------------------------+ 
| AIH | Value | Complexity      | Financing  | 
|  |  | Medium | High | Not applicable | MAC/Other | FAE | 
+----------------------------------------------------------------+ 
| xyz | 12.43 | 12.34 |  |    | 12.34  |  | 
+----------------------------------------------------------------+ 
| abc | 1.56 |  | 1.56 |    |   | 1.56| 
+----------------------------------------------------------------+ 

मैं PDFBox का उपयोग करें: (7 कॉलम: पहले दो हमेशा डेटा है, केवल एक जटिलता स्तंभ डेटा है, केवल एक ही वित्त पोषण स्तंभ डेटा है) : डेटा की

PDDocument document = PDDocument.load(pathToFile); 
PDFTextStripper s = new PDFTextStripper(); 
String content = s.getText(document); 

उन दो लाइनें इस तरह निकाला जा होगा:

xyz 12.43 12.4312.43 
abc 1.56 1.561.56 

पिछले दो संख्याओं के बीच कोई सफेद रिक्त स्थान हैं, लेकिन यह सबसे बड़ी समस्या नहीं है। समस्या यह है कि मुझे नहीं पता कि पिछले दो संख्याओं का क्या अर्थ है: मध्यम, उच्च, लागू नहीं है? मैक/अन्य, एफएई? मेरे पास संख्याओं और उनके कॉलम के बीच संबंध नहीं है।

मेरे लिए पीडीएफबॉक्स लाइब्रेरी का उपयोग करने की आवश्यकता नहीं है, इसलिए एक अन्य लाइब्रेरी का उपयोग करने वाला समाधान ठीक है। मैं जो चाहता हूं वह फ़ाइल को पार्स करने में सक्षम होना चाहिए और यह जानना कि प्रत्येक पार्स किए गए नंबर का क्या अर्थ है।

+9

गुड लक ... मैं पीडीएफ नरक में अपने आप को पूरी तरह से इस बिंदु पर हूँ, और प्रारूप के साथ काफी निराश। – Fosco

+20

पीडीएफ को आउटपुट डिस्प्ले प्रारूप के रूप में डिज़ाइन किया गया था, निष्कर्षण के लिए नहीं। उपयोगकर्ताओं को दोष दें, स्वरूप नहीं। –

+0

यदि पीडीएफ एक निश्चित लेआउट का है तो कॉलम से डेटा निकालने के अन्य तरीके हैं। मैंने सिर्फ एक फॉर्म पर निश्चित फ़ील्ड स्थितियों से पीडीएफ पाठ निकालने के लिए एक उपकरण लिखा है।पीडीएफ फाइल देखना दिलचस्प होगा कि मैथ्यूस का जिक्र है। –

उत्तर

-1

मैं पीडीएफबॉक्स से परिचित नहीं हूं, लेकिन आप itext को देखने का प्रयास कर सकते हैं। हालांकि होमपेज पीडीएफ पीढ़ी कहता है, आप पीडीएफ मैनिपुलेशन और निष्कर्षण भी कर सकते हैं। एक नज़र डालें और देखें कि यह आपके उपयोग के मामले में फिट बैठता है या नहीं।

+1

क्या आपके पास फ़ाइल सामग्री निकालने के लिए itext का उपयोग करने का कोई उदाहरण है? –

+0

मुझे iText का उपयोग करके सामग्री को पढ़ने का एक आसान तरीका मिला लेकिन इससे मेरी मदद नहीं हुई। पीडीएफटेक्स्ट एक्स्ट्रेक्टर का उपयोग करना मुझे पीडीएफबॉक्स का उपयोग करने के समान परिणाम मिलता है। :-( –

+0

यह थोड़ी देर हो गया है, लेकिन क्या यह पीडीएफ रीडर नहीं है .getContent()? –

2

पीडीएफ से डेटा निकालना समस्याओं से भरा हुआ है। क्या दस्तावेज़ किसी प्रकार की स्वचालित प्रक्रिया के माध्यम से बनाए गए हैं? यदि ऐसा है, तो आप पीडीएफ को असम्पीडित पोस्टस्क्रिप्ट (पीडीएफ 2 एसपीएस आज़माएं) में परिवर्तित करने पर विचार कर सकते हैं और देख सकते हैं कि पोस्टस्क्रिप्ट में कुछ प्रकार के नियमित पैटर्न हैं जिनका आप शोषण कर सकते हैं।

-1

छवि पर प्रिंट करने और उस पर ओसीआर करने के बारे में कैसे?

बहुत अप्रभावी लगता है, लेकिन व्यावहारिक रूप से पाठ को पहुंचने योग्य बनाने के लिए पीडीएफ का बहुत ही उद्देश्य है, आपको जो करना होगा वह आपको करना होगा।

+0

मान लीजिए कि क्या आप ओसीआर टेबल को पढ़ सकते हैं, इस पर गठबंधन कर सकते हैं? – markdigi

+0

@markdigi: मुझे ओसीआर सॉफ्टवेयर के साथ बहुत कम अनुभव है। कुछ बहुत बेकार रीडआईरिस कहा जाता है जो मेरे एचपी प्रिंटर के साथ मुक्त हो गया, और एक आश्चर्यजनक रूप से सक्षम, अभी तक उचित मूल्य वाला उत्पाद जिसे एबीबी फाइन रीडर (मुझे लगता है) कहा जाता है। अगर मुझे सही याद है, तो दोनों एमएस वर्ड प्रारूप में टेबल के साथ दस्तावेज पढ़ने में सक्षम हैं, और इसमें टेबल शामिल हैं। कृपया इस जानकारी को आगे की खोज के लिए एक संकेत के रूप में लें, एक ठोस सिफारिश नहीं। –

+1

ओसीआरिंग व्यर्थ होगा क्योंकि आपके पास वास्तविक चरित्र और एक्स, वाई स्थान कम से कम किसी भी पीडीएफ एपीआई –

18

आपको एक उपयोगी प्रारूप में डेटा निकालने के लिए एक एल्गोरिदम तैयार करने की आवश्यकता होगी। आप जिस पीडीएफ लाइब्रेरी का उपयोग करते हैं, भले ही आपको यह करने की आवश्यकता होगी। अक्षरों और ग्राफिक्स को राज्य के ड्राइंग संचालन की एक श्रृंखला द्वारा खींचा जाता है, यानी स्क्रीन पर इस स्थिति में स्थानांतरित करें और चरित्र 'सी' के लिए ग्लिफ खींचें।

मेरा सुझाव है कि आप org.apache.pdfbox.pdfviewer.PDFPageDrawer बढ़ाएं और strokePath विधि को ओवरराइड करें। वहां से आप क्षैतिज और ऊर्ध्वाधर रेखा खंडों के लिए ड्राइंग ऑपरेशंस को रोक सकते हैं और उस तालिका का उपयोग अपनी तालिका के लिए कॉलम और पंक्ति स्थितियों को निर्धारित करने के लिए कर सकते हैं। फिर यह टेक्स्ट क्षेत्रों को स्थापित करने और यह निर्धारित करने का एक साधारण मामला है कि किस क्षेत्र में कौन से नंबर/अक्षर/अक्षर खींचे जाते हैं। चूंकि आप क्षेत्रों के लेआउट को जानते हैं, इसलिए आप यह बताने में सक्षम होंगे कि एक्स्ट्राक्टेड टेक्स्ट किस कॉलम से संबंधित है।

इसके अलावा, आपके पास दृश्यमान रूप से अलग किए गए पाठ के बीच रिक्त स्थान नहीं होने का कारण यह है कि अक्सर, एक स्पेस कैरेक्टर पीडीएफ द्वारा नहीं खींचा जाता है। इसके बजाय टेक्स्ट मैट्रिक्स को अद्यतन किया गया है और अगले चरण को आकर्षित करने के लिए 'चाल' के लिए एक ड्राइंग कमांड जारी किया गया है और अंतिम स्थान के अलावा "स्पेस चौड़ाई" जारी की गई है।

शुभकामनाएं।

+0

यह टूल उपर्युक्त जैसा कुछ प्रतीत होता है, और कुछ स्रोत कोड उपलब्ध हैं http://www.jpedal.org/support_egTZ.php –

+0

मैंने हाल ही में कुछ ऐसा किया, सिवाय इसके कि मुझे टेक्स्ट की कई पंक्तियों से निपटना पड़ा। कॉलम और पंक्तियों के बाद वास्तविक पाठ को कैसे निकालना है, यह जानने के लिए कक्षाओं के एक्स्ट्रेक्ट टेक्स्ट सेट पर भी नज़र डालें। एक और नोट पर, मुझे पंक्तियों को सही करने में समस्याएं थीं, लेकिन जब मैं कॉलम वापस चला गया तो एक नई पंक्ति मानकर समायोजित करने में सक्षम था। – deterb

+0

@deterb आपने मल्टीलाइन टेक्स्ट कैसे संभाला? –

0

http://swftools.org/ इन लोगों के पास एक पीडीएफ 2 एसडब्ल्यूएफ घटक है। वे टेबल दिखाने में भी सक्षम हैं। वे स्रोत भी दे रहे हैं। तो आप संभवतः इसे देख सकते हैं।

9

मेरे उत्तर के लिए बहुत देर हो सकती है, लेकिन मुझे लगता है कि यह मुश्किल नहीं है। आप PDFTextStripper क्लास का विस्तार कर सकते हैं और writePage() और processTextPosition (...) विधियों को ओवरराइड कर सकते हैं। आपके मामले में मुझे लगता है कि कॉलम हेडर हमेशा समान होते हैं। इसका मतलब है कि आप प्रत्येक कॉलम शीर्षक के एक्स-समन्वय को जानते हैं और आप कॉलम शीर्षकों के लिए संख्याओं के एक्स-समन्वय की तुलना कर सकते हैं। अगर वे काफी करीब हैं (आपको यह तय करने के लिए परीक्षण करना होगा कि कितना करीब है) तो आप कह सकते हैं कि वह संख्या उस कॉलम से संबंधित है।

एक और दृष्टिकोण "charactersByArticle" वेक्टर रोकना होगा के बाद प्रत्येक पृष्ठ लिखा है:

@Override 
public void writePage() throws IOException { 
    super.writePage(); 
    final Vector<List<TextPosition>> pageText = getCharactersByArticle(); 
    //now you have all the characters on that page 
    //to do what you want with them 
} 

अपने कॉलम जानने के बाद, आप क्या स्तंभ हर नंबर के अंतर्गत आता है तय करने के लिए एक्स-निर्देशांक की अपनी तुलना कर सकते हैं ।

आपके पास संख्याओं के बीच कोई स्थान नहीं है क्योंकि आपको शब्द विभाजक स्ट्रिंग सेट करना है।

मुझे आशा है कि यह आपके लिए या दूसरों के लिए उपयोगी है जो समान चीजों की कोशिश कर रहे हैं।

4

मुझे pdftotext उपयोगिता (सुडो एपीटी-इंस्टॉल पॉपप्लर-यूटिल्स) द्वारा उत्पन्न पाठ फ़ाइलों को पार्स करने में अच्छी सफलता मिली है।

File convertPdf() throws Exception { 
    File pdf = new File("mypdf.pdf"); 
    String outfile = "mytxt.txt"; 
    String proc = "/usr/bin/pdftotext"; 
    ProcessBuilder pb = new ProcessBuilder(proc,"-layout",pdf.getAbsolutePath(),outfile); 
    Process p = pb.start(); 

    p.waitFor(); 

    return new File(outfile); 
} 
+1

उन विंडोज़ उपयोगकर्ताओं के लिए आपकी एक्सई फ़ाइल डाउनलोड करें: http://www.foolabs.com/xpdf/download.html वैरिएबल प्रो को pdftotext.exe फ़ाइल पर इंगित करें। मुख्य फ़ंक्शन में निष्पादित होने पर फ़ंक्शन प्रकार को हटाएं और फ़ंक्शन का कीवर्ड वापस करें। –

7

आप पीडीएफबॉक्स में क्षेत्र द्वारा टेक्स्ट निकाल सकते हैं। ExtractByArea.java उदाहरण फ़ाइल, pdfbox-examples आर्टिफ़ैक्ट में यदि आप मेवेन का उपयोग कर रहे हैं तो देखें। एक स्निपेट

PDFTextStripperByArea stripper = new PDFTextStripperByArea(); 
    stripper.setSortByPosition(true); 
    Rectangle rect = new Rectangle(464, 59, 55, 5); 
    stripper.addRegion("class1", rect); 
    stripper.extractRegions(page); 
    String string = stripper.getTextForRegion("class1"); 

समस्या को पहली जगह निर्देशांक मिल रहा है। मैंने सामान्य TextStripper को processTextPosition(TextPosition text) ओवरराइड करने में सफलता हासिल की है और प्रत्येक चरित्र के लिए निर्देशांक प्रिंट कर रहे हैं और यह पता लगाया है कि वे कहां हैं।

लेकिन कम से कम यदि आप मैक पर हैं तो एक बहुत आसान तरीका है। पूर्वावलोकन में पीडीएफ खोलें, ⌘ मैं इंस्पेक्टर को दिखाने के लिए, फसल टैब का चयन करें और सुनिश्चित करें कि इकाइयां पॉइंट्स में हैं, टूल मेनू से आयताकार चयन चुनें, और रुचि के क्षेत्र का चयन करें। यदि आप एक क्षेत्र का चयन करते हैं, तो इंस्पेक्टर आपको निर्देशांक दिखाएगा, जिसे आप Rectangle कन्स्ट्रक्टर तर्कों में गोल और फ़ीड कर सकते हैं। पहली विधि का उपयोग करके आपको केवल यह पुष्टि करने की आवश्यकता है कि मूल कहां है।

+0

पीडीएफ के पास एक निश्चित लेआउट के लिए अच्छा, सरल समाधान! मैकोज़ में पूर्वावलोकन का उपयोग करने की चाल के लिए एक और अपवॉट (अगर मैं कर सकता था!) ​​दे दूंगा। निष्कर्षण वास्तव में आसान बनाता है। – Matthias

-1

पीडीएफ फ़ाइल से तालिका की सामग्री पढ़ने के लिए, आपको केवल किसी भी एपीआई का उपयोग करके पीडीएफ फ़ाइल को टेक्स्ट फ़ाइल में परिवर्तित करना होगा (मैंने iText के PdfTextExtracter.getTextFromPage() का उपयोग किया है) और फिर उस txt फ़ाइल को पढ़ें अपने जावा कार्यक्रम द्वारा .. अब इसे पढ़ने के बाद प्रमुख कार्य किया जाता है .. आपको अपनी ज़रूरत के डेटा को फ़िल्टर करना होगा। आप इसे स्ट्रिंग क्लास के स्प्लिट विधि का उपयोग करके लगातार कर सकते हैं जब तक कि आपको अपनी intrest का रिकॉर्ड न मिल जाए .. यहां मेरा कोड है जिसके द्वारा मैंने पीडीएफ फ़ाइल द्वारा रिकॉर्ड का हिस्सा निकाला है और इसे एक सीएसवी फ़ाइल में लिख दिया है। पीडीएफ का यूआरएल फ़ाइल है .. http://www.cea.nic.in/reports/monthly/generation_rep/actual/jan13/opm_02.pdf

कोड: -

public static void genrateCsvMonth_Region(String pdfpath, String csvpath) { 
     try { 
      String line = null; 
      // Appending Header in CSV file... 
      BufferedWriter writer1 = new BufferedWriter(new FileWriter(csvpath, 
        true)); 
      writer1.close(); 
      // Checking whether file is empty or not.. 
      BufferedReader br = new BufferedReader(new FileReader(csvpath)); 

      if ((line = br.readLine()) == null) { 
       BufferedWriter writer = new BufferedWriter(new FileWriter(
         csvpath, true)); 
       writer.append("REGION,"); 
       writer.append("YEAR,"); 
       writer.append("MONTH,"); 
       writer.append("THERMAL,"); 
       writer.append("NUCLEAR,"); 
       writer.append("HYDRO,"); 
       writer.append("TOTAL\n"); 
       writer.close(); 
      } 
      // Reading the pdf file.. 
      PdfReader reader = new PdfReader(pdfpath); 
      BufferedWriter writer = new BufferedWriter(new FileWriter(csvpath, 
        true)); 

      // Extracting records from page into String.. 
      String page = PdfTextExtractor.getTextFromPage(reader, 1); 
      // Extracting month and Year from String.. 
      String period1[] = page.split("PEROID"); 
      String period2[] = period1[0].split(":"); 
      String month[] = period2[1].split("-"); 
      String period3[] = month[1].split("ENERGY"); 
      String year[] = period3[0].split("VIS"); 

      // Extracting Northen region 
      String northen[] = page.split("NORTHEN REGION"); 
      String nthermal1[] = northen[0].split("THERMAL"); 
      String nthermal2[] = nthermal1[1].split(" "); 

      String nnuclear1[] = northen[0].split("NUCLEAR"); 
      String nnuclear2[] = nnuclear1[1].split(" "); 

      String nhydro1[] = northen[0].split("HYDRO"); 
      String nhydro2[] = nhydro1[1].split(" "); 

      String ntotal1[] = northen[0].split("TOTAL"); 
      String ntotal2[] = ntotal1[1].split(" "); 

      // Appending filtered data into CSV file.. 
      writer.append("NORTHEN" + ","); 
      writer.append(year[0] + ","); 
      writer.append(month[0] + ","); 
      writer.append(nthermal2[4] + ","); 
      writer.append(nnuclear2[4] + ","); 
      writer.append(nhydro2[4] + ","); 
      writer.append(ntotal2[4] + "\n"); 

      // Extracting Western region 
      String western[] = page.split("WESTERN"); 

      String wthermal1[] = western[1].split("THERMAL"); 
      String wthermal2[] = wthermal1[1].split(" "); 

      String wnuclear1[] = western[1].split("NUCLEAR"); 
      String wnuclear2[] = wnuclear1[1].split(" "); 

      String whydro1[] = western[1].split("HYDRO"); 
      String whydro2[] = whydro1[1].split(" "); 

      String wtotal1[] = western[1].split("TOTAL"); 
      String wtotal2[] = wtotal1[1].split(" "); 

      // Appending filtered data into CSV file.. 
      writer.append("WESTERN" + ","); 
      writer.append(year[0] + ","); 
      writer.append(month[0] + ","); 
      writer.append(wthermal2[4] + ","); 
      writer.append(wnuclear2[4] + ","); 
      writer.append(whydro2[4] + ","); 
      writer.append(wtotal2[4] + "\n"); 

      // Extracting Southern Region 
      String southern[] = page.split("SOUTHERN"); 

      String sthermal1[] = southern[1].split("THERMAL"); 
      String sthermal2[] = sthermal1[1].split(" "); 

      String snuclear1[] = southern[1].split("NUCLEAR"); 
      String snuclear2[] = snuclear1[1].split(" "); 

      String shydro1[] = southern[1].split("HYDRO"); 
      String shydro2[] = shydro1[1].split(" "); 

      String stotal1[] = southern[1].split("TOTAL"); 
      String stotal2[] = stotal1[1].split(" "); 

      // Appending filtered data into CSV file.. 
      writer.append("SOUTHERN" + ","); 
      writer.append(year[0] + ","); 
      writer.append(month[0] + ","); 
      writer.append(sthermal2[4] + ","); 
      writer.append(snuclear2[4] + ","); 
      writer.append(shydro2[4] + ","); 
      writer.append(stotal2[4] + "\n"); 

      // Extracting eastern region 
      String eastern[] = page.split("EASTERN"); 

      String ethermal1[] = eastern[1].split("THERMAL"); 
      String ethermal2[] = ethermal1[1].split(" "); 

      String ehydro1[] = eastern[1].split("HYDRO"); 
      String ehydro2[] = ehydro1[1].split(" "); 

      String etotal1[] = eastern[1].split("TOTAL"); 
      String etotal2[] = etotal1[1].split(" "); 
      // Appending filtered data into CSV file.. 
      writer.append("EASTERN" + ","); 
      writer.append(year[0] + ","); 
      writer.append(month[0] + ","); 
      writer.append(ethermal2[4] + ","); 
      writer.append(" " + ","); 
      writer.append(ehydro2[4] + ","); 
      writer.append(etotal2[4] + "\n"); 

      // Extracting northernEastern region 
      String neestern[] = page.split("NORTH"); 

      String nethermal1[] = neestern[2].split("THERMAL"); 
      String nethermal2[] = nethermal1[1].split(" "); 

      String nehydro1[] = neestern[2].split("HYDRO"); 
      String nehydro2[] = nehydro1[1].split(" "); 

      String netotal1[] = neestern[2].split("TOTAL"); 
      String netotal2[] = netotal1[1].split(" "); 

      writer.append("NORTH EASTERN" + ","); 
      writer.append(year[0] + ","); 
      writer.append(month[0] + ","); 
      writer.append(nethermal2[4] + ","); 
      writer.append(" " + ","); 
      writer.append(nehydro2[4] + ","); 
      writer.append(netotal2[4] + "\n"); 
      writer.close(); 

     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 

    } 
2

मैं pdf फ़ाइल जिसमें डेटा तालिका प्रारूप में है पढ़ने में एक ही समस्या थी। पीडीएफबॉक्स का उपयोग करके नियमित पार्स के बाद प्रत्येक पंक्ति को अल्पविराम के रूप में अल्पविराम के रूप में निकाला गया था ... कॉलमर स्थिति खोना। इसे हल करने के लिए मैंने PDFTextStripperByArea का उपयोग किया और निर्देशांक का उपयोग करके मैंने प्रत्येक पंक्ति के लिए कॉलम द्वारा डेटा कॉलम निकाला। यह प्रदान किया गया है कि आपके पास एक निश्चित प्रारूप पीडीएफ है।

 File file = new File("fileName.pdf"); 
     PDDocument document = PDDocument.load(file); 
     PDFTextStripperByArea stripper = new PDFTextStripperByArea(); 
     stripper.setSortByPosition(true); 
     Rectangle rect1 = new Rectangle(50, 140, 60, 20); 
     Rectangle rect2 = new Rectangle(110, 140, 20, 20); 
     stripper.addRegion("row1column1", rect1); 
     stripper.addRegion("row1column2", rect2); 
     List allPages = document.getDocumentCatalog().getAllPages(); 
     PDPage firstPage = (PDPage)allPages.get(2); 
     stripper.extractRegions(firstPage); 
     System.out.println(stripper.getTextForRegion("row1column1")); 
     System.out.println(stripper.getTextForRegion("row1column2")); 

फिर 2 पंक्ति और इतने पर ...

10

मैं कई उपकरण का इस्तेमाल किया था पीडीएफ फाइल से तालिका को निकालने के लिए, लेकिन यह मेरे लिए काम नहीं किया।

इसलिए मैंने पीडीएफ फाइलों में टैब्यूलर डेटा को पार्स करने के लिए अपना स्वयं का एल्गोरिदम लागू किया है (इसका नाम traprange है)।

  1. इनपुट फ़ाइल:: sample-1.pdf, परिणाम: sample-1.html
  2. इनपुट फ़ाइल: sample-4.pdf, परिणाम: sample-4.html

traprange पर अपने प्रोजेक्ट पृष्ठ पर जाएं

निम्नलिखित कुछ नमूना पीडीएफ फाइल और परिणाम हैं ।

3

PDFLayoutTextStripper है जो डेटा के प्रारूप को रखने के लिए डिज़ाइन किया गया था।

README से:

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 

import org.apache.pdfbox.pdfparser.PDFParser; 
import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.util.PDFTextStripper; 

public class Test { 

    public static void main(String[] args) { 
     String string = null; 
     try { 
      PDFParser pdfParser = new PDFParser(new FileInputStream("sample.pdf")); 
      pdfParser.parse(); 
      PDDocument pdDocument = new PDDocument(pdfParser.getDocument()); 
      PDFTextStripper pdfTextStripper = new PDFLayoutTextStripper(); 
      string = pdfTextStripper.getText(pdDocument); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     }; 
     System.out.println(string); 
    } 
} 
0

यह ठीक काम करता है अगर पीडीएफ फाइल "केवल आयताकार मेज" pdfbox 2.0.6 का उपयोग कर दिया है। किसी भी अन्य तालिका के साथ केवल आयताकार तालिका के साथ काम नहीं करेगा।

import java.io.File; 
import java.io.IOException; 
import java.util.ArrayList; 

import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.text.PDFTextStripper; 
import org.apache.pdfbox.text.PDFTextStripperByArea; 
public class PDFTableExtractor { 
    public static void main(String[] args) throws IOException { 
     ArrayList<String[]> objTableList = readParaFromPDF("C:\\sample1.pdf", 1,1,6); 
     //Enter Filepath, startPage, EndPage, Number of columns in Rectangular table 
    } 
    public static ArrayList<String[]> readParaFromPDF(String pdfPath, int pageNoStart, int pageNoEnd, int noOfColumnsInTable) { 
     ArrayList<String[]> objArrayList = new ArrayList<>(); 
     try { 
      PDDocument document = PDDocument.load(new File(pdfPath)); 
      document.getClass(); 
      if (!document.isEncrypted()) { 
       PDFTextStripperByArea stripper = new PDFTextStripperByArea(); 
       stripper.setSortByPosition(true); 
       PDFTextStripper tStripper = new PDFTextStripper(); 
       tStripper.setStartPage(pageNoStart); 
       tStripper.setEndPage(pageNoEnd); 
       String pdfFileInText = tStripper.getText(document); 
       // split by whitespace 
       String Documentlines[] = pdfFileInText.split("\\r?\\n"); 
       for (String line : Documentlines) { 
        String lineArr[] = line.split("\\s+"); 
        if (lineArr.length == noOfColumnsInTable) { 
         for (String linedata : lineArr) { 
          System.out.print(linedata + "    "); 
         } 
         System.out.println(""); 
         objArrayList.add(lineArr); 
        } 
       } 
      } 
     } catch (Exception e) { 
      System.out.println("Exception " +e); 
     } 
      return objArrayList; 
    } 
} 
0

आप किसी दस्तावेज़ के एक विशेष क्षेत्र से पाठ निकालने के लिए PDFBox के PDFTableStripperByArea वर्ग का उपयोग कर सकते हैं। आप तालिका के प्रत्येक कक्ष क्षेत्र को पहचानकर इस पर निर्माण कर सकते हैं। यह बॉक्स से बाहर प्रदान नहीं किया गया है, लेकिन उदाहरण DrawPrintTextLocations वर्ग दर्शाता है कि आप किसी दस्तावेज़ में अलग-अलग वर्णों के बाध्यकारी बक्से को कैसे पार्स कर सकते हैं (तारों या पैराग्राफ के बाध्यकारी बक्से को पार्स करना बहुत अच्छा होगा, लेकिन मैंने समर्थन नहीं देखा है इसके लिए पीडीएफबॉक्स में - यह question देखें)। आप तालिका के अलग-अलग कोशिकाओं की पहचान करने के लिए सभी स्पर्श करने वाले बाउंडिंग बॉक्स को समूहबद्ध करने के लिए इस दृष्टिकोण का उपयोग कर सकते हैं। ऐसा करने का एक तरीका Rectangle2D क्षेत्रों के सेट boxes को बनाए रखना है और फिर प्रत्येक पार्स किए गए चरित्र के लिए चरित्र के बाध्यकारी बॉक्स को DrawPrintTextLocations.writeString(String string, List<TextPosition> textPositions) में ढूंढें और मौजूदा सामग्री के साथ विलय करें।

Rectangle2D bounds = s.getBounds2D(); 
// Pad sides to detect almost touching boxes 
Rectangle2D hitbox = bounds.getBounds2D(); 
final double dx = 1.0; // This value works for me, feel free to tweak (or add setter) 
final double dy = 0.000; // Rows of text tend to overlap, so no need to extend 
hitbox.add(bounds.getMinX() - dx , bounds.getMinY() - dy); 
hitbox.add(bounds.getMaxX() + dx , bounds.getMaxY() + dy); 

// Find all overlapping boxes 
List<Rectangle2D> intersectList = new ArrayList<Rectangle2D>(); 
for(Rectangle2D box: boxes) { 
    if(box.intersects(hitbox)) { 
     intersectList.add(box); 
    } 
} 

// Combine all touching boxes and update 
for(Rectangle2D box: intersectList) { 
    bounds.add(box); 
    boxes.remove(box); 
} 
boxes.add(bounds); 

आप इन क्षेत्रों को PDFTableStripperByArea पर भेज सकते हैं।

आप एक और आगे जा सकते हैं और इन क्षेत्रों के क्षैतिज और लंबवत घटकों को अलग कर सकते हैं, और फिर भी किसी भी सामग्री को पकड़ने के बावजूद, सभी तालिका की कोशिकाओं के निचले क्षेत्रों को अलग कर सकते हैं।

मेरे पास इन चरणों को करने का कारण है, और अंत में PDFBox का उपयोग करके अपना खुद का PDFTableStripper कक्षा लिखा। मैंने अपना कोड gist on GitHub के रूप में साझा किया है। main method कैसे वर्ग इस्तेमाल किया जा सकता का एक उदाहरण देता है:

try (PDDocument document = PDDocument.load(new File(args[0]))) 
{ 
    final double res = 72; // PDF units are at 72 DPI 
    PDFTableStripper stripper = new PDFTableStripper(); 
    stripper.setSortByPosition(true); 

    // Choose a region in which to extract a table (here a 6"wide, 9" high rectangle offset 1" from top left of page) 
    stripper.setRegion(new Rectangle(
     (int) Math.round(1.0*res), 
     (int) Math.round(1*res), 
     (int) Math.round(6*res), 
     (int) Math.round(9.0*res))); 

    // Repeat for each page of PDF 
    for (int page = 0; page < document.getNumberOfPages(); ++page) 
    { 
     System.out.println("Page " + page); 
     PDPage pdPage = document.getPage(page); 
     stripper.extractTable(pdPage); 
     for(int c=0; c<stripper.getColumns(); ++c) { 
      System.out.println("Column " + c); 
      for(int r=0; r<stripper.getRows(); ++r) { 
       System.out.println("Row " + r); 
       System.out.println(stripper.getText(r, c)); 
      } 
     } 
    } 
} 
संबंधित मुद्दे