I am reading in a file using a scanner. The file is formatted with the first line being the dimensions of the array. The next line contains the 1st row, next line the second, etc. Example file:
3 3
1 2 3
4 5 6
7 8 9
The problem I keep running into is that my array values seem to be all 9. The file is in ints but I need them in doubles. I also have a lot of print statements in there as I am trying to debug what was going on. My exception handling isn't finished. I will go back and beef that up after I can instantiate the array correctly. Any pointers would be appreciated. For example: a better way of getting the dimensions and instantiating the array with just opening the file once.
Updated but getting a nullPointerException
public class Help implements TopoMapInterface {
private String filename;
private File mapfile;
public double[][] baseMap;
public double[][] enMap;
public int enhancementLevel;
public Help(String filename) throws FileNotFoundException,
InvalidFileFormatException {
this.filename = filename;
System.out.println("Reading in file: " + filename);
String number = "";
int row = 0;
int col = 0;
int count = 0;
try {
Scanner inputFile = new Scanner(new File(filename));
while (inputFile.hasNextInt()) {
row = Integer.parseInt(inputFile.next());
col = Integer.parseInt(inputFile.next());
System.out.println("Row : " + row);
System.out.println("Col : " + col);
baseMap = new double[row][col];
System.out.println(baseMap[2][4]);
for (int i = 0; i < baseMap.length; i++){
for (int j = 0; j < baseMap[i].length; j++){
baseMap[i][j] = Double.parseDouble(inputFile.next());
}
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
Assuming that your first line has the value of row first and then column
I would do this
int row = Double.parseDouble(inputFile.next());
int col = Double.parseDouble(inputFile.next());
for (int i = 0;i<row;i++){
for(j=0;j<col;j++)
{
baseMap[i][j]=Double.parseDouble(inputFile.next());
}}
This should store all your values in double as you want and I think so this is an easier way to store after reading from file.
I think so I got your question correct!
Every single time you read in a number when count1 > 2, you're then iterating over your entire matrix and inserting doubleVal into every single cell; the last value you see is 9, and so that's what you have everywhere.
More generally, if you're guaranteed to have correct input (i.e., you have a school exercise like this one), then you shouldn't be reading your dimension specifications inside a loop; you should read the first two ints, create the array based on that size, and then use a nested for loop to insert the values into the array.
for (int r = 0; r < baseMap.length; r++){
for (int c = 0; c < baseMap[r].length; c++){
baseMap[r][c] = doubleVal;
}
}
is where the problem lies.
this iterates through every row and column of the array, setting every element to the current number
since the last number you see is 9, that;s what gets left in the array.
what you really need is some other way of keeping track of row and column counts, rather than iterating through the array. perhaps a pair of counters?
int intVal = Integer.parseInt(number);
double doubleVal = (double) intVal;
should probably be replaced with
double doubleVal = Double.parseDouble(number);
file reading improvements as given by No Idea For Name
would significantly improve this code. though using is a java 7 and later only construct.
for earlier versions. upgrade if you can, remember to close the resources otherwise.
first of all when using scanner or any other stream, you should close them in the end using a finally statement
Scanner inputFile = null;
try{
inputFile = new Scanner(new File(filename));
}
catch{}
finally{
if(inputFile != null)
inputFile.close();
}
this will ensure that you will release the scanner when done reading and not hold it to the next loop.
also, in your code, in the second while loop you seem to not close it right, and so in each loop this code is called:
if (count1 > 2){
for (int r = 0; r < baseMap.length; r++){
for (int c = 0; c < baseMap[r].length; c++){
baseMap[r][c] = doubleVal;
}
}
last thing, you are opening the file twice! there is no need for that. at the very minimum you can change your code to:
public class Help implements TopoMapInterface {
private String filename;
private File mapfile;
public double[][] baseMap;
public double[][] enMap;
public int enhancementLevel;
public Help(String filename) throws FileNotFoundException,
InvalidFileFormatException {
this.filename = filename;
System.out.println("Reading in file: " + filename);
String number = "";
int row = 0;
int col = 0;
int count = 0;
Scanner inputFile = null;
try {
inputFile = new Scanner(new File(filename));
number = inputFile.next();
System.out.println(number);
row = Integer.parseInt(number);
number = inputFile.next();
col = Integer.parseInt(number);
int count1 = 0;
baseMap = new double[row][col];
while (inputFile.hasNextInt()) {
count1++;
number = inputFile.next();
int intVal = Integer.parseInt(number);
double doubleVal = (double) intVal;
}// Closed your while loop here
if (count1 > 2){
for (int r = 0; r < baseMap.length; r++){
for (int c = 0; c < baseMap[r].length; c++){
baseMap[r][c] = doubleVal;
}
}
System.out.println(doubleVal+"*");
}
}
System.out.println("end of this while loop");
} catch (Exception e) {
System.out.println(e.toString());
}
finally
{
if(inputFile != null)
inputFile.close();
}
try {
System.out.println("Row = " + row + " Col = " + col);
for (int r = 0; r < baseMap.length; r++) {
for (int c = 0; c < baseMap[r].length; c++) {
System.out.print(baseMap[r][c] + " ");
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
I am not sure why you are scanning the file two times, but if you are then here is the problem in your code
for (int r = 0; r < baseMap.length; r++){
for (int c = 0; c < baseMap[r].length; c++){
baseMap[r][c] = doubleVal;
}
}
Following code will solve your problem:
try {
Scanner inputFile = new Scanner(new File(filename));
int count1 = 0;
int r = -1, c = -1;
baseMap = new double[row][col];
while (inputFile.hasNextInt()) {
count1++;
number = inputFile.next();
int intVal = Integer.parseInt(number);
double doubleVal = (double) intVal;
if (count1 > 2){
if (count1 % row == 0)
r++;
c = count1 % col;
baseMap[r][c] = doubleVal;
System.out.println(doubleVal+"*");
}
}
inputFile.close();
System.out.println("Row = " + row + " Col = " + col);
for (r = 0; r < baseMap.length; r++) {
for (c = 0; c < baseMap[r].length; c++) {
System.out.print(baseMap[r][c] + " ");
}
}
} catch (Exception e) {
System.out.println(e.toString());
}
Also don't forget to put a break in your first scanning
if (count == 1) {
row = Integer.parseInt(number);
} else if (count == 2) {
col = Integer.parseInt(number);
break;
}
Related
Hi i want to fill a 2d array with comma separated values like this
3
1,2,3
4,5,6
7,8,0
first number the size of the array, the next values are the values of the array this is my code at the moment
//readfile
public static void leeArchivo()
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try
{
//read first value which is teh size of the array
size = Integer.parseInt(br.readLine());
System.out.println("size grid" + size);
int[][] tablero = new int[size][size];
//fill the array with the values
for (int i = 0; i < tablero.length; i++)
{
for (int j = 0; j < tablero[i].length; j++ )
{
tablero[i][j] = Integer.parseInt(br.readLine());
}
}
br.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
This method is working fine for me, just another question, this will work if I want to insert another 2d array of the same size next to the other?
public static void leeArchivo()
{
Scanner s = new Scanner(System.in);
size = Integer.parseInt(s.nextLine());
tablero = new int[size][size];
boolean exit = false;
while (!exit) {
for (int i = 0; i < size; i++) {
//quit commas to fill array
String valuesStrArr[] = s.nextLine().split(",");
for (int j = 0; j < size; j++) {
tablero[i][j] = Integer.parseInt(valuesStrArr[j]);
}
if (i == size - 1)
exit = true;
}
}
}
Example:
3
1,2,3
4,5,6
7,8,0
1,2,3
8,0,4
7,6,5
Solution using Scanner
Scanner s = new Scanner(System.in);
int size = Integer.parseInt(s.nextLine());
int[][] tablero = new int[size][size];
boolean exit = false;
while (!exit) {
for (int i = 0; i < size; i++) {
String valuesStrArr[] = s.nextLine().split(",");
for (int j = 0; j < size; j++) {
tablero[i][j] = Integer.parseInt(valuesStrArr[j]);
}
if (i == size - 1)
exit = true;
}
}
Scanner in = new Scanner(System.in);
int num = in.nextInt();
Use Scanner. Replace System.in with File.
First, you have to separate the elements.
You can do this using the String method split (https://www.javatpoint.com/java-string-split)
//fill the array with the values
for (int i = 0; i < tablero.length; i++)
{
String[] elements = br.readLine().split(",");
for (int j = 0; j < tablero[i].length; j++ )
{
tablero[i][j] = Integer.parseInt(elements[j]);
}
}
br.close();
Or you can use Scanner method, nextInt.
Regarding perfomance, the first option is better.
I start from the left-bottom and proceeding in clockwise direction till no chars are left. here is my code.
import java.io.*;
import java.util.*;
public class Solution {
static int count = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
char[][] matrix = new char[n][m];
char[] temp = new char[n*m];
for(int r=0;r<n;r++){
for(int col=0;col<m;col++){
matrix[r][col] = sc.next().charAt(col);
}
}
int k=0, l = 0;
while(k < n && l < m){
if(l<m){
for(int i = n-1;i>=k;i--){
temp[count] = matrix[i][l];
count++;
}
l++;
}
for(int i = l;i<m;i++){
temp[count] = matrix[k][i];
count++;
}
k++;
for(int i = k;i<n;i++){
temp[count] = matrix[i][m-1];
count++;
}
m--;
if(k < n){
for(int i = m-1;i>=l;i--){
temp[count] = matrix[n-1][i];
}
n--;
}
}
String code = String.valueOf(temp);
String[] dec = code.split("#");
//System.out.println(dec);
int count2 = dec.length;
System.out.println(count2);
}
}
So can anyone point out where I am going wrong? I start at left bottom, climb up, go right , then go down, go left and continue till no elements left.
There are two issues: incorrect input and missing counter increment.
Incorrect input:
for(int r=0;r<n;r++){
for(int col=0;col<m;col++){
// The following reads a new line each time a new character is needed
matrix[r][col] = sc.next().charAt(col);
}
}
This could be fixed either by lifting sc.next() from the inner loop:
for (int r = 0; r < n; r++) {
String line = sc.next();
for (int col = 0; col < m; col++) {
matrix[r][col] = line.charAt(col);
}
}
Or (preferable) removing inner loop completely:
for (int r = 0; r < n; r++) {
matrix[r] = sc.next().toCharArray();
}
Missing increment (lower part of the spiral):
for(int i = m-1;i>=l;i--){
temp[count] = matrix[n-1][i];
// Counter increment is missing. Add
// counter++;
}
In general, is is better to use StringBuilder for gradual construction of the string. In you case it will look as following:
StringBuilder temp = new StringBuilder();
<...>
temp.append(matrix[n-1][i]);
<...>
String code = temp.toString();
In this code you don't have to estimate possible string size nor manually track current insert position.
starting left bottom in the matrix is
matrix[0][m];
going up the hill will be made by decreasing m to a point where you already had a char inserted.
i would use 4 for loops inside a while loop like is presented:
while (usedRow < (int)0.5*n && usedCol < (int)0.5*m)
{
//usedRow and usedCol start with the value of 0 and will be raised
// by the end of the loop
int i, j;
for (i = m - usedCol; i<=(m-usedCol); i++)
{
matrix[usedRow][m-i] = sc.next().charAt(0);
}
for (j = usedRow; j <= (n-usedRow); j++)
{
matrix[n + j][usedCol] = sc.next.charAt(0);
}
for (i = usedCol; i <= (m-usedCol); i++)
{
matrix [n - usedRow][m+i] = sc.next().chatAt(0);
}
for ( j = n - usedRow; j <= (n - usedRow); j++)
{
matrix[n - j][m - usedCol] = sc.next().charAt(0);
}
usedRow++;
usedCol++;
}
this way you go clockwise and keep the loop within the rows and cols that are not in use.
hope that it helped you in a way.
I need to read ints from large csv and then do specific sums with them. Currently I have algorithm that:
String csvFile = "D:/input.csv";
String line = "";
String cvsSplitBy = ";";
Vector<Int[]> converted = new Vector<Int[]>();
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
while ((line = br.readLine()) != null) {
String[] a = line.split(";",-1);
int[] b = new int[a.length];
for (int n = 0, n < a.length(), n++){
b[n] = Integer.parseInt(a[n]);
}
converted.add(b);
}
}
catch (IOException e) {
e.printStackTrace();
}
int x = 7;
int y = 5;
int sum = 0;
for (int m = 0; m < converted.size(); m++){
for (n = 0, n < x, n++){
sum = sum + converted.get(m)[n];
}
System.out.print(sum + " ");
for (int n = x + y, n < converted.get(m).length, n = n + y){
sum = 0;
for (int o = n -y; o < n; o++)
sum = sum + converted.get(m)[n];
}
System.out.print(sum + " ");
}
System.out.println("");
}
What I tried to do, is to get sum of first x members of a csv row, and then sum of x members every +y. (in this case sum of first x - 7(sum of 0-6), then sum of next x - 7, but y - 5 columns later(sum of 5-11), (sum of 10-16)... and write them, for every row.(in the end collecting line number with greatest (sum of 0-6), (sum of 5-11).., so final result should be for example 5,9,13,155..., which would mean line 5 had the greatest sum of 0-6, line 9 greatest sum of 5-11... ) As you can see, this is a quite inefficient way. First I've read whole csv into string[], then to int[] and saved to Vector. Then I created quite inefficient loop to do the work. I need this to run as fast as possible, as i will be using very large csv with lot of different x and y. What I was thinking about, but don't know how to do it is:
do these sums in the reading loop
do the sum differently, not always looping x members backward (either saving last sum and then subtract old and add new members, or other faster way to do subarray sum)
use intStream and parallelism (parallel might be tricky as in the end i am looking for max )
use different input then csv?
all of the above?
How can I do this as fast as possible? Thank you
As the sums are per line, you do not need to first read all in memory.
Path csvFile = Paths.get("D:/input.csv");
try (BufferedReader br = Files.newBufferedReader(csvFile, StandardCharsets.ISO_8859_1)) {
String line;
while ((line = br.readLine()) != null) {
int[] b = lineToInts(line);
int n = b.length;
// Sum while reading:
int sum = 0;
for (int i = 0; i < 7; ++i) {
sum += b[i];
}
System.out.print(sum + " ");
sum = 0;
for (int i = n - 5; i < n; ++i) {
sum += b[i];
}
System.out.print(sum + " ");
System.out.println();
}
}
private static int[] lineToInts(String line) {
// Using split is slow, one could optimize the implementation.
String[] a = line.split(";", -1);
int[] b = new int[a.length];
for (int n = 0, n < a.length(), n++){
b[n] = Integer.parseInt(a[n]);
}
return b;
}
A faster version:
private static int[] lineToInts(String line) {
int semicolons = 0;
for (int i = 0; (i = line.indexOf(';', i)) != -1; ++i) {
++semicolons;
}
int[] b = new int[semicolons + 1];
int pos = 0;
for (int i = 0; i < b.length(); ++i) {
int pos2 = line.indexOf(';', pos);
if (pos2 < 0) {
pos2 = line.length();
}
b[i] = Integer.parseInt(line.substring(pos, pos2));
pos = pos2 + 1;
}
return b;
}
As an aside: Vector is old, better use List and ArrayList.
List<int[]> converted = new ArrayList<>(10_000);
Above the optional argument of initial capacity is given: ten thousand.
The weird try-with-resource syntax try (BufferedReader br = ...) { ensures that br is alway automatically closed. Even on exception or return.
Parallelism and after reformatting the question
You could read all lines
List<String> lines = Files.readAllLines(csvFile, StandardCharsets.ISO_8859_1);
And than play with parallel streams like:
OptionalInt max = lines.parallelStream()
.mapToInt(line -> {
int[] b = lineToInst(line);
...
return sum;
}).max();
or:
IntStream.range(0, lines.size()).parallel()
.mapToObj(i -> {
String line = lines.get(i);
...
return new int[] { i, sum5, sum7 };
});
You could probably try to create some of your sums while reading the input. Might also be feasible to use HashMaps of type Integer,Integer
So i have a file that looks like this:
+-+-+-+ ("/n")
|S| | ("/n")
+ + + + ("/n")
| |E| ("/n")
+-+-+-+ ("/n")
/n being a new line in the file
and i want to have each character here as an entry in a 5x7 array. I do not know how to do it, this is what i have tried (along with a lot of other things. input is the file):
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("maze0.txt"));
char maze[][] = new char[5][7];
int charCount = 0;
for (int row = 0; row < finalHeight; row++) {
for (int col = 0; col < finalWidth; col++) {
while (input.hasNextLine()){
String line = input.nextLine();
if ((row < finalHeight - 1 || col < finalWidth) && charCount < line.length()) {
maze[row][col] = line.charAt(charCount);
charCount += 1;
System.out.print(maze[row][col]);
But this prints out +S+ + which is not right. I am a brand new beginner programmer and having a hard time with this, thanks for any help you can offer.
I fixed it!! this is what I did:
Scanner input = new Scanner(new File("maze0.txt"));
char maze[][] = new char[5][7];
input.nextLine();
for (int row = 0; row < 5; row++) {
String fileLine = input.nextLine();
for (int col = 0; col < 7; col++) {
char nextChar = fileLine.charAt(col);
maze[row][col] = nextChar;
System.out.print(maze[row][col]);
Actually, while the screen might display +S+ +, you only have one value in your array - at maze[0][0] (a value of '+'). Your while loop reads the entire file before the for loops ever increment.For each line it reads, it sets maze[row][column] = line.charAt(charCount); -- but row and column never get incremented because, well, there's another line to read. So it reads another line and overwrites maze[0][0] to be the line.charAt(1) (because you incremented charCount). This character is the space. Then it loops back through because there's another line to read, and puts the 3rd character at maze[0][0]. So on and so forth. When it's read the entire file, then it steps through the for loops, but while (input.hasNextLine()) doesn't execute because it's already read the entire file.
Here is a simple and efficient way to do it.
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("maze0.txt"));
char maze[][] = new char[5][7];
for (int i = 0; i < maze.length; i++) {
//Get each line and convert to character array.
maze[i] = input.nextLine().toCharArray();
}
}
You can read each line from the file and convert it to char array.
public static void main(String[] args) throws IOException {
Scanner scan = new Scanner(new File("maze0.txt"));
String b;
char maze[][] = new char[5][7];
for (int row = 0; row < 5; row++) {
while ( scan.hasNextLine() ){
b = scan.nextLine();
maze[row] = b.toCharArray();
System.out.println(maze[row]);
}
}
scan.close();
}
you just need two loops why are you running 3 loops?
Scanner sc = new Scanner(new File("maze.txt"));
String line = null;
for(int i = 0; i< 5;i++)
{
line = sc.readLine()
for(int j = 0; j < 7; j++)
{
maze[i][j] = line.charAt(j);
}
}
This snippet should read the file and store it in a matrix.
Since you are reading the line in the inner loop, you are printing the diagonal.
Convert the line to character array using .toCharArray() That will give you an array of all the characters. Then just feed them into your array.
it'd look something like..
// everytime we come to a new row, read a line from the file, convert it into letters then proceed on feeding them into columns.
for (int row = 0; row < finalHeight; row++)
{
String line = input.nextLine();
Char[] chars = line.toCharArray();
if(!input.hasNextLine())
break; // if there is no more lines to read, break the loop.
for (int col = 0, i = 0; (col < finalWidth && i < chars.length); col++,i++)
{
maze[row][col] = chars[i];
System.out.print(maze[row][col]);
}
}
import java.io.*;
import java.util.*;
public class B
{
public static void main(String...aaadf)throws FileNotFoundException
{
Scanner sc = new Scanner(new File("D://maze.txt"));
char maze[][] = new char[5][7];
String line = null;
for(int i = 0; i< 5;i++)
{
line = sc.nextLine();
for(int j = 0; j < 7; j++)
{
maze[i][j] = line.charAt(j);
}
}
for(int i = 0; i< 5;i++)
{
for(int j = 0; j < 7; j++)
{
System.out.print(maze[i][j]);
}
System.out.println();
}
}
}
I have an assignment that I have to create a randomly sized 3D array, write it into a a binary file, then read the binary file back into the program and create another 3D array that's the same as the first. I'm having problems reading back into the program, after hours I can only get the first int, or the last, from the prior array. I haven't gotten into passing the first 2D's yet so I just allocated some space to make the array work, but once I get this that should come quickly. The readData() method is the one giving me problems. Thanks in advance.
import java.io.*;
import java.util.*;
public class homework1 {
public homework1() {
}
// Allocates space for the 3-dimension array as specified and for each
// array element, assigns a random number, and return the array
public static int[][][] createData() {
int[][][] data;
//Random variables for array dimensions
Random rand = new Random();
int x = rand.nextInt(5) + 1;
rand = new Random();
int y = rand.nextInt(5) + 1;
rand = new Random();
int z = rand.nextInt(5) + 1;
data = new int[x][y][z];
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
for (int k = 0; k < z; k++) {
rand = new Random();
int r = rand.nextInt(5) + 1;
data[i][j][k] = r;
}
}
}
return data;
}
//Writes the 3-dimension array to file.
public static int[][][] writeData(int[][][] array, String fileName)
throws IOException {
try {
FileOutputStream out = new FileOutputStream(fileName);
DataOutputStream outs = new DataOutputStream(out);
for (int i = 0; i < array.length; i++) {
//outs.writeInt(array[i].length); (maybe?)
for (int j = 0; j < array[i].length; j++) {
//outs.writeInt(array[i][j].length); (maybe?)
for (int k = 0; k < array[i][j].length; k++) {
outs.writeInt(array[i][j][k]);
}
}
}
outs.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return array;
}
public static int[][][] readData(String fileName)
throws FileNotFoundException, IOException {
int[][][] array = new int[3][3][5];
try {
FileInputStream in = new FileInputStream(fileName);
DataInputStream ins = new DataInputStream(in);
int readFrom = ins.readInt(); //read 4 binary byes and
System.out.println("From file");
while (in.read() != -1) {
// poop = ins.readInt();
System.out.println(readFrom);
for (int i = 0; i < array.length; i++) {
//outs.writeInt(array[i].length); (maybe?)
for (int j = 0; j < array[i].length; j++) {
//outs.writeInt(array[i][j].length); (maybe?)
for (int k = 0; k < array[i][j].length; k++) {
array[i][j][k] = readFrom;
}
}
}
System.out.flush();
readFrom=ins.readInt();
}
//save them in an integer
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (EOFException ex){
ex.printStackTrace();
}
System.out.println("Blank array that needs to be filled");
return array;
}
// Displays the array.
public static void printData(int[][][] array) {
for (int i = 0; i < array.length; i++) {
System.out.println("Frame " + i + ":");
for (int j = 0; j < array[i].length; j++) {
for (int k = 0; k < array[i][j].length; k++) {
System.out.print("\t" + array[i][j][k] + " ");
}
System.out.print("\n");
}
}
}
public static void main(String args[]) throws IOException {
// throws FileNotFoundException, IOException {
int data[][][];
data = createData();
printData(data);
writeData(data, "data.out");
data = readData("data.out");
printData(data);
}
}
As you have written it, you don't read from the file each time you loop in the innermost loop — and not either in the outer loops. So you read only once.
The ins.readInt() call should be in the innermost loop, because you need to read each table cell.
I believe you can attain this using Serialization.
Let's think. The readData() method positively MUST obtain information about the array size from somewhere, right? writeData() then MUST store it.
and, how many times do you call readInt() in the readData()?