I need to read a text file into a 2D array, I can read files into the program perfectly fine (see my code below) however I cannot get my head around how to read them into a 2D array. The array the function is reading into is a global array hence why it's not in the function.
Also I won't know the amount of rows the array has at first (currently set at 300 as it won't be over this) and I know this could cause a problem, I've seen some people suggest using ArrayLists however I have to have a 2D array so I was also wondering if there was a way to change an ArrayList to a 2D array and if this would be more effective?
public static String readMaze(String fileName) {
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
for (int i = 0; i < mazeNew.length; i++) {
for (int j = 0; j < mazeNew[i].length; j++) {
// mazeNew[i][j] = ; - this is where I think something needs to be added
}
}
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return fileName;
}
example text file:
11 4
5 6
4 6
0 5
3 5
8 7
1 4
There's a few options here, but generally you'll want to use the Java Scanner class as it's designed for exactly this kind of thing. Alternatively, use an existing structured data format (like JSON or XML) and an existing parser to go with it - the advantage being you can make use of a vast amount of tools and libraries which deal with those formats and don't have to re-invent anything.
However, following through with the scanner approach, it would be like so:
public static ArrayList<int[]> readMaze(String fileName) {
// Number of ints per line:
int width=2;
// This will be the output - a list of rows, each with 'width' entries:
ArrayList<int[]> results=new ArrayList<int[]>();
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner mazeRunner = new Scanner(bufferedReader);
// While we've got another line..
while (mazeRunner.hasNextLine()) {
// Setup current row:
int[] row = new int[width];
// For each number..
for (int i = 0; i < width; i++) {
// Read the number and add it to the current row:
row[i] = mazeRunner.nextInt();
}
// Add the row to the results:
results.add(row);
// Go to the next line (optional, but helps deal with erroneous input files):
if ( mazeRunner.hasNextLine() ) {
// Go to the next line:
mazeRunner.nextLine();
}
}
mazeRunner.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return results;
}
If you have fixed no. of columns you can use this, but make sure input file must follow the same no of coulmns.
FileReader fileReader = new FileReader(fileName);
Scanner sc = new Scanner(fileReader);
int row=0, col=0;
while ((sc.hasNext()) != null) {
if(col < colSize){ //colSize is size of column
mazeNew[row][col]= sc.nextInt();
}
else{
col=0;
row++;
}
}
Below is the core logic, you would probably also like to to handle some errors, such as how many elements is a line split into, are there empty lines, etc.
List<String[]> list = new ArrayList<>();
Pattern pattern = Pattern.compile("\\s+");
while ((line = bufferedReader.readLine()) != null) {
list.add(pattern.split(line, -1));
}
String[][] mazeNew = list.toArray(new String[0][0]);
Something like this would work
it wont only read 2d text files .. it should work fine with any dimensions
public class Utile{
public static ArrayList<int[]> readMaze(String path){
ArrayList<int[]> result = new ArrayList<>();
try{
Scanner sc = new Scanner(new File(path));
String[] temp;
String line;
while(sc.hasNextLine()){
line = sc.nextLine();
if (line.length() != 0){ //if the line is empty it will cause NumberFormatException
temp = line.split(" ");
int[] val = new int[temp.length];
for(int i = 0;i < temp.length;i++){
val[i] = Integer.pareseInt(temp[i]);
}
result.add(val);
}
}
sc.close();
}catch(Exception e){
e.printStackTrace(); //just log it for now
}
return result;
}
}
I am not a java expert, but in PHP I would do it with explode(). But I found an example how to do the same in java using string.split(). The result is the same ... an 2D Array of the content. If possible you should try to add an delimiter to the rows inside that text document. But you could split the rows on the space character either.
Example:
String foo = "This,that,other";
String[] split = foo.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
sb.append(split[i]);
if (i != split.length - 1) {
sb.append(" ");
}
}
String joined = sb.toString();
Related
I'm trying to read a text file and put each comma separated value in an array and put all of them inside a 2d array.But the code I have right now puts the whole line in the array
Scanner sc = new Scanner(new BufferedReader(new FileReader(path)));
int rows = 3;
int columns = 1;
String[][] myArray = new String[rows][columns];
while (sc.hasNextLine()) {
for (int i = 0; i < myArray.length; i++) {
String[] line = sc.nextLine().trim().split(" " + ",");
for (int j = 0; j < line.length; j++) {
myArray[i][j] = line[j];
}
}
}
System.out.println(Arrays.deepToString(myArray));
This is the text file:
A6,A7
F2,F3
F6,G6
Output
[[A6,A7], [F2,F3], [F6,G6]]
Expected Output
[[A6],[A7],[F2],[F3],[F6],[G6]]
The problem is that you are assigning the entire 2D array instead of just each item.
Here are several alternatives.
Use Files.lines to stream the file.
splitting on a comma creates the 1D array of two elements for each line
flatMap that to stream each item.
that map that to an array of one item.
then just store them in a 2D array.
String[][] array = null;
try {
array = Files.lines(Path.of("f:/MyInfo.txt"))
.flatMap(line->Arrays.stream(line.split(","))
.map(item->new String[]{item}))
.toArray(String[][]::new);
} catch (IOException ioe) {
ioe.printStackTrace();
}
if (array != null) {
System.out.println(Arrays.deepToString(array));
}
prints
[[A6], [A7], [F2], [F3], [F6], [G6]]
Here is an approach similar to yours.
List<String[]> list = new ArrayList<>();
try {
Scanner scanner = new Scanner(new File("f:/MyInfo.txt"));
while (scanner.hasNextLine()) {
String[] arr = scanner.nextLine().split(",");
for (String item : arr) {
list.add(new String[]{item});
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
There is no deepToString for Lists so you either iterate it or convert to a 2D array.
String[][] ar = list.toArray(String[][]::new);
System.out.println(Arrays.deepToString(ar));
prints
[[A6], [A7], [F2], [F3], [F6], [G6]]
i think you have to double the rows size and for each line just put one element and increment the i++
The declaration of the result array is not correct.
Since you want the end result should look like this, [[A6],[A7],[F2],[F3],[F6],[G6]], it is a 2-dimensional array with one row and six columns.
Considering it, I have changed and simplified your code.
int rows = 3;
String[][] r = new String[1][rows * 2];
FileInputStream fstream = new FileInputStream("/path/to/the/file")
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
while((line = br.readLine()) != null) {
String[] current = line.split(",");
r[0][i++] = current[0];
r[0][i++] = current[1];
}
I have the following file
3
2,3,4,5
6,7,8
9,10
and I am trying to convert it to pass it as jagged array of double. By that I mean, I am trying to store this as
double[][] myArray = {{2,3,4},{6,7},{9}}
double[] secondArray = {5,8,10}
I have been able to get the values read from the file but I am stuck on 2 things.
How can I convert the values into double array?
How can I store the last elements into a new array?
I am facing the error because my array contains comma separated values but how can I get the individual values to convert to double? I am still new to Java so I am not aware of all the inbuilt methods.
here is what I have so far
public double[] fileParser(String filename) {
File textFile = new File(filename);
String firstLine = null;
String secondLine = null;
String[] secondLineTokens = null;
FileInputStream fstream = null;
try {
fstream = new FileInputStream(filename);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
try {
firstLine = br.readLine(); // reads the first line
List<String> myList = new ArrayList<String>();
while((secondLine = br.readLine()) != null){
myList.add(secondLine);
//secondLineTokens = secondLine.split(",");
}
String[] linesArray = myList.toArray(new String[myList.size()]);
for(int i = 0; i<linesArray.length; i++){
System.out.println("tokens are: " + linesArray[i]);
}
double[] arrDouble = new double[linesArray.length];
for(int i=0; i<linesArray.length; i++)
{
arrDouble[i] = Double.parseDouble(linesArray[i]); #error here
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
It looks like the first line gives you the number of lines in the rest of the file. You can leverage it to make the arrays upfront, like this:
int n = Integer.parseInt(br.readLine());
double a[][] = new double[n][];
double b[] = new double[n];
for (int i = 0 ; i != n ; i++) {
String[] tok = br.readLine().split(",");
a[i] = new double[tok.length-1];
for (int j = 0 ; j != a[i].length ; j++) {
a[i][j] = Double.parseDouble(tok[j]);
}
b[i] = Double.parseDouble(tok[tok.length-1]);
}
Similarly, you can use String.split method to find out how many entries is to be added to the jagged array. This way the code becomes much shorter, because you can pre-allocate all your arrays.
Demo.
I have a Justice_League.csv file that has four lines with commas between them. I want to count the number of characters there are in each line and convert that number to hex.
Below is the contents of Justice_League.csv:
Bruce Wayne,Batman,None,Gotham City,Robin,The Joker 43 2B
Oliver Queen,Green Arrow,None,Star City,Speedy,Deathstroke 50 32
Clark Kent,Superman,Flight,Metropolis,None,Lex Luthor 46 2E
Bart Allen,The Flash,Speed,Central City,Kid Flash,Professor Zoom 52 34
As you can see I have handcounted the characters and wrote the HEX value next to it. Now I need this done in Java. This is what I have so far. Can anybody help me out?
public String convertCSVToFlat (Exchange exchange) throws Exception {
String csv="Justice_League.csv";
BufferedReader bReader = new BufferedReader(new FileReader(csv));
String line = "";
int count = 0;
String str[] = new String[200];
int[] a = new int[24];
String[] hexNumber = new String[4];
try {
bReader.readLine();
int characterSum = 0;
int i = 0;
while((line = bReader.readLine()) != null) {
String[] f=line.split(",");
a[count]=Integer.parseInt(f[2]);
str[count]=f[1];
count++;
characterSum += line.length();
hexNumber[i] = Integer.toHexString(characterSum);
i++;
}
} catch (IOException e) {
e.printStackTrace();
}
bReader.close();
return hexNumber.toString();
I suggest you to read the javadoc of String.split. I think that you misunderstood the concept when you did this:
String[] f=line.split(",");
a[count]=Integer.parseInt(f[2]); //--> java.lang.NumberFormatException here!
Avoid using 'magic' numbers in your code like int[] a = new int[24];. Why 24?
Well, here comes a version that do what you want to do. Maybe it isn't the best way to do this but it works.
public void convertCSVToFlat () throws Exception {
String csv="Justice_League.csv";
BufferedReader bReader = new BufferedReader(new FileReader(csv));
//We're storing the values at this 3 arraylists,
//but a better approach is using an object to hold'em
ArrayList<String> lines = new ArrayList<String>();
ArrayList<Integer> chars = new ArrayList<Integer>();
ArrayList<String> hex = new ArrayList<String>();
String line = "";
try {
while((line = bReader.readLine()) != null) {
lines.add(line);
//I'm assuming that you don't want to count the commas and spaces.
//If you want to, comment the next line
line = line.replaceAll(",", "").replaceAll(" ", "");
int c = line.length(); //count remaining chars...
chars.add(c);
hex.add(Integer.toHexString(c));
}
} catch (IOException e) {
e.printStackTrace();
}
bReader.close();
//Just to show the results
for (int i = 0; i < lines.size(); i++) {
System.out.print(lines.get(i));
System.out.print("\t" + chars.get(i));
System.out.println("\t" + hex.get(i));
}
}
Like I said previously, this is a way to solve this. You should try another options to solve this in order to improve your knowledge...
I have loaded from text files many times before without thi issue, I have read and re-read my code and I (personally) cant see why I would get this issue, I am completely lost.
static public ArrayList<Media> importMedia(String fileName) throws IOException
{
try {
ArrayList<Media> mList = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line = reader.readLine();
int numberOfItems = Integer.valueOf(line);
while((line = reader.readLine()) != null)
{
String[] split = line.split(",");
if(split[0].contains("mp3"))
{
Mp3 mp3 = new Mp3(split[1]/*title*/,split[0]/*filename*/,Integer.parseInt(split[4])/*releaseyear*/,split[2]/*artist*/,split[3]/*album*/,split[5]/*label*/,Double.parseDouble(split[6])/*runtime*/);
mList.add(mp3);
}else if (split[0].contains("gif"))
{
Gif gif = new Gif(split[1]/*title*/,split[0]/*filename*/,Integer.parseInt(split[6])/*releaseyear*/,Double.parseDouble(split[2])/*width*/,Double.parseDouble(split[3])/*height*/,split[4]/*equipName*/,split[5]/*equipModel*/);
mList.add(gif);
}else if(split[0].contains("avi"))
{
String castNames = "";
boolean first = true;
for(int i = 7; i < 15; i++)
{
if(!(split[i].isEmpty()))
{
if(first)
{
castNames += split[i];
first = false;
}else{
castNames += "," + split[i];
}
}
}
Avi avi = new Avi(split[1]/*title*/,split[0]/*filename*/,Integer.parseInt(split[3])/*releaseyear*/,split[2]/*studio*/,split[5]/*director*/,castNames/*castnames*/,Double.parseDouble(split[4])/*runtime*/,Integer.parseInt(split[6])/*cast*/);
mList.add(avi);
}else{
}
}
return mList;
} catch (Exception ex) { System.out.println(ex.toString()); }
return null;
}
Now it will only get the first 3 files(Console shown in picture)
I am simply trying to loop through and I am not sure why it would be out of bounds, I cannot see anything wrong with the loop, or why its giving me some but not all.
In this code you are using a String Array split from index 0 to index 14.
It would be good to do some defensive programming by checking length of String Array.
Please check the length of array before proceeding to use it in your programme.
like split.length >14
By using this habit you can always escape from 'ArrayIndexOutOfBoundsException'
I want to read lines of numbers from a file. The code is as follows but the IDE shows NullPointerException runtime exception. Not sure what I am doing wrong.
//reading the contents of the file into an array
public static void readAndStoreNumbers() {
//initialising the new object
arr = new int[15][];
try {
//create file reader
File f = new File("E:\\Eclipse Projects\\triangle.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
//read from file
String nums;
int index = 0;
while ((nums = br.readLine()) != null) {
String[] numbers = nums.split(" ");
//store the numbers into 'arr' after converting into integers
for (int i = 0; i < arr[index].length; i++) {
arr[index][i] = Integer.parseInt(numbers[i]);
}
index++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
Your second dimension of arr is uninitialized, and you are invoking
arr[index].length
You could be running into an NPEX for two reasons.
You don't finish your definition of arr - it's not evident in your code that you declare arr as int arr[][];
Even if you had the above, you wouldn't have set aside space for your second array. What you have now is a jagged array; you can have elements of whatever length in the second dimension you wish in your second array.
The only modification I made to your code to get it to work would be the following line:
arr[index] = new int[numbers.length];
...after pulling elements into numbers, and before entering the loop.
you need to change -
for(int i=0; i<arr[index].length; i++) {
to
arr[index] = new int[numbers.length];
for (int i = 0; i < numbers.length; i++) {
Java doesn't have real multidimensional arrays. What you are using is actually an array of int arrays: new int[n][] actually creates an array with room for n objects of type int[].
Consequently you will have to initialize each of those int arrays separately. That would have been obvious from the fact that you never actually specified the length of the second dimension anywhere in your program.
I think you should use StringBuilder..
//reading the contents of the file into an array
public static void readAndStoreNumbers() {
//initialising the StringBuffer
StringBuilder sb = new StringBuilder();
try {
//create file reader
File f = new File("E:\\Eclipse Projects\\triangle.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
//read from file
String nums;
int index = 0;
while ((nums = br.readLine()) != null) {
String[] numbers = nums.split(" ");
//store the numbers into 'arr' after converting into integers
for (int i = 0; i < arr[index].length; i++) {
sb.append(Integer.parseInt(numbers[i])).append("\n");
}
}
} catch (IOException e) {
e.printStackTrace();
}
}