使用PDFBox解析PDF文件(尤其是表格)


71

我需要解析一个包含表格数据的PDF文件。我正在使用PDFBox提取文件文本以稍后解析结果(字符串)。问题在于文本提取无法按我期望的方式处理表格数据。例如,我有一个文件,其中包含一个像这样的表(7列:前两列始终有数据,只有一个Complexity列有数据,只有一个Financing列有数据):

+----------------------------------------------------------------+
| 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:

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

最后两个数字之间没有空格,但这不是最大的问题。问题是我不知道最后两个数字的含义:中,高,不适用?MAC /其他,FAE?我没有数字和它们的列之间的关系。

对我来说,不需要使用PDFBox库,因此使用另一个库的解决方案就可以了。我想要的是能够解析文件并知道每个解析数字的含义。


10
祝您好运...我本人正处于PDF地狱之中,目前完全不满意该格式。
Fosco 2010年

24
PDF被设计为输出显示格式,而不是提取格式。责怪用户,而不是格式。
mark stephens 2010年

如果PDF具有固定的布局,则还有其他方法可以从列中提取数据。我刚刚编写了一种从表单上固定字段位置提取PDF文本的工具。看到Matheus所指的PDF文件将很有趣。
Andrew Cash

不幸的是我无法显示PDF文件。它包含项目的客户数据,因此无法透露。
Matheus Moreira 2010年

我在不同的库(pdfparser.org)中也遇到相同的问题。这似乎不是图书馆的问题。经过大量搜索之后,我得出的解决方案是将过程分为两部分:1)PDFtoHTML和2)HTMLtoTXT。
卡里姆2014年

Answers:


20

您将需要设计一种算法来提取可用格式的数据。无论使用哪种PDF库,都需要这样做。字符和图形是通过一系列有状态的绘制操作绘制的,即,移动到屏幕上的此位置并绘制字符'c'的字形。

我建议您扩展org.apache.pdfbox.pdfviewer.PDFPageDrawer并覆盖该strokePath方法。在这里,您可以截取水平和垂直线段的绘制操作,并使用该信息来确定表格的列和行位置。然后,只需设置文本区域并确定在哪个区域绘制哪些数字/字母/字符就可以了。由于您知道区域的布局,因此可以知道提取的文本属于哪一列。

同样,在视觉上分隔的文本之间可能没有空格的原因是,PDF通常不会绘制空格字符。取而代之的是更新文本矩阵,并发出“移动”的绘制命令以绘制下一个字符和与最后一个字符分开的“空格宽度”。

祝好运。


该工具似乎可以完成上述操作,并且有一些可用的源代码jpedal.org/support_egTZ.php
Matthew Lock

最近我做了类似的事情,除了我不得不处理多行文本。还要看一下ExtractText类集,以弄清楚一旦拥有列和行,如何提取实际文本。另一方面,我在使行正确设置方面遇到问题,但是当我返回列时可以通过假设新行来进行调整。
威慑2011年

@deterb如何处理多行文字?
Gourav Saklecha'4

@purecharger有什么方法可以识别桌子的位置?
Gourav Saklecha

@GouravSaklecha,您需要对任何写出PDF文档的格式进行逆向工程,以弄清其处理的确切方式-不同的PDF生成器对此进行不同的处理。通常,您可以通过查看绘制的文本的位置来辨别多行。
阻止

14

我曾经使用过许多工具来从pdf文件中提取表格,但对我来说却不起作用。

因此,我已经实现了自己的算法(其名称为traprange)来解析pdf文件中的表格数据。

以下是一些示例pdf文件和结果:

  1. 输入文件:sample-1.pdf,结果:sample-1.html
  2. 输入文件:sample-4.pdf,结果:sample-4.html

访问我的项目页面traprange


嗨,能否请你给lib依赖maven?
Vahe Harutyunyan

@VaheHarutyunyan请检查该文件中github.com/thoqbk/traprange/blob/master/pom.xml
芹苴

@ThomQ似乎我们在Maven Central中没有它?search.maven.org
Vahe Harutyunyan

@VaheHarutyunyan没有,我们没有
芹苴

13

您可以在PDFBox中按区域提取文本。如果使用的是Maven 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" );

问题是首先获取坐标。我已经成功扩展了normal TextStripper,覆盖processTextPosition(TextPosition text)和打印出每个字符的坐标并弄清楚它们在文档中的位置。

但是,有一种更简单的方法,至少在Mac上是这样。在“预览”中打开PDF,然后打开“ I”以显示检查器,选择“裁剪”选项卡并确保单位在“点”中,然后从“工具”菜单中选择“矩形选择”,然后选择感兴趣的区域。如果选择区域,检查器将向您显示坐标,您可以将其舍入并输入到Rectangle构造函数参数中。您只需要使用第一种方法来确认原点在哪里。


2
当PDF具有固定布局时,这是一种不错的简单解决方案!如果在macOS中使用Preview,将给另一个赞(如果可以的话)。使提取真正容易。
马赛厄斯

11

