简体   繁体   中英

Java Buffered Reader Text File Parsing

I am really struggling with parsing a text file. I have a text file which is in the following format

ID
Float Float 
Float Float
....   // variable number of floats
END
ID
Float Float 
Float Float
....   
END

etc However the ID can represent one of two values, 0 which means it is a new field, or -1 which means it is related to the last new field. The number of times a related field can repeat it self is unlimited. Which is where the problem is occurring.

As I have a method in a library which takes an ArrayList of the new Floats, then an ArrayList of an ArrayList of the related floats.

When I try and code the logic for this I just keep getting deeper and deeper embedded while loops.

I would really appreciate any suggestions as to how I should go about this. Thanks in advance.

Here is the code I have so far.

BufferedReader br = new BufferedReader(new FileReader(buildingsFile));

        String[] line = br.readLine().trim().split("    ");
        boolean original = true;

        while(true)
        {
            if(line[0].equals("END"))
                break;

            startCoordinate = new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1]));

            while(true)
            {
                line = br.readLine().trim().split("    ");

                if(!line[0].equals("END") && original == true)
                    polypoints.add(new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1])));
                else if(!line[0].equals("END") && original == false)
                    cutout.add(new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1])));
                else if(line[0].equals("END") && original == false)
                {
                    cutouts.add(cutout);
                    cutout.clear();
                }
                else if(line[0].equals("-99999"))
                    original = false;
                else if(line[0].equals("0"))
                    break;
            }

            buildingDB.addBuilding(mapName, startCoord, polypoints, cutouts);
        }

New Code

        int i = 0;

        BufferedReader br = new BufferedReader(new FileReader(buildingsFile));

        String[] line;

        while(true)
        {
            line = br.readLine().trim().split("    ");

            if(line[0].equals("END"))
                break;

            polygons.add(new Polygon(line));

            while(true)
            {
                line = br.readLine().trim().split("    ");

                if(line[0].equals("END"))
                    break;
                polygons.get(i).addCoord(new Coordinate(Double.parseDouble(line[0]), Double.parseDouble(line[1])));
            }



            i++;
        }
        System.out.println(polygons.size());


        int j = 0;
        for(i = 0; i< polygons.size(); i++)
        {
            Building newBuilding = new Building();

            if(polygons.get(i).isNew == true)
            {
                newBuilding = new Building();
                newBuilding.startCoord = new Coordinate(polygons.get(i).x, polygons.get(i).y);
            }

            while(polygons.get(i).isNew == false)
                newBuilding.cutouts.add(polygons.get(i).coords);

            buildings.add(newBuilding);
        }

        for(i = 0; i<buildings.size(); i++)
        {
            System.out.println(i);
            buildingDB.addBuilding(mapName, buildings.get(i).startCoord, buildings.get(i).polypoint, buildings.get(i).cutouts);
        }

You can try using ANTLR here, The Grammar defines the format of the text you are expecting and then you can wrap the contents in a Java object. The * and + Wildcards will resolve the complexity of while and for. Its very simple and easy to use, you dont have to construct AST you can take the parsed content from java objects directly. But the only overhead is you have to add the ANTLR.jar to your path.

I assume that a "field" means an ID and a variable number of coordinates (pairs of floats), that, judging from your code, represents a polygon in fact.

I would first load all the polygons, each into a separate Polygon object:

class Polygon {
    boolean isNew;
    List<Coordinate> coordinates;
}

and store the polygons in another list. Then in a 2nd pass go through all the polygons to group them according to their IDs into something like

class Building {
    Polygon polygon;
    List<Polygon> cutouts;
}

I think this would be fairly simple to code.

OTOH if you have a huge amount of data in the file, and/or you prefer processing the read data little by little, you could simply read a polygon and all its associated cutouts, until you find the next polygon (ID of 0), at which point you could simply pass the stuff read so far to the building DB and start reading the next polygon.

Maybe you should use map for new floats and related floats..if got your question it should help..example:

HashMap hm = new HashMap();
hm.put("Rohit", new Double(3434.34));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM