Java Reading a 2D array from a file - java

Say I have a file of the following format:
3
4
1,2,3,4
5,6,7,8
9,10,11,12
The first two lines of the file represent the number of rows and columns of a 2D array. Thereafter, each line represents the values of each row of the 2D array. I am trying to read this file and create a 2D integer array in java. I tried the following code:
public class PrintSpiral {
private static BufferedReader in = null;
private static int rows = 0;
private static int columns = 0;
private static int [][] matrix = null;
public static void main(String []args) throws Exception {
try {
String filepath = args[0];
int lineNum = 0;
int row=0;
in = new BufferedReader(new FileReader(filepath));
String line = in.readLine();
while(line!=null) {
lineNum++;
if(lineNum==1) {
rows = Integer.parseInt(line);
System.out.println("The number of rows of the matrix are: " + rows);
} else if(lineNum==2) {
columns = Integer.parseInt(line);
System.out.println("The number of columns of the matrix are: " + columns);
matrix = new int[rows][columns];
} else {
String [] tokens = line.split(",");
for (int j=0; j<tokens.length; j++) {
System.out.println("I am filling the row: " + row);
matrix[row][j] = Integer.parseInt(tokens[j]);
}
row++;
}
}
} catch (Exception ex) {
System.out.println("The code throws an exception");
System.out.println(ex.getMessage());
} finally {
if (in!=null) in.close();
}
System.out.println("I am printing the matrix: ");
for (int i=0; i < rows; i++) {
for(int j=0; j < columns; j++)
System.out.print(matrix[i][j]);
System.out.println("");
}
}
}
The output that I see is:
The number of rows of the matrix are: 3
The number of columns of the matrix are: 3
I am filling the row: 0
I am filling the row: 1
I am filling the row: 2
I am filling the row: 3
The code throws an exception
3
I am printing the matrix:
300
300
300
3 0 0 0 0 0 3 3 0
Clearly, the java code is not reading the file correctly. Also, my code throws an exception. I am not sure what causes this exception. I can't seem to figure out what's wrong with my code. Thanks!