对于我的答案来说可能为时已晚,但是我认为这并不难。您可以扩展PDFTextStripper类,并重写writePage()和processTextPosition(...)方法。在您的情况下,我假定列标题始终相同。这意味着您知道每个列标题的x坐标,并且可以将数字的x坐标与列标题的x坐标进行比较。如果它们足够接近(必须测试以确定接近程度),则可以说该数字属于该列。

另一种方法是在写完每页之后截取“ 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
}

了解了列之后,您可以对x坐标进行比较,以确定每个数字所属的列。

数字之间没有空格的原因是必须设置单词分隔符字符串。

希望对您或其他尝试类似操作的人有用。


10

有一个PDFLayoutTextStripper旨在保留数据格式。

从自述文件:

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);
    }
}

1
在当前版本的pdfbox中,PDFParser实例创建需要更改为PDFParser pdfParser = new PDFParser( new RandomAccessBufferedFileInputStream( "sample.pdf"));
Sabir Khan

4

我已经成功解析了pdftotext实用程序生成的文本文件(sudo apt-get install poppler-utils)。

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
对于这些Windows用户,请从以下网站下载您的exe文件: foolabs.com/xpdf/download.html将变量proc指向pdftotext.exe文件。如果在主函数中执行,则删除该函数的返回类型和return关键字。
Dinesh Ravi

4

尝试使用TabulaPDF(https://github.com/tabulapdf/tabula)。这是一个非常好的库,可以从PDF文件中提取表格内容。非常符合预期。

祝好运。:)


3
提供一个有关在这种情况下如何使用库的示例,将大大提高该答案的质量以及该答案将被提高的机会。
chb

2

从PDF提取数据注定会有很多问题。文件是通过某种自动过程创建的吗?如果是这样,您可以考虑将PDF转换为未压缩的PostScript(尝试pdf2ps),然后查看PostScript是否包含某种可以利用的常规模式。


2

在读取数据为表格格式的pdf文件时,我遇到了同样的问题。使用PDFBox进行常规解析后,每行都以逗号作为分隔符进行提取...丢失了列的位置。为了解决这个问题,我使用了PDFTextStripperByArea,并使用坐标逐行提取了每一行的数据。前提是您具有固定格式的pdf。

        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行,依此类推...


2

您可以使用PDFBox的PDFTextStripperByArea类从文档的特定区域提取文本。您可以通过识别表的每个单元格的区域来建立此基础。这不是开箱即用的,但是示例DrawPrintTextLocations类演示了如何解析文档中单个字符的边界框(解析字符串或段落的边界框会很棒,但是我没有看到支持PDFBox为此-参见此问题)。您可以使用此方法将所有接触的边界框分组,以标识表的不同单元格。要做到这一点的方法之一是维护一组boxesRectangle2D地区,然后为每个解析字符找到字符的边框作为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);

然后,您可以将这些区域传递到PDFTextStripperByArea

您还可以再进一步,分离出这些区域的水平和垂直分量,从而推断所有表格单元格的区域,而不管是否随后保留任何内容。

我不得不执行这些步骤,并最终PDFTableStripper使用PDFBox编写了自己的类。我已经在GitHub上分享了我的代码要点。该main方法提供了有关如何使用该类的示例:

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));
            }
        }
    }
}

PDFTableStripperByArea不存在,表示PDFTextStripperByArea。
Walid Bousseta

0

如何打印到图像并在上面进行OCR?

听起来效果很差,但是实际上它是PDF的主要目的,它使文本不可访问,您必须执行自己的操作。


不要以为您可以阐述哪些OCR可以读取表?
markdigi

@markdigi:我对OCR软件的经验很少。我的HP打印机随附了一个非常笨拙的称为ReadIris的产品,以及一个叫aabby FineReader的功能强大但价格合理的产品(我认为)。如果我没记错的话,它们都可以读取带有MS Word格式的表格的文档,并且其中包括表格。请将此信息作为进一步探索的提示,而不是具体的建议。
卡尔·斯莫特里奇

1
OCRing毫无意义,因为您至少可以在任何PDF API中访问实际字符和X,Y位置
Matthew Lock

1
我使用您的方法来整理有序的,尽管很费力的方法,从PDF文档中的简单表格中提取内容,我使用PDF X-Change Viewer的OCR,然后使用其选择工具,然后剪切,最后粘贴到电子表格中。这是一个多步骤的过程。选择工具可以使用[alt]键来按列进行选择,尽管并不是完全可以预见的(列,行边界并不总是可以保持的)。这比抄写要好。但是,对于在带有标题的许多页面上拆分的长表,此方法很繁琐。我的天真的理解是PDF缺乏可利用的表形式主义。
subsci


0

如果使用pdfbox 2.0.6的PDF文件具有“仅矩形表”,则此方法效果很好。仅与矩形表不兼容。

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;
    }
}

1
如果单元格值包含空格,则此解决方案不起作用。
manikanta

0

对于想要做与OP相同的事情(就像我一样)的人,经过几天的研究,Amazon Textract是最好的选择(如果您的容量太低,免费套餐就足够了)。


0

对我来说,不需要使用PDFBox库,因此使用另一个库的解决方案就可以了

卡米洛特和神剑

