Array

Hello, im trying to convert a .dat file (just ordinary text) to a 2d array. Ofcourse i can get codes from google for this, but id like to make it myself. Im quite far, it works if im not using any spaces in the map. But id like to have a map file so its easier to read for the mapmaker. It always returns array out of bounds. This is my map file:


   0,  10,  10,  30,   0,   0,   0,   0,
   0,  10,  20,  30,   0,   0,   0,   0,
   0,  10,  20,  21,  40,  40,  40,  40,
   0,  10,  20,  20,  20,  20,  20,  20,
   0,  80,  50,  50,  50,  50,  50,  50,
   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,

and my read map class:


import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;

public class MapToArray {
	public int height;
	public int length;
	String filename;
	int[][] numbers;
	LineNumberReader reader;
	String lineRead = "";
	public boolean error = false;

	MapToArray(String filename) {
		this.filename = filename;
		try{
			System.out.println("New map loaded!");
			reader =  new LineNumberReader(new FileReader(filename));
			reader.close();
		}catch (FileNotFoundException e){
			System.out.println("File not found");
			error = true;
		}catch (IOException e){
			System.out.println("Cant acces file!");
			error = true;
		}
	}

	public int[][] getArray() {
		process();
		return numbers;
	}

	public void getLength() {
		int countChar = 0;
		try {
			reader = new LineNumberReader(new FileReader(filename));
			lineRead = reader.readLine();
			while (countChar < lineRead.length()) {
				if (!(lineRead.charAt(countChar) == ','))
					length++;
				countChar++;
			}
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void getHeigth() {

		try {
			reader = new LineNumberReader(new FileReader(filename));
			while ((lineRead = reader.readLine()) != null) {
			}
			height = reader.getLineNumber();
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void process() {
		ArrayList<String> array = new ArrayList<String>();

		getLength();
		getHeigth();
		try {
			reader = new LineNumberReader(new FileReader(filename));
			for (int i = 0; i < height; i++) {
				array.add(reader.readLine());
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		if (array.size() == 0) {
			System.out.println("Empty map");
		}
		System.out.println("Length: " + length + " Heigth: " + height);
		numbers = new int[length][height];

		int r = 0;
		for (String s : array) {
			toArray(s, r);
			r++;
		}
	}

	private void toArray(String s, int row) {
		System.out.print("String: "+s+"Row: "+row);
		String match = ",";
		String[] veld = s.split(match);
		for (int i = 0; i < length; i++) {
			if(!veld[i].matches(" ")){
				try{
					numbers[i][row] = Integer.parseInt(veld[i]);
				}catch(NumberFormatException e){
					System.out.println("Not a valid map!");
				}
			}
		}
	}
}


Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8
	at MapToArray.toArray(MapToArray.java:97)
	at MapToArray.process(MapToArray.java:87)
	at MapToArray.getArray(MapToArray.java:32)
	at Board.<init>(Board.java:21)
	at Main.<init>(Main.java:10)
	at Main.main(Main.java:20)


Anybody sees my mistake here?

The code tag for bbcode is case-sensitive, so could you fix that, and perhaps paste the full exception traceback you get as well?

Fixed

Please don’t use “global” variables. Putting them in a class doesn’t help much^^.
“Static” methods are also quite bad.

why not something like this.

public class MapToArray {

    private final String filename;
    private int[][] mapdata;

    MapToArray(String filename) {
        this.filename = filename;
    }

    public void ini() throws IOException {
        List<int[]> rows = new ArrayList<> ();
        try (LineNumberReader reader = new LineNumberReader(new FileReader(filename))) {
 
            String lineRead;
            while((lineRead = reader.readLine()) != null){
                  String[] values = lineRead.split(",");
                  int[] row = new int[values.length];
                  for (int i = 0; i < row.length; i++) {
                      row[i] = Integer.parseInt(values[i]);
                   }
                   rows.add(row);
             }
        } catch (IOException e) {
            throw e;
        }
        
        mapdata = new int[rows.size()][];
        for (int i = 0; i < mapdata.length; i++) {
            mapdata[i] = rows.get(i);
        }
    }
    
    public boolean isInitialized()
    {
        return mapdata != null;
    }
    
    public int getWidth()
    {
        assert isInitialized();
        return mapdata.length;
    }
    
    public int getHeight()
    {
        assert isInitialized();
        return mapdata[0].length;
    }
    //you really shouldn't return an inner array
    public int[][] getMapData()
    {
        return mapdata;
    }
}

ps: code is untested and without error handling


      System.out.print("String: "+s+"Row: "+row);
      String match = ",";
      String[] veld = s.split(match);
      for (int i = 0; i < length; i++) {
         if(!veld[i].matches(" ")){

Since the offending index was 0, the problem would appear to be that there are no commas in s. Could be you have a blank line or something that you need to skip over? Since you print the string, you should be able to verify this for yourself. Also, you might be interested in java.util.Scanner just FYI

Thanks,

i didnt want it like that because i like to write my own code, i learn much more from it and its a lot of fun to do ::).

Also trying your code, it doesnt work.


List<int[]> rows = new ArrayList<> ();

That line is wrong, and i dont really know how to fix this, im not very used to arrayLists.
Also i dont see how this code is avoiding to read the spaces, doesnt that matter in this code?
And if your method is better, why?
Also, why shouldnt i return an inner array? How should i pass the information trough then?

Many questions, soz! But thanks for helping this far! :smiley:

You cannot use arrays as generic type parameters. If you need to nest a list in a list, just do so: List<List> = new ArrayList<ArrayList>()

offending index was 0, I dont really understand this part of your sentence. It does have commas, this is what it returns:


New map loaded!
Length: 32 Heigth: 8
String:    0,  10,  10,  30,   0,   0,   0,   0,Row: 0
Not a valid map!

This one goes too far for my basic understanding. I have no clue what is happening here whatshowever! :expressionless:
And simply copy paste this part doesnt work either, so i cant test it out.

Bad font – that 8 looked like a 0. You’re trying to access index 8, which is the ninth element, and you only have eight. Classic off-by-one error.

You can have an array of generics, but it doesn’t work very well, and you can’t have a generic taking an array parameter at all. In short, arrays and generics don’t mix well. Don’t worry about it, stick to your array code and get that working first.

sure u can

something liek this compiles just fine

public static void main(String[] args) {
List<int[]> a = new LinkedList<>();
a.add(new int[2]);
System.out.println(a.get(0)[1]);
}

@elamre I think it don’t compile for you because I used diamond cases which are only allowed in java7

use

     List<int[]> a = new LinkedList<int[]>();

instead of

     List<int[]> a = new LinkedList<>();

String[] veld = s.split(match);

Be very careful with String.split(…) as its implementation a full regex engine.

here I cleaned up your code a bit. And as a next step you can merge all these file reads in one read, why bother with opening the file like 4 times and you get something similar like I posted at the top

@riven yes I know was just a quick mock up

public class MapToArray {

    private final String filename;

    MapToArray(String filename) {
        this.filename = filename;
    }

    public int[][] getArray() throws IOException {
        ArrayList<String> array = new ArrayList<String>();

        int length = getLength();
        int height = getHeigth();
        
        LineNumberReader reader = new LineNumberReader(new FileReader(filename));
        for (int i = 0; i < height; i++) {
            array.add(reader.readLine());
        }

        if (array.size() == 0) {
            System.out.println("Empty map");
        }
        System.out.println("Length: " + length + " Heigth: " + height);
        int[][] numbers = new int[length][height];

        int r = 0;
        for (String s : array) {
            toArray(s, r, numbers);
            r++;
        }

        return numbers;
    }

    public int getLength() throws IOException {
        int countChar = 0;
        try {
            LineNumberReader reader = new LineNumberReader(new FileReader(filename));
            String lineRead = reader.readLine();
            int length = 0;
            while (countChar < lineRead.length()) {
                if (!(lineRead.charAt(countChar) == ',')) {
                    length++;
                }
                countChar++;
            }
            reader.close();
            return length;
        } catch (IOException e) {
            throw e;
        }
    }

    public int getHeigth() throws IOException {

        try {
            LineNumberReader reader = new LineNumberReader(new FileReader(filename));
            String lineRead;
            while ((lineRead = reader.readLine()) != null) {
            }
            int height = reader.getLineNumber();
            reader.close();
            return height;
        } catch (IOException e) {
            throw e;
        }
    }

    private void toArray(String s, int row, int[][] numbers) {
        System.out.print("String: " + s + "Row: " + row);
        String match = ",";
        String[] veld = s.split(match);
        for (int i = 0; i < numbers.length; i++) {
            if (!veld[i].matches(" ")) {
                try {
                    numbers[i][row] = Integer.parseInt(veld[i]);
                } catch (NumberFormatException e) {
                    System.out.println("Not a valid map!");
                }
            }
        }
    }

Yeah sorry, once again I got it completely reversed – it’s the array of generics that freaks out. Either way it’s not a good idea to mix them.

This code still has the same error as i have though. Looks much cleaner, i give you that.
Also i was openning it 4 times to check for the array length and such (on a rather primitive way).
And yes @spongy

I can see that, but i cannot seem to find why it is doing this. Well i guess it is because of the spaces. But i cant seem to get rid of that.

Also @Riven, how is that bad (not in an offending way, more in a question way)?

Thanks so much everybody!

Finally got it after a lot of debugging. My last for loop was incorrect, i had taken the wrong length. I took the one from the total sentence (thus including spaces and commas) whereas i shouldve picked the veld one (the amount of commas).

Thanks for all the help!

Here is the code (might someone ever need it):


import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;

public class MapToArray {

    private final String filename;
    MapToArray(String filename) {
        this.filename = filename;
    }

    public int[][] getArray() throws IOException {
        ArrayList<String> array = new ArrayList<String>();

        int length = getLength();
        int height = getHeigth();
        
        LineNumberReader reader = new LineNumberReader(new FileReader(filename));
        for (int i = 0; i < height; i++) {
            array.add(reader.readLine());
        }

        if (array.size() == 0) {
            System.out.println("Empty map");
        }
        System.out.println("Length: " + length + " Heigth: " + height);
        int[][] numbers = new int[length][height];

        int r = 0;
        for (String s : array) {
            toArray(s, r, numbers);
            r++;
        }

        return numbers;
    }

    public int getLength() throws IOException {
        int countChar = 0;
        try {
            LineNumberReader reader = new LineNumberReader(new FileReader(filename));
            String lineRead = reader.readLine();
            int length = 0;
            while (countChar < lineRead.length()) {
                if (!(lineRead.charAt(countChar) == ',')) {
                    length++;
                }
                countChar++;
            }
            reader.close();
            return length;
        } catch (IOException e) {
            throw e;
        }
    }

    public int getHeigth() throws IOException {

        try {
            LineNumberReader reader = new LineNumberReader(new FileReader(filename));
            String lineRead;
            while ((lineRead = reader.readLine()) != null) {
            }
            int height = reader.getLineNumber();
            reader.close();
            return height;
        } catch (IOException e) {
            throw e;
        }
    }

    private void toArray(String s, int row, int[][] numbers) {
        System.out.print("String: " + s + "Row: " + row + "\n");
        String match = ",";
        String[] veld = s.split(match);
        
        for(int i = 0; i<veld.length;i++)
        	veld[i] = veld[i].replaceAll(" ","");
        System.out.println(numbers.length);
        for (int i = 0; i < veld.length; i++) {
            System.out.println("in i:" + veld[i]);
            try {
            	System.out.println("i: "+i);
                numbers[i][row] = Integer.parseInt(veld[i]);
            } catch (NumberFormatException e) {
                System.out.println("Not a valid map!");
            }
        }
    }
}