change
in = new BufferedReader(new FileReader(filepath));
String line = in.readLine();
while(line!=null) { .....
to
in = new BufferedReader(new FileReader(filepath));
String line = null;
while((line = in.readLine()) !=null) { .....
to read a new line at the start of each loop

You (very obviously) don't have a readLine() inside your loop, so it only ever reads the first line of the file.
Why bother having to specify the rows/columns? Why not just figure it out from the data itself?

at the end of the while loop, add in.readline();
you are just keeping the same line forever and looping on it.

Related

Why does this code add the same entry from my csv file to the 2d array?

I am reading from a csv file called bookings which has 3 rows currently
1,000,Test Name,1,First
2,000,Another Name,2,First
3,001,Yet Another,3,Business
I have a method which is meant to read through the file and add each element into a 2d array of bookings, however, the method instead adds the same record to all elements in the 2d array
Output:
Bookings: [[3, 001, Yet Another, 3, Business], [3, 001, Yet Another, 3, Business], [3, 001, Yet Another, 3, Business]
Code:
public class Booker {
int flightsLength;
int nextFlight;
// 2D Array representing bookings
String[][] bookings = new String[1000][5];
// Read bookings from csvr
//file path
String path ="bookings.csv";
//current line being read
String line;
public void readBookings() {
try {
//new buffered reader object named br
BufferedReader br;
System.out.println("RUNNING:");
//initialise the buffered reader with the file as a parameter
br = new BufferedReader(new FileReader(path));
// Store length of flights csv
flightsLength = getFlightsCount();
//while next line is available, loop
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
for (int row = 0; row < flightsLength; row++) {
for (int cell = 0; cell <= 4; cell++) {
bookings[row][cell] = values[cell];
}
}
}
System.out.println("Bookings: " + Arrays.deepToString(bookings));
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
}
Please let me know if I should explain the code more or if there is any confusion, and thank you in advance for the help.
You read each line, parse it, and then proceed to add its values to ALL the rows from 0 to flightsLength, every time.
Instead you need to read each line, parse it, and then add it to the next row in your bookings.
Effectively, get rid of the for (int row = 0; row < flightsLength; row++) { (and the matching }) that ruin things for you, and maintain your own row index, something like:
int row = 0;
//while next line is available, loop
while ((line = br.readLine()) != null) {
String[] values = line.split(",");
for (int cell = 0; cell <= 4; cell++) {
bookings[row][cell] = values[cell];
}
row++;
}

Filling a double[][] from the CSV file

I have this CSV file:
World Development Indicators
Number of countries,4
Country Name,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014
Bangladesh,6.28776238,13.20573922,23.46762823,30.16828408,34.35334451,44.94535882,55.19256723,62.82023906,74.42964608,80.03535051
"Bahamas, The",69.21279415,75.37855087,109.340767,102.7875065,101.2186453,118.8292307,81.5628489,80.65383375,76.05187427,82.29635806
Brazil,46.31418452,53.11025849,63.67475185,78.5549801,87.54187651,100.8810115,119.0023853,125.0018521,135.3050481,138.9514906
Germany,94.55486999,102.2828888,115.1403608,126.5575074,126.2280577,106.4836959,109.6595675,111.5940398,120.9211651,120.4201855
I am trying to store countries' data(double once) into a matrix(double[][]). Here is the code that I have so far:
public double[][] getParsedTable() throws IOException {
double[][] table = new double[4][10];
String row;
int indexRow = 0;
int indexColumn = 0;
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine();
br.readLine();
String line = br.readLine();
while(line != null && !line.isEmpty()){
line = br.readLine();
String[] array = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
for(int i = 1; i < array.length; i++){
table[indexRow][indexColumn] = Double.parseDouble(array[i]);
indexColumn++;
}
indexColumn = 0;
indexRow++;
}
System.out.print(Arrays.deepToString(table));
return table;
}
I am getting an arror : NullPointerException at:
String[] array = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
I cant figure out why. I tried different combinations. nothing seems to work. It seems to pick up the numbers from the CSV file and store them, but when I call:
System.out.print(Arrays.deepToString(table));
it does not print out anything, hence I cant check if its stored properly or not. Could you tell me: 1. Why I am getting an error. 2. Why System.out.println does not print out an array. Thanks
If we assume that name of a country will not contain a digit and country name and numbers will be only comma separated, then following can be done without regex. I have changed file reading a little bit because it can run into issues.
public double[][] getParsedTable() throws IOException {
double[][] table = new double[4][10];
int indexRow = 0;
int indexColumn = 0;
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine(); // ignore first line
br.readLine(); // ignore second line
br.readLine(); // ignore third line (contains title)
String line;
while (true) {
line = br.readLine();
if (line == null) break; // end of file reading
int index = 0;
while (true) {
index = line.indexOf(",", index) + 1;
if (Character.isDigit(line.charAt(index))) {
break;
}
}
// from index, line is expected to contain comma separated numbers
String[] array = line.substring(index).split(",");
for (int i = 0; i < array.length; i++) {
table[indexRow][indexColumn] = Double.parseDouble(array[i]);
indexColumn++;
}
indexColumn = 0;
indexRow++;
}
System.out.print(Arrays.deepToString(table));
return table;
}
In the csv, first 3 lines are not real country's data. So read in line-4 before while loop starts.
In while loop, first finish the processing of line string first. Eg: regular expression check & assign split data into table.
Then only read in next line at end of while loop, to be processed in next iteration.
Feel free to try this out:
public double[][] getParsedTable() throws IOException {
double[][] table = new double[4][10];
int indexRow = 0;
int indexColumn = 0;
// check whether you need to handle any exception for this
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = null;
try {
// line 1-3 are not real country's data
br.readLine();
br.readLine();
br.readLine();
// first country data begin at line 4
line = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
while (line != null && !line.isEmpty()) {
String[] array = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
for (int i = 1; i < array.length; i++) {
table[indexRow][indexColumn] = Double.parseDouble(array[i]);
indexColumn++;
}
indexColumn = 0;
indexRow++;
// read next line only at end of loop, not beginning of loop
// line is ready to be processed at next iteration
try {
line = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.print(Arrays.deepToString(table));
return table;
}
Arrays.deepToString is wrong. You are passing in an array of primitives. When you pass it in, you pass in double[][]. This is interpeted as Object[] where the objects are double[], so it will try to print double[] objects, and not print doubles.
One solution is to create an array Double[][].
Change
double[][] table = new double[4][10];
to
Double[][] table = new Double[4][10];
Autoboxing will convert each double to a Double. Since Double is an object and not a primitive, deepToString will print out each Double individually. If you read the javadoc for deepToString it explains that it operates recursively on arrays of reference type, not on primitive arrays.
If you want to stick with double[][]
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
System.out.print(table[i][j]);
System.out.print(' ');
}
System.out.println();
}

Reading CSV file in Java with headers and multiple columns

I am reading a CSV file that looks like the following:
Red Blue Green
1st Y N
2nd Y Y N
3rd N Y
I want the output to be something like
1st Red Y
1st Blue N
2nd Red Y
2nd Blue Y
2nd Green N
3rd Red N
3rd Green Y
I am pulling in the colors row into an array, but I am not sure how to get my desired output. Below is my code so far:
public String readFile(File aFile) throws IOException {
StringBuilder contents = new StringBuilder();
ArrayList<String> topRow = new ArrayList<String>();
try {
BufferedReader input = new BufferedReader(new FileReader(aFile));
try {
String line = null;
while (( line = input.readLine()) != null){
if(line.startsWith(",")) {
for (String retval: line.split(",")) {
topRow.add(retval);
//System.out.println(retval);
}
}
}
}
finally {
input.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
return contents.toString();
}
The first row needs to be read and stored as array/list (I prefer array here, as it will be faster). Then subsequent rows needs to be parsed and stored, with the column name fetched from the first row, now stored as array.
In the code, I have directly written a String with line breaks, I suggest to use a List of String Array (of length 3), so that it can be used easily for any future action.
public String readFile(File aFile) throws IOException {
String data = "";
try {
BufferedReader input = new BufferedReader(new FileReader(aFile));
String line = null;
int cnt = 0;
String[] topRow = new String[0];
while (( line = input.readLine()) != null){
if(cnt==0){
String[] l = line.split(",");
topRow = new String[l.length-1];
for(int i= 0; i<l.length-1; i++){
topRow[i] = l[i+1];
}
}
else{
String[] l = line.split(",");
for(int i= 1; i<Math.min(l.length, topRow.length+1); i++){
if(!l[i].equals("")){
String row = "";
row = l[0];
row = row + " " + topRow[i-1];
row = row + " " + l[i];
if(data.equals(""))data = row;
else data = data + "\n" + row;
}
}
}
cnt++;
}
}
catch (IOException ex){
ex.printStackTrace();
}
return data;
}

Reading text file character by character into a 2d char[][] array

I have to read in a text file called test.txt. the first line of the text file are two integers. these integers tell you the rows and columns of the 2D char array. The rest of the file contains characters. the file looks a bit like: 4 4 FILE WITH SOME INFO except vertically on top of one another not horizontally. I must then read each of the rest of the contents of the file into the 2D char[][] array using nested for loops. I am not supposed to copy from one array to another. This is the code I have so far. I'm having trouble reading each character line by line into my 2D char array. Help been working at this for hours.
public static void main(String[] args)throws IOException
{
File inFile = new File("test.txt");
Scanner scanner = new Scanner(inFile);
String[] size = scanner.nextLine().split("\\s");
char[][] array = new char[Integer.parseInt(size[0])][Integer.parseInt(size[1])];
for(int i=0; i < 4; i++) {
array[i] = scanner.nextLine().toCharArray();
}
for(int k = 0; k < array.length; k++){
for(int s = 0; s < array[k].length; s++){
System.out.print(array[k][s] + " ");
}
System.out.println();
}
scanner.close();
}
}
If I have understood it correctly - file format is something like
4 4
FILE
WITH
SOME
INFO
Modify as below
Scanner scanner = new Scanner(inFile);
String[] size = scanner.nextLine().split("\\s");
char[][] array = new char[Integer.parseInt(size[0])][Integer.parseInt(size[1])];
for(int i=0; i < rows; i++) {
array[i] = scanner.nextLine().toCharArray();
}
Above code is for initialization of you char array. In order to print the same you can do something like
Arrays.deepToString(array);
Copying Tirath´s file format:
4 4
FILE
WITH
SOME
INFO
I would pass it into a 2d array as follows:
public static void main(String[] args){
char[][] receptor = null; //receptor 2d array
char[] lineArray = null; //receptor array for a line
FileReader fr = null;
BufferedReader br = null;
String line = " ";
try{
fr = new FileReader("test.txt");
br = new BufferedReader(fr);
line = br.readLine();//initializes line reading the first line with the index
int i = (int) (line.toCharArray()[0]-48); //we convert line to a char array and get the fist index (i) //48 = '0' at ASCII
int j = (int)(line.toCharArray()[1]-48); // ... get the second index(j)
receptor = new char[i][j]; //we can create our 2d receptor array using both index
for(i=0; i<receptor.length;i++){
line = br.readLine(); //1 line = 1 row
lineArray = line.toCharArray(); //pass line (String) to char array
for(j=0; j<receptor[0].length; j++){ //notice that we loop using the length of i=0
receptor[i][j]=lineArray[j]; //we initialize our 2d array after reading each line
}
}
}catch(IOException e){
System.out.println("I/O error");
}finally{
try {
if(fr !=null){
br.close();
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
} //end try-catch-finally
}

java.util.NoSuchElementException Not printing desired output

I'm writing a Java program to try to parse a text file and store the contents of it in a matrix. The following is my Java code:
import java.io.*;
import java.util.*;
public class Viterbi
{
String[][] gmatrix = new String[50][4];
float[] pmatrix = new float[50];
public Viterbi(String filename)
{
BufferedReader br = null;
try
{
String currentline;
StringTokenizer st;
br = new BufferedReader(new FileReader(filename));
while((currentline = br.readLine()) != null)
{
st = new StringTokenizer(currentline, ";");
while(st.hasMoreTokens())
{
for(int i=0; i<50; i++)
{
for(int j=0; j<4; j++)
{
gmatrix[i][j] = st.nextToken();
System.out.println("i --> " + i + " j--> " + j + ": " + gmatrix[i][j]+"\t");
}
}
}
}
for(int i=0; i<50; i++)
{
for(int j=0; j<3; j++)
System.out.print(gmatrix[i][j]+"\t");
System.out.println("");
}
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if(br != null)
br.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public static void main(String[] args)
{
Viterbi v = new Viterbi("rules.txt");
}
}
And here's the contents of the text file:
S;a;S;0.6
S;b;X;0.4
X;c;$;0.1
X;X;$;0.9
I want the output to be displayed in the gmatrix as:
S a s
S b X
X c $
X X $
But for some reason I get the following output and exception:
i --> 0 j--> 0: S
i --> 0 j--> 1: a
i --> 0 j--> 2: S
i --> 0 j--> 3: 0.6
java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
at Viterbi.<init>(Viterbi.java:27)
at Viterbi.main(Viterbi.java:62)
How can I print the correct output as desired?
In your code, you are only calling hasNextToken() once at the start of the while condition. You need to call hasNextToken() as many times as nextToken(), to make sure that nextToken() will work. The reason you don't have any more tokens on the line is that there are only 4 tokens per line (apparently) but you have two for loops that will try to call nextToken() a total of 50*4=200 times.
Alternatively to how you are doing this: you could just split the currentLine on ";" with the split() method and then loop through the returned String[] elements.
In your first while loop, you are actually trying to populate the whole gmatrix by parsing a single line of the input file. This is not what you expect. Since there are only 4 tokens in the first line, you get the exception when you are trying to call st.nextToken() to get the next (non-existing) token when the program is trying to get gmatrix[1][0].
To correct your code, you should check and read a new input line in your first for(int i = ...) loop, and remove the 2 out-most while loops.
Example:
for(int i = 0; ...){
// check if there is another line in input;
// tokenize a line of input;
for(int j = 0; ...){
// get a token and populate one element in gmatrix;
}
}
Instead of using the two while loops.

Categories

Resources