Iterate Through TXT File Into An Array

Discussion in 'Plugin Development' started by Sayshal, May 13, 2013.

Thread Status:
Not open for further replies.
  1. Offline


    So I have a text file, because I am in control of it's contents I can guarantee it'll always have the same structure, etc. I need to sort each line into a 2D array.

    How would I go about creating a for loop to store all this data into an array/list etc?
    TXT File:
    P.S: Yes I know it's Steam ID's, I'm using them as a way to auto-whitelist people.

    Any help would be great, as my other thread got 0 replies.
  2. You can read every line with an BufferedReader and the getLine() Method. (If you don't know what a BufferedReader is use Google)
    Then you get a String which can be splitteted with split(",").
    Than you can cast all parts with Boolean.getValue(line.splite[4]), etc.

    This is just a quick answer, but it should help you finding the right way

  3. For my plugin, I've stored data in CSV files (being what you've created). I've created a couple of generic, abstract classes for interpreting them. I'm going to split them off into a separate library at some point in the future, but you can use this for now (as long as you leave the author field as is): (see attached file)

    If you create an instance of FileHandler, the methods you're prompted to implement allow you to fill in the logic behind your file format. If you create an instance of CSVFileHandler, the methods you're prompted to implement allow you to pass in the fields you want to be in the table in the file. For instance:

    static CSVFileHandler File = new CSVFileHandler(new File(SM.getPlugin().getDataFolder(), "ManaStores.csv"), SM.getPlugin().getLogger(), "Mana stores file corrupted; loaded all uncorrupt records.")
            protected void onNoFileToInterpret()
            { SM.Print("No saved mana stores found. Start from scratch."); }
            protected List<String> getColumnNames()
                List<String> ColumnNames = new ArrayList<String>();
                return ColumnNames;
            protected List<Pair<String, Boolean>> getRow(int RowNumber)
                if(RowNumber >= Contents.size())
                    return null;
                    List<Pair<String, Boolean>> Fields = new ArrayList<Pair<String, Boolean>>();
                    Pair<CoOrdinate, Integer> current = Contents.get(RowNumber);
                    Fields.add(new Pair(current.Get1().WorldName, true));
                    Fields.add(new Pair(String.valueOf(current.Get1().X), false));
                    Fields.add(new Pair(String.valueOf(current.Get1().Y), false));
                    Fields.add(new Pair(String.valueOf(current.Get1().Z), false));
                    Fields.add(new Pair(String.valueOf(current.Get2()), false));
                    return Fields;
            protected void PreInterpretation()
            { Contents = new ArrayList<Pair<CoOrdinate, Integer>>(); }
            protected boolean InterpretRow(List<String> Row)
                boolean LineIsCorrupt = false;
                if(Row.size() != 5)
                    LineIsCorrupt = true;
                else if(SM.getServer().getWorld(Row.get(0)) == null || !SM.isInteger(Row.get(1)) || !SM.isInteger(Row.get(2)) || !SM.isInteger(Row.get(3)) || !SM.isInteger(Row.get(4)))
                    LineIsCorrupt = true;
                else if(Integer.parseInt(Row.get(4)) < 1)
                    LineIsCorrupt = true;
                    CoOrdinate LineCoOrd = new CoOrdinate(Row.get(0), Integer.parseInt(Row.get(1)), Integer.parseInt(Row.get(2)), Integer.parseInt(Row.get(3)));
                    Contents.add(new Pair(LineCoOrd, Integer.parseInt(Row.get(4))));
                return !LineIsCorrupt;
            protected void PostInterpretation()
            { Contents = Sorter.QuickSort(Contents); }
    This is all ripped straight from what I'm doing at the moment. The SplitCSVLine method isn't complete, but it works. I've just not gotten round to filling out support for escape characters and such, but there's a todo list in the sourcecode for the method.

    You should have a look through to sourcecode so you can do this independent of my classes ^_^
  4. Sayshal
    I suggest removing first and last char and then use string.split("\",\""); instead, that way players having commas in their name won't affect your split and you won't need extra trimming on each value.

    Or if you want extra security you could use regex.
  5. Offline


    No playername will have commas, so that seems unecessary. Now that I've split it up using String.split(","), how can I nicely put that in some sort of array or something that'll allow me to then use each value as component for a GUI that I'll be creating later. Example GUI:

    | Name | Blah | Blah | Blah | Blah |
    | [0][0] | [0][1] | [0][2] | [0][3] | [0][4]|
    | [1][0] | [1][1] | [1][2] | [1][3] | [1][4]|
    | [2][0] | [2][1] | [2][2] | [2][3] | [2][4]|
    etc etc.
  6. The InterpretRow method in the abstract class I uploaded has a list of all the strings in the CSV row currently being parsed passed in as an argument when it's called, and the method's called once for each line (excluding the title line). From there, it's just a case of writing the logic for what you want to do with each string as each row is loaded.

    After I checked for corruption in my example, I did:
    CoOrdinate LineCoOrd = new CoOrdinate(Row.get(0), Integer.parseInt(Row.get(1)), Integer.parseInt(Row.get(2)), Integer.parseInt(Row.get(3)));
    Contents.add(new Pair(LineCoOrd, Integer.parseInt(Row.get(4))));
    Where the first element contains a string with the world name, the next three contain the X, Y, and Z coördinates, and the final one being the amount of levels stored in a specific block. Contents is just my store for that data.
  7. .split(",") is returning an 1D String Array ( String[] ).
    If You can cast it with Boolean/Integer.valueOf(StringArray[x]);

    If you want to remove "" and STEAM_0:
    You can create a Method for that
    public String[] removeCrap(String[] strings)
    String[] newStrings = new String[string.lenght];
    for(int i = 0; i < strings.lenght; i++)
    newStrings[i] = strings[i].replace(""", "")
    //It would be better if you remove the "" from the file
    newStrings[1] = newStrings[1].replace("STEAM_0:", "");
    return newStrings;
  8. But it can be iterated over each line in the file. Place each array into returned into a List<String[]> and you practically have a 2 dimensional array.
  9. Offline


    That sounds extremely confident. My original plan was to simply pass every command separated value into one 2D array using something like (pseudocode)

    String[][] sortedAdminArray = new sortedAdminArray[ROW][COL] //static hardcoded variable since I have control over size of array at all times

    sortedAdminArray[0][index] = //Not sure how to pass first "<string>" in the first line.

    I know what I want to do, I just have never done much with Arrays so I don't know how to parse the data into [0][index], until you hit a "\n" char, then 0 becomes 1, etc.

    I might just try this, but if anyone has a simpler way I'd really love to learn the right way of doing this, as my next project is a full plugin.
  10. Unless you know before you load the file how long it's going to be, it's better to use a list than an array. Although I'd recommend using the classes I uploaded in my first post the way I've shown you, and then look through the source-code to get your head around what they do.

    The classes themselves handle all the logic needed for saving and loading to and from CSV files and have you implement a few simple abstract methods to specify what you're loading into and saving from. It's covered in the javadoc.
Thread Status:
Not open for further replies.

Share This Page