简体   繁体   中英

Chunk data between two words from a text file in java

I have a .txt file where the data is in following format.

Start-enclosure
Standard
African Safari Enclosure
09am
05pm
Ram
Safari Enclosure for animals requiring large roaming area
30
Start-animl
Elephant
400

Giraffe
350

Lion
300
End-enclosure


Start-enclosure
Premium
Standard Australian Enclosure
09am
09pm
Shyam
Standard Enclosure for animals available in australia
30
5
Start-animl
Koala
8

Wormbat
25

Wallaby
20
End-enclosure

I want to store this data in a List<Enclosure> Like using switch case for the type (Standard, Premium) and storing data in this format

Enclosure Name
Opening Time
Closing Time
Enclosure Manager
Description
Entry Price

List<Animals> { animal name, animal weight }

How can I achieve it. I was hoping some way to chunk data between Start-enclosure and End-enclosure and looping from the data. But how do I achieve it I am trying it but I need a direction to go straight path.

I write below code for chunking a data based on start and end, and its working fine for me.

You can modified start and end with enclosure

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class ChunkTest{

    static List<String> sList = new ArrayList<>();

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        sList = new Tester().test();
        sList.forEach((d) -> System.out.println(d));

    }

    private List<String> test() throws IOException {

        String str = "", str2 = "";
        FileInputStream fileInputStream = new FileInputStream(new File("path/to/text/file"));
        BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream));
        while ((str = br.readLine()) != null) {
            if (!str.equals("start")) {
                str2 = str2 + "\n" + str;
            }
            if (str.equals("end")) {
                sList.add(str2.replace("end", ""));
                str2 = "";
            }

        }

        return sList;
    }

}

Tested with below data:

start
1
2
3
4
end

start
5
6
7
8
end

Your input file's second enclosure has two lines for price, namely 30 and 5 . Is that a typo? (because your proposed variable ' Entry Price ' is NOT a list)... And your algorithm will vary depending on the answer.

You can achieve the desired implementation with one loop. However, you have to stick to a few requirements about your input text file:

  • blank lines between enclosures can be ignored
  • blank lines inside animals section can be ignored
  • enclosure related fields appear before Start-animl section
  • enclosure & animal fields appear in a deterministic order

With the above requirements, you can achieve your goal, as shown in the code. As you can see, the implementation does require fair bit of bookkeeping. You should study the code and understand it. Also understand the implications of the above requirements within the code. For example, code won't work if the order of fields changes unless you make corresponding code changes.

public class FileParser {

    static class Animal {
        String name;
        String weight;

        @Override
        public String toString() {
            return "(" + name + "," + weight + ")";
        }
    }

    static class Enclosure {

        String EnclosureName;
        String EnclosureType;
        String OpeningTime;
        String ClosingTime;
        String EnclosureManager;
        String Description;
        String EntryPrice;
        String PriceModifier;
        List<Animal> Animals;

        @Override
        public String toString() {
            return
                    "\tEnclosureName [" + EnclosureName + "]\n" +
                    "\tOpeningTime [" + OpeningTime + "]\n" +
                    "\tClosingTime [" + ClosingTime + "]\n" +
                    "\tEnclosureManager [" + EnclosureManager + "]\n" +
                    "\tDescription [" + Description + "]\n" +
                    "\tEntryPrice [" + EntryPrice + "]\n" +
                    "\tPriceModifier [" + PriceModifier + "]\n" +
                    "\tAnimals " + Animals
                    ;
        }
    }