您可能想尝试Python库Camelot,这是Python的开源库。如果您不愿意编写代码,则可以使用围绕Camelot创建的Web界面Excalibur。您将文档“上载”到localhost Web服务器,然后从该localhost服务器“下载”结果。

这是使用此python代码的示例:

import camelot
tables = camelot.read_pdf('foo.pdf', flavor="stream")
tables[0].to_csv('foo.csv')

输入是包含此表的pdf:

PDF-TREX样本

PDF-TREX集中的样本表

没有为camelot提供帮助,它通过查看文本相对对齐来独立工作。结果以csv文件的形式返回:

PDF表格从骆驼样品中提取

PDF表格从骆驼样品中提取

可以添加“规则”以帮助camelot识别复杂表中的鱼片位置:

规则已添加至Excalibur
在Excalibur中添加了规则。资源

的GitHub:

这两个项目处于活动状态。

是与其他软件(具有基于实际文档的测试),Tabulapdfplumberpdftablespdf-table-extract的比较


我想要的是能够解析文件并知道每个解析后的数字意味着什么

您无法自动执行此操作,因为pdf不是语义结构。

书本与文件

从语义的角度来看,Pdf“文档”是非结构化的(就像记事本文件一样),pdf文档给出了在何处打印文本片段的说明,该文本片段与同一节的其他片段无关,内容之间没有分隔(打印内容) ,以及这是标题,表格或脚注的片段还是视觉表示(字体,位置等)的片段。Pdf是PostScript的扩展,它描述了Hello World!这样的页面:

!PS
 /Courier             % font
 20 selectfont        % size
 72 500 moveto        % current location to print at
 (Hello world!) show  % add text fragment
 showpage             % print all on the page

(维基百科)。
可以想象,使用相同的指令,表格是什么样的。

我们可以说html不太清晰,但是有很大的不同:HTML以语义方式描述内容(标题,段落,列表,表头,表单元格,...),并将CSS关联为可视形式,因此内容为完全可访问。从这个意义上讲,html是sgml的简化后代,它放置了约束以允许进行数据处理:

标记应该描述文档的结构和其他属性,而不是指定需要执行的处理,因为它不太可能与将来的开发冲突。

与PostScript / Pdf相反。SGML用于发布中。Pdf不嵌入这种语义结构,它仅包含与纯字符串相关联的css等效项,这些字符串可能不是完整的单词或句子。Pdf用于封闭的文档,现在用于所谓的工作流管理

在尝试了不确定性和尝试从pdf提取数据的困难之后,很明显pdf根本不是将来保存文档内容的解决方案(尽管Adobe已从他们的对中获得了pdf标准)。

实际上保存得很好的是印刷形式,因为pdf在创建时就完全致力于此方面。Pdf几乎和印刷书籍一样死了。

当重复使用内容时,必须再次依靠手动重新输入数据,例如从印刷书籍中重新输入(可能尝试对它进行一些OCR)。这一点越来越正确,因为许多pdf甚至阻止了复制粘贴的使用,在单词之间引入多个空格,或者在对Web进行一些“优化”时产生乱码。

当文档的内容(而不是其印刷表示形式)有价值时,则pdf不是正确的格式。甚至Adobe也无法通过pdf渲染完美地重新创建文档的来源。

因此,打开的数据永远都不能以pdf格式发布,这限制了它们只能用于读取和打印(如果允许),并且使重用变得更加困难或不可能。


0
ObjectExtractor oe = new ObjectExtractor(document);

SpreadsheetExtractionAlgorithm sea = new SpreadsheetExtractionAlgorithm(); // Tabula algo.

Page page = oe.extract(1); // extract only the first page

for (int y = 0; y < sea.extract(page).size(); y++) {
  System.out.println("table: " + y);
  Table table = sea.extract(page).get(y);

  for (int i = 0; i < table.getColCount(); i++) {
    for (int x = 0; x < table.getRowCount(); x++) {
      System.out.println("col:" + i + "/lin:x" + x + " >>" + table.getCell(x, i).getText());
    }
  }
}

2
您应该提及您使用的库。您的代码包含许多非PDFBox或Java基本类的类……
mkl


-1

我对PDFBox不熟悉,但是您可以尝试查看itext。即使主页上显示了PDF生成,您也可以进行PDF操作和提取。看一下它是否适合您的用例。


1
您是否有使用itext提取文件内容的示例?
Matheus Moreira

我找到了一种使用iText读取内容的简单方法,但并没有帮助我。使用PdfTextExtractor可以获得与使用PDFBox类似的结果。:-(
Matheus Moreira

已经有一段时间了,但是不是PdfReader然后是.getContent()吗?
保罗·桑瓦尔德

-1

为了从pdf文件中读取表格的内容,您只需要通过使用任何API将pdf文件转换为文本文件(我使用iText的PdfTextExtracter.getTextFromPage()),然后通过Java程序读取该txt文件..现在阅读完后,主要任务已完成..您必须过滤所需的数据。您可以通过连续使用String类的split方法来执行此操作,直到找到您感兴趣的记录为止。.这是我的代码,通过该代码我可以提取一部分PDF文件的记录并将其写入.CSV文件。文件是.. 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();
        }

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.