Alright, lets try this again, sorry for the poor title I don't know what to call this. I haven't done much File I/O before, I personally think Java is absolutely terrible at it but nonetheless I have to do it.
A bit of background information, this is my Conway's Game of Life project, and all of my other code works fine I just need to do the I/O now.
I'm reading in from a text file, that looks like this.
So what this does is the first two numbers are the size of that the array needs to be, the String after them is irrelevant. And after that is the array of the cell arrangement in this example it's that of the glider. Now my problem is that I don't know how to store the first line in a String, and the rest in an array. Below is what I've done, and brace yourselves for a Big O of n^∞.
public char[][] fileIO(){
ArrayList<String> list = new ArrayList<String>();
char[][] newArray;
String[] tokens;
BufferedReader reader;
String inputLine;
try{
reader = new BufferedReader(new FileReader("untitled.txt"));
while((inputLine = reader.readLine()) != null){
list.add(inputLine);
}
reader.close();
}catch (IOException e){
System.out.println(e);
}
tokens = list.get(0).trim().split("\\s+");
newArray = new char[Integer.parseInt(tokens[0])][Integer.parseInt(tokens[1])];
for(int row = 0; row < newArray.length; row++){
for(int col = 0; col < newArray[row].length; col++){
for(int line = 1; line < list.size(); line++){
for(int Char = 0; Char < list.get(line).length(); Char++){
newArray[row][col] = list.get(line).charAt(Char);
}
}
}
}
return newArray;
}
I know there's a lack of comments, so I'll try to explain what I tried to do now;
I read from the file and stored it all in an ArrayList
Got the tokens of the first like (10 20 Glider), and created an instantiated an array with the values 10 and 20
Then proceeded to loop through the array's rows and columns, then each line of the inputted array, and then looped through each character of that line to add into the array at their respected positions.
However, this doesn't seem to be working and I'm sure there is a much simpler and efficient way of doing this. So I ask again, can anyone tell me of a simpler way of doing this I/O? I don't need the code, just an explanation of how to do so.
In this:
for(int row = 0; row < newArray.length; row++){
for(int col = 0; col < newArray[row].length; col++){
for(int line = 1; line < list.size(); line++){
for(int Char = 0; Char < list.get(line).length(); Char++){
newArray[row][col] = list.get(line).charAt(Char);
}
}
}
}
You have two outer loops that are browsing through your newArray grid, and two inner loops that are browsing through the lines of the file. By doing that, you are essentially writing every char of every lines of your file into each cell of your grid, one after the other. In the end, you will have the last character of the last line of your file in all the cells of newArray. This is probably not what you want to do.
Edit: If I understand correctly, the number at the beginning of the file are the number of lines and the number of columns of the data that follow. Then you just have to use the two outer loops, and use row and col to access respectively the line in list and the character in the line.
Related
I was working through a project and I have to use charAt to continuously add elements of an array from a text file to a new array that i would have specified. The size of the array differs depending on the text file being used so it is best to assume that the contents of the file are unknown, however i will provide an example.
I keep on getting a "StringIndexOutOfBoundException" when i run my code and i am not sure why, or how to fix it.
What the code should be doing is taking the user input to get the exact text file location, then it will be reading that line by line and adding that to a new array. The first two lines of the text file array are the array row and column size.
my code is as follows:
public static void main(String[] args) throws FileNotFoundException
{
System.out.println("Enter the location of the board file using the FULL PATH NAME.");
Scanner input = new Scanner(System.in);
String n = input.nextLine();
input.close();
File a = new File(n);
Scanner sc = new Scanner(a);
int row = sc.nextInt();
int col = sc.nextInt();
char[][] board = new char[row][col];
for (int numRow = 0; numRow < row+1; numRow ++)
{
String string = sc.next();
for (int numCol = 0; numCol < col+1; numCol++)
{
board[row][col] = string.charAt(numCol);
}
}
sc.close();
GridGame game = new GridGame (row, col, board);
game.playGame();
An example input text file:
10 10
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
SWWWWWWWWW
EEEEEEEEES
TWWWWWWWWW
The issue you are facing is because a Java array has 0-based index i.e. the index of the first element is 0 and that of the last element is array.length - 1. Therefore, your loop with the variable as the index of the array should not go beyond array.length - 1. Your terminating condition, numRow < row+1 is taking the value of numRow up to the length of the array instead of array.length - 1.
Replace
for (int numRow = 0; numRow < row+1; numRow ++)
{
String string = sc.next();
for (int numCol = 0; numCol < col+1; numCol++)
{
board[row][col] = string.charAt(numCol);
}
}
with
for (int r = 0; r < row && sc.hasNextLine(); r++) {
board[r] = sc.nextLine().toCharArray();
}
The other concept you need to understand is a 2-D array in Java an array of arrays i.e. board[0] should hold the array of characters from the first line of the file, board[1] should hold the array of characters from the second line of the file and so on. Now, if you want to access the 4th character of the 3rd line from the file, you can access it as board[2][3].
The last but not the least is regarding closing the Scanner for System.in. You should never close this Scanner because it also closes the System.in. So, you should remove the line, input.close() from your code.
Update
You can write the above mentioned single loop as a nested loop as well but it is unnecessary.
for (int r = 0; r < row && sc.hasNextLine(); r++) {
char[] lineChars = sc.nextLine().toCharArray();
for(int c = 0; c < col; c++) {
board[r][c] = lineChars [c];
}
}
You need a nested loop in order to access/process individual characters but to store/access/process each row of a 2-D array, you do not need a nested loop. As I have already mentioned, a 2-D array is an array of 1-D arrays and therefore to access each of these 1-D arrays (not individual elements inside these 1-D arrays), you need a single loop, not a nested loop.
I have a .txt file with 1302 lines, which divides evenly to 14 x 93 (corresponding to 14 columns and 93 rows). I would like to parse the 1302 lines into a [93][14] multi-dimensional array. I have the following script that traverses each individual "cell", but as for the file parsing, I have some questions.
int rows = 93;
int columns = 14;
int i;
int j;
int count = 0;
String[][] array = new String[rows][columns];
for(i = 0; i < rows; i++){
for(j = 0; j < columns; j++){
System.out.println(i + "," + j);
count++;
}
}
How do I assign each "line" of the text file into each cell?
My Recommendation (aside from changing using double[][] to something like List<List<Double>>) would be to go through each text line as such:
InputStream fis;
BufferedReader br;
String line;
fis = new FileInputStream("the_file_name");
br = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
while ((line = br.readLine()) != null) {
// Deal with the line
}
// Done with the file
br.close();
br = null;
fis = null;
With this, you should be able to get each individual 'line' of the file. The reason I mention above using the List<List<Double>> instead of double[][] is because you get two things out of that:
1) dynamic resizeability. Even if you know the size and want to give that list a default size to help with performance, you aren't LIMITED to that size, which is worth it's weight in.. flops? programmers gold.
2) using the primitive double (lowercase d) as opposed to the Java object Double (uppercase D) really kill you as far as not getting access to a LOT of great methods and useability built into Double (capitol D object). for more explanation on this, see: Double vs. double
Also note, the code above has no error checking, so you'll want to build some of that into it, it's a pretty basic implementation.
EDIT::
Alright, so in your code that you posted at: code snipped you have a double for-loop INSIDE of the readLine() loop. like so:
while ((line = br.readLine()) != null) {
for (int i = 0; i < rows; i++){
for(int j = 0; j< columns; j++){
line = array[i][j];
}
}
}
Now, there are two problems with this:
1) you are setting LINE equal to the content of array[i][j] which means nothing, since array is just an empty 2-dimensional array.
2) for EVERY line in the text file you are looping 1302 times (and then some more because you're doing (1302 * columns) * 1302
really what this code above does, is it takes care of your 'row' loop. so instead of what you're doing, just do:
int i = 0;
while ((line = br.readLine()) != null) {
array[i][0] = line;
i++
}
that will fill up your array with all of the strings from the file.
Read in the lines (rows) with Scanner or BufferedReader, then use split("\\s+"); to split the lines into tokens (columns). Then use Double.parseDouble() on each of the tokens and then insert it into your array.
In order to assign anything to a 2D matrix, you can do something like this:
for (int r=0; r<NUM_ROWS; r++)
for (int c=0; c<NUM_COLS; c++)
matrix[r][c] = get_line(r*NUM_COLS + c)
Where get_line(i) will get the i'th line in the file
I' re-doing an exam for practicing and i've almost completed it. The only problem i have is with this part:
int z=0,x=0;
String line="";
RandomAccessFile read = new RandomAccessFile(s, "rw");
while((read.readLine())!=null)
z++;
read.seek(0);
while(x<z){
line=read.readLine();
StringTokenizer stk = new StringTokenizer(line, " ");
if(line.charAt(0)=='r'){
nr=z;
nc=stk.countTokens()-1;
valori = new int[nr][nc];
while(stk.hasMoreTokens()){
stk.nextToken();
for(int i=0; i<nr; i++)
for(int j=0; j<nc; j++)
valori[i][j] = Integer.parseInt(stk.nextToken());}
}
else if(line.charAt(0)=='c'){
nr=stk.countTokens()-1;
nc=z;
valori = new int[nr][nc];
while(stk.hasMoreTokens()){
stk.nextToken();
for(int i=0; i<nr; i++)
for(int j=0; j<nc-1; j++)
valori[j][i] = Integer.parseInt(stk.nextToken());}
}x++;
Basically i have to read a file where i have the description of a matrix as follows:
c 0 1 0
c 0 0 1
c 0 0 0
c 1 0 0
And the resulting matrix would be
|0|0|0|1|
|1|0|0|0|
|0|1|0|0|
After reading the file i have to build the matrix with a 2d int array, i used the same code from another exercise but when using stk.nextToken() i get java.util.NoSuchElementException at java.util.StringTokenizer.nextToken(Unknown Source)
I cannot find the error, 2d arrays are correctly initialized and filled.
Thanks in advance for any help.
The "Unknown Source" part of the exception is an effect of running your code through the jre instead of the JDK. If you run with the JDK, your runtime environment will have access to the debug info and proper line numbers will be printed instead.
a quick look suggests that this section is in error:
nr=stk.countTokens()-1;
nc=z; //z == # of rows
//first pass through = hasMoreTokens == true (a total of 4: C,0,1,0)
while(stk.hasMoreTokens()){
//first token - C
stk.nextToken();
//this will iterate 3 times
for(int i = 0; i < nr; i++)
//this, too, will iterate 4 times - a total of 12 times considering
// the outer loop
for(int j = 0; j < nc-1; j++)
// after 3 passes, this will throw the exception
valori[j][i] = Integer.parseInt(stk.nextToken());}
}x++;
This error means that there are no more tokens in the StringTokenizer remaining, and you are asking for a one more token. "Unknown source" is not relevant to your problem - this just means you have no access to the source code of the Java system library but I doubt it will be helpful.
This happens because the line you read from the file contains less space delimited tokens than you expect.
The error happens because you are tokenizing one single line, and in the two for loops you are reading columns and rows.
Instead of using the StringTokenizer with while loops I would recommend to use the .split command:
int j=0;
// read all rows
while((read.readLine())!=null) {
String line=read.readLine();
String[] columns=line.split(" ");
// read columns of each row
int i=0;
for (String column: columns) {
if (!column.equals("c")) {
valori[j][i] = Integer.parseInt(column);
}
i++;
}
j++;
}
PS: Pseudo code above, untested.
I'm new to Java programming...
I'm trying to read data from text file and save it into 2D array. So basically, program will receive parameter (IP) and look for the file with same IP number.
And the program will read each line and store into an 2D array.
My attempt:
String ipNum = request.getParameter("ipNum");
String root = getServletContext().getRealPath("/");
String dailyPath = root + "\\" + ipNum +".txt";
int[][] myarray = new int[3][6];
BufferedReader br = new BufferedReader(new FileReader(dailyPath));
String line = " ";
String [] temp;
while ((line = br.readLine())!= null){
temp = line.split(" ");
for(int i = 0; i<myarray.length; i++) {
for (int j = 0; j<myarray.length; j++) {
myarray[i][j] = Integer.parseInt(temp[i]);
}
}
}
Data:
CPU 30 30 30 30 30 30
RAM 70 70 70 70 70 70
HAR 80 80 80 80 80 80
NET 100 100 100 100 100 100
the problem that I'm having is that when I call array, I always get 100 or 0 (assuming empty)
so for example myarray[1][2] should output 30 but i get 100
myarray [2][4] = 70 but i get 100...
I tried to play around with the code for past few hours, I can't figure it out...is my whole code wrong or something?
Thanks for help!
Yeah, you are iterating twice and therefore filling your array with the last value... try this code:
int i = 0;
while ((line = br.readLine())!= null){
temp = line.split(" ");
for (int j = 0; j<myarray[i].length; j++) {
myarray[i][j] = Integer.parseInt(temp[j]);
}
i++;
}
Hope this helps...
Besides Joshs remark you also set the termination conditions the wrong way.
for(int i = 0; i< myarray.length; i++) {
for (int j = 0; j< myarray[i].length; j++) {
myarray[i][j] = Integer.parseInt(temp[i]);
}
}
This way you can iterate through the array but you can't use this to solve your problem. Instead you need to use 1 while-loop and 1 for-loop.
It looks to me like you're reading each line of text and then parsing that line into a 2D array. This isn't entirely correct as each line can be considered a row. Maybe you could use a counter for each line you read in your while ((line = br.readLine())!= null) loop and then only read into the row of your 2D array at the counter index... like so:
int rowCounter = 0;
while ((line = br.readLine())!= null) {
for(int i = 0; i<myarray.length; i++)
myarray[rowCounter][i] = Integer.parseInt(temp[i]);
rowCounter++;
}
As a side note, if you did want to index into a multidimensional array you also have a side problem. In both of your loops you are iterating until you reach the max number of rows. For your j loop going through the columns this might cause a problem. Instead when using a 2D loop try:
for(int i = 0; i < array.Length; i++)
for(int j = 0; j < array[0].Length; j++)
//Do some stuff
Your 'while' loop and your first 'for' loop are performing a similar task--for each line you read, you are iterating over every row in your array and filling it's columns with the line you are reading. Every value is 100 because the last line you read is full of 100s.
I suggest removing the first 'for' loop, declare 'int i = 0;' before the 'while' loop, and an 'i++' at the bottom (but inside) the for loop.
#Vivek makes a good point that you need to measure 'myArray[ i ].length' for your j counter.
What I'm trying to do is I have this program which reads in a number, and that number designates how many words there are, for example:
3
red
blue
green
And then prints out that same text but in reverse order so it would be
green
blue
red
followed by a blank line indicating to the server that you are done with that specific problem. But I seem to have a bug in my code somewhere.
I tried to store the words in an array List. I used a for loop to store them in the list and then to print them out in reverse order I just used another for loop going the opposite way, starting from the end of the list going to the beginning.
When I run the program from the command prompt it just goes to the next command prompt line as if I had as it to compile the program, there are no errors but when I
did a test, using a test program I created, it seems that the program reads the number but then goes and prints out a blank array.
It would seem as though the words from the server don't get stored in the array and I'm not sure what I'm doing wrong. I'm not the greatest programmer so any help would greatly be appreciated.
The Code:
import java.io.*;
import java.util.*;
public class Solution
{
public static void run(BufferedReader in, PrintWriter out)
throws IOException
{
int x = Integer.parseInt(in.readLine());
while(x != 0)
{
ArrayList num = new ArrayList();
for(int i = 0; i < num.size(); i++)
{
//String f = in.readLine();
num.add(in.readLine());
}
//System.out.println(num);
for(int i = num.size()-1; i > 0; i--)
{
out.println(num.get(i));
//x = Integer.parseInt(in.readLine());
System.out.println();
}
break;
}
out.flush();
}
}
ArrayList num = new ArrayList();
for(int i = 0; i < num.size(); i++)
means you go from 0 to... 0!
for(int i = 0; i < x; i++)
would be better.
The while loop never stops
EDIT: Oops no, this is not true, but what is the point of having a while loop that runs once? You put a break at the end of it, so maybe you could refactor that to an if? Maybe a guard?
The size of num here is 0. You should use 'x' instead of num.size()
for(int i = 0; i < num.size(); i++)
{
//String f = in.readLine();
num.add(in.readLine());
}
This might not be the exact what you have done.. a bit different.. :-)
int x = Integer.parseInt(in.readLine());
String[] arr = new String[x]; // Edited :: Slip of mind - Thanks Pgras
for(int i=0;i<x;i++){ //input x number of words and store..
arr[i] = in.readLine();
}
for(i=x-1;i>=0;i--){ //Display words in reverse order
System.out.println(arr[i]);
}