    private static Map<String,ArrayList<Enclosure>> parse(File inputFile)
            throws IOException {

        Map<String,ArrayList<Enclosure>> enclosureMap = new HashMap<>();
        final int SECTION_NOOP = 0, SECTION_ENCLOSURE = 1, SECTION_ANIMAL = 2;
        int sectionType = SECTION_NOOP;

        try ( BufferedReader br = new BufferedReader(new FileReader(inputFile)) ) {
            String line;
            int enclosureLineNumber = 0, animalLineNumber = 0;
            String encType = "";
            Enclosure enclosure = null;
            while ( (line = br.readLine()) != null ) {

                String text = line.trim();

                // ignore blank lines
                if ( text.length() == 0 && (sectionType == SECTION_NOOP || sectionType == SECTION_ANIMAL) ) {
                    continue;
                }

                switch (text) {
                    case "Start-enclosure":
                        sectionType = SECTION_ENCLOSURE;
                        enclosure = new Enclosure();
                        enclosure.Animals = new ArrayList<>();
                        enclosureLineNumber++;
                        break;
                    case "Start-animl":
                        sectionType = SECTION_ANIMAL;
                        animalLineNumber++;
                        break;
                    case "End-enclosure":
                        sectionType = SECTION_NOOP;
                        enclosureLineNumber = 0;
                        animalLineNumber = 0;
                        if ( enclosure != null ) {
                            enclosureMap.get(encType).add(enclosure);
                        }
                        enclosure = null;
                        break;
                    default:
                        if ( enclosure != null && sectionType == SECTION_ANIMAL ) {
                            // line is from inside the Animals section
                            Animal theAnimal;
                            switch ( animalLineNumber )  {
                                case 1:
                                    theAnimal = new Animal();
                                    theAnimal.name = text;
                                    enclosure.Animals.add(theAnimal);
                                    animalLineNumber = 2;
                                    break;
                                case 2:
                                    theAnimal = enclosure.Animals.get( enclosure.Animals.size() -1 );
                                    theAnimal.weight = text;
                                    animalLineNumber = 1;
                                    break;
                                default:
                                    break;
                            }
                        } else if ( enclosure != null && sectionType == SECTION_ENCLOSURE ) {
                            // line is from the Enclosure (before Animals)
                            switch (enclosureLineNumber) {
                                case 1:
                                    encType = text;
                                    enclosure.EnclosureType = text;
                                    if ( !enclosureMap.containsKey(encType) ) {
                                        enclosureMap.put( encType, new ArrayList<>() );
                                    }
                                    break;
                                case 2:
                                    enclosure.EnclosureName = text;
                                    break;
                                case 3:
                                    enclosure.OpeningTime = text;
                                    break;
                                case 4:
                                    enclosure.ClosingTime = text;
                                    break;
                                case 5:
                                    enclosure.EnclosureManager = text;
                                    break;
                                case 6:
                                    enclosure.Description = text;
                                    break;
                                case 7:
                                    enclosure.EntryPrice = text;
                                    break;
                                case 8:
                                    enclosure.PriceModifier = text;
                                    break;
                                default:
                                    break;
                            }
                            enclosureLineNumber++;
                        } else {
                            // ignore lines that are not part of Enclosure
                        }
                        break;
                }

            }
        }

        return enclosureMap;
    }

    public static void main(String[] args) throws IOException {
        if ( args.length != 1 ) {
            System.err.println("Missing filename argument");
            System.exit(1);
        }
        File inputFile = new File(args[0]);
        if ( !inputFile.canRead() ) {
            System.err.println(args[0] + ": does not exist or unreadable");
        }

        Map<String,ArrayList<Enclosure>> enclosureMap = parse(inputFile);

        enclosureMap.entrySet().forEach((entry) -> {
            System.out.println("Enclosures of Type = " + entry.getKey() + "\n");
            entry.getValue().forEach((enclosure) -> {
                System.out.println(enclosure + "\n");
            });
        });
    }

}

For your input file, the output produced by above code would be:

Enclosures of Type = Standard

    EnclosureName [African Safari Enclosure]
    OpeningTime [09am]
    ClosingTime [05pm]
    EnclosureManager [Ram]
    Description [Safari Enclosure for animals requiring large roaming area]
    EntryPrice [30]
    PriceModifier [null]
    Animals [(Elephant,400), (Giraffe,350), (Lion,300)]

Enclosures of Type = Premium

    EnclosureName [Standard Australian Enclosure]
    OpeningTime [09am]
    ClosingTime [09pm]
    EnclosureManager [Shyam]
    Description [Standard Enclosure for animals available in australia]
    EntryPrice [30]
    PriceModifier [5]
    Animals [(Koala,8), (Wormbat,25), (Wallaby,20)]

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