Search code examples
javamultilinedata-extraction

How to read multi-line content between two words from a PDF file using java?


I have a requirement where I have to get data from a PDF file which is coming after word "IN:" and before word "OUT:" and there are many such occurrences across the file.

The problem statement is that it can be in multiple lines as well, and it's format is not defined.

I even tried it by putting some conditions like starting or ending with specific characters, but in that way I would have to write too many conditions and also such format does exist after the "OUT:" word which was getting fetched.

Kindly let me know how can I solve the problem.

Below is sample data formats:

Format 1:

IN: {
"abc": "valueabc",
"def": "valuedef",
"ghi":
[
{"jkl": valuejkl, "mno": valuemno, "pqr":
"valuepqr"},
{"jkl": valuejkl, "mno": valuemno, "stu": "valuestu", "pqr":
"valuepqr"},
{"jkl": valuejkl, "mno": valuemno, "stu": "valuestu", "pqr":
"valuepqr"}
],
"id": "1"
}
OUT: {"abc": "valueabc", "id": "1", "def": {}}

Format 2 :

IN: {"abc": "valueabc", "def": "valuedef", "id": "1"}
OUT: {"abc": "valueabc", "id": "1", "ghi": "valueghi"}

Format 3 :

IN: {"abc": "valueabc", "def": "valuedef", "jkl":
["valuejkl"], "id": "1"}
OUT: {"abc": "valueabc", "id": "1", "ghi": {}}

Below is the core logic of the solution code I have tried, in if statement there is separate data which needs to be fetched as well, afterwards it's the logic for fetching the data after "IN:" and before "OUT:"

for(String line:lines)
            {
                String pattern = "^[0-9]+[\\.][0-9]+[\\.][0-9]+[\\.].*";
                boolean matches = Pattern.matches(pattern, line);
                if(matches)
                {
                    String subString1 = line.split("\\.")[3].trim();
                    String subString2 = line.split("\\.")[4].trim();
                    String finalString = subString1+"."+subString2+",";
                    System.out.println();
                    System.out.print(finalString); 
                }
                else if(line.startsWith("IN:"))
                {
                    String finalString = line.substring(3).trim();
                    System.out.print(finalString);
                }
                else if(!(line.startsWith("IN:")||line.startsWith("OUT:"))&&((line.trim().length()>1)&&(line.endsWith("}"))))
                {
                    String finalString = line.trim();
                    System.out.print(finalString);
                }
                else if(!(line.startsWith("IN:")||line.startsWith("OUT:"))&&((line.trim().length()>1)&&(line.startsWith("\""))))
                {
                    String finalString = line.trim();
                    System.out.print(finalString);
                }
                else
                {
                    continue;
                }
            }

Solution

  • How about this? If you want a value between IN: and OUT:, Could you try this code?

    StringBuilder sb = new StringBuilder();
    boolean targetFound = false;
    for (String line : lines) {
        if (line.startsWith("IN:")) {
            line = line.replace("IN:", "");
            targetFound = false;
        } else if (line.startsWith("OUT:")) {
            targetFound = true;
        }
    
        if (targetFound && !line.equals("OUT:")) {
            // Print
            System.out.println(sb.toString());
            sb.setLength(0);
        } else {
            sb.append(line.trim());
        }
    }
    

    INPUT TEXT:

    IN: {
    "abc": "valueabc",
    "def": "valuedef",
    "ghi":
    [
    "valuepqr"},
    {"jkl": valuejkl, "mno": valuemno, "stu": "valuestu", "pqr":
    "valuepqr"}
    ],
    "id": "1"
    }
    OUT: {"abc": "valueabc", "~"}
    

    RESULT:

    {"abc": "valueabc","def": "valuedef","ghi":["valuepqr"},{"jkl": valuejkl, "mno": valuemno, "stu": "valuestu", "pqr":"valuepqr"}],"id": "1"}