dimas
dimas

Reputation: 2597

How to read certain portion of the text file in java

I wanted to read certain portions in a text file and add each of those portion into a their corresponding ArrayList. This is a sample text file:

format: pair_diploid
option: -b 50
option: -pp +
option: -mr masked
option: -n C:\Users\Fertilak\gimp\gimp
preprocess_script: cpp
source_files {
1   types.h 1
2   actions.c   2316
3   actions.h   1
4   editor-actions.c    91
5   editor-actions.h    1
287 test-clipboard.c    1247
}
source_file_remarks {
42
:   masked
152
:   masked
170
:   masked
}
clone_pairs {
5545    56.0-180    148.0-180
3083    62.1959-2107    62.2107-2255
3083    62.2107-2255    62.1959-2107
89  82.0-520    82.620-1140
89  82.620-1140 82.0-520
5545    148.0-180   56.0-180
12084   2865.633-694    2868.2877-2938
12084   2868.2877-2938  2865.633-694
}
clone_set_remarks {
}

The portions that I wanted to be added on my 2 ArrayList are enclosed by brackets "{}" in source_files and clone_pairs. So for example I want to add in arraylist sourcefiles all of the data such as

    1   types.h 1
    2   actions.c   2316
...etc

which are enclosed in source_files brackets. Also the same thing for clone_pairs I will add all of the data enclosed in the brackets to arrayList clonePairs.

This is what I have done so far... but its not working.

    public void readFile(String file){
List<String> sourceFiles = new ArrayList<String>();
List<String> clonePairs = new ArrayList<String>();

            try{
                BufferedReader buff = new BufferedReader(new FileReader(file));
                
                try{
                    
                    String readBuff = buff.readLine();
                    while (readBuff != null){
                        if (readBuff.equals("source_files {") && !readBuff.equals("}")){
                            sourceFiles.add(readBuff);
                               }

                    else if (readBuff.equals("clone_pairs {") && !readBuff.equals("}")){
                            clonePairs.add(readBuff);
                               }

                        readBuff = buff.readLine();
                    }
                }
                finally{
                    buff.close();
                    }
            }
            
            catch(FileNotFoundException e){
                System.out.println("File not found");
            }
            catch(IOException e){
                System.out.println(e);
            }
            
        }

Almost everything is working in this piece of code except for the if-else conditions. Any suggestions on how to do this?

EDIT

I have edited content and replaced it with readBuff string. Sorry

EDIT 2

For the benefit of everyone this is the right code as proposed by Andrew Solution Code:

public void readFile(String file){
        try{
            BufferedReader buff = new BufferedReader(new FileReader(file));
            
            try{
                
                String readBuff = buff.readLine();
                String section = "";
                while (readBuff != null){
                    if (section.equals("source_files {") && !readBuff.equals("}")){
                        sourceFiles.add(readBuff);
                    } else if (section.equals("clone_pairs {") && !readBuff.equals("}")){
                        clonePairs.add(readBuff);
                    } else if (readBuff.equals("source_files {") || readBuff.equals("clone_pairs {")) {
                        section = readBuff;
                    } else if (readBuff.equals("}")) {
                        section = "";
                    }

                    readBuff = buff.readLine();
                }

            }
            finally{
                buff.close();
                }
        }
        
        catch(FileNotFoundException e){
            System.out.println("File not found");
        }
        catch(IOException e){
            System.out.println("exceptional case");
        }
    }

Upvotes: 1

Views: 6146

Answers (3)

mithra
mithra

Reputation: 1141

I tried this

public static void readFile(String file){
   List<String> sourceFiles = new ArrayList<String>();
   List<String> clonePairs = new ArrayList<String>();
   file = "test.txt";
   try{
       BufferedReader buff = Files.newBufferedReader(Paths.get(file));
       
       try{
           
           String readBuff = buff.readLine();
           boolean sourceStart = false;
           boolean cloneStart = false;
           boolean sourceEnd = false;
           while (readBuff != null){
               if(readBuff.equals("}")){
                   sourceEnd = true;
                   sourceStart=false;
                   cloneStart=false;
               }else {
                   sourceEnd = false;
               }
               if (sourceStart && !sourceEnd){
                   sourceFiles.add(readBuff);
               }
               else if (cloneStart && !sourceEnd){
                   clonePairs.add(readBuff);
                }
               
               if (readBuff.equals("source_files {")){
                   sourceStart=true;
               }
               
               if (readBuff.equals("clone_pairs {")){
                   cloneStart=true;
               }
               

               readBuff = buff.readLine();
           }
           
           sourceFiles.forEach(sf -> System.out.println(sf));
           System.out.println("---------------------");
           System.out.println("---------------------");
           
           clonePairs.forEach(cf -> System.out.println(cf));
       }
       finally{
           buff.close();
           }
   }
   catch(FileNotFoundException e){
       System.out.println("File not found exception");
   }
   catch(IOException e){
       System.out.println(e);
   }
   

}

Upvotes: 0

fonZ
fonZ

Reputation: 2479

I think that the approach with the if/else in the body of the while is just plain overhead. Because for every loop you are checking for: 1. The condition in the while loop 2. Every if else in the loop. Then when you encounter for example "source_files {" you are still checking every loop for all those conditions.

In any case you have to read every line of the file, and IF you know the order in which they are defined then this should be alot more efficient:

This method will get the BufferedReader to start with.

private BufferedReader getBufferedReader(File file) {
    try{
        return new BufferedReader(new FileReader(file));
    }
    catch(FileNotFoundException e){
        e.printStackTrace();
    }
}

This method will read every line of the buffer until it encounters the start string. Then it will add every next line to the list until it encounters the closing brackets. And will return your newly made list.

private List<String> readContent(BufferedReader buff, String start) {
    List<String> list = new ArrayList<String>();
    try {
        String readBuff;
        do {
            readBuff = buff.readLine();
        }
        while (readBuff != null && !readBuff.startsWith(start));

        do {
            readBuff = buff.readLine();
            list.add(readBuff);
        }
        while (readBuff != null && !readBuff.startsWith("}"));

    }
    catch(IOException e){
        e.printStackTrace();
    }
    return list;
}

And eventually your method looks like this.

    public void readLists(File file) {
        BufferedReader buff = getBufferedReader(file);
        List<String> sourceFiles = readContent(buff,"source_files {");
        List<String> clonePairs = readContent(buff,"clone_pairs {");
    }

This code basically reads every line of the file once with the conditions directly in the while loop so you dont need any if/else.

You only need the if/else if you dont know the order of the data in the file. So this code assumes that source_files comes first and clone_pairs next.

Also, i use startsWith because there might be a space after your bracket ie "source_files { " which would make the equals fail.

Upvotes: 1

Andrew
Andrew

Reputation: 4624

What you're building is called a state machine. You need something to keep track of where you are in the file - the state. I've called it section.

                String readBuff = buff.readLine();
                String section = "";
                while (readBuff != null){
                    if (section.equals("source_files {") && !readBuff.equals("}")){
                        sourceFiles.add(readBuff);
                    } else if (section.equals("clone_pairs {") && !readBuff.equals("}")){
                        clonePairs.add(readBuff);
                    } else if (readBuff.equals("source_files {") || readBuff.equals("clone_pairs {")) {
                        section = readBuff;
                    } else if (readBuff.equals("}")) {
                        section = "";
                    }

                    readBuff = buff.readLine();
                }

Upvotes: 3

Related Questions