Well I have been stumped as to the best way to do this, I have written the code to read in lines of code from txt files as List. I can then print specific parts or convert this to an array of objects. But, ultimately I would like to have just a 2d int array you can see often in C/C++. I am very green when it comes to java, having only started earlier this week. I have like it up until this point of making dynamic 2d arrays at run time. Can any of you suggest a good way to get to a 2d int array from where i am currently stuck. I was just about to convert it to a char array using 'toChar', then to take the (value#index-48) and store it in its corresponding spot, but that seems pretty ghetto to me.
====updated==========================
eh, thanks for all the replies, but I just figured out how to do it using doubles, so for anyone else, here you go. I would still rather have int, since I have already built my other matrixops classes using this type, but Double shouldn't be an issue i guess.
package uaa.cse215;
import java.io.*;
import java.util.*;
public class ReadMatrix {
private Double[][] A;
private Double[][] B;
private int count;
public int filedir(String matrix) throws Exception{
Double[][] Temp;
String[] arr;
BufferedReader rd = new BufferedReader(new FileReader(matrix));
String s;
List<String> textFile = new ArrayList<String>();
while ((s=rd.readLine())!=null) {
textFile.add(s);
}
String splitarray[] = textFile.get(0).split(" ");//run once to grab # cols
int rows = textFile.size();//number of rows
int cols = splitarray.length;//number of cols
Temp = new Double[rows][cols]; // now can initiate array
for (int i=0; i<rows; i++) {
s = textFile.get(i);
arr = s.split(" ");
for (int j=0; j<cols; j++) {
Temp[i][j] = Double.parseDouble(arr[j]);
}
}
count++;
if (count == 1){
A = Temp;
}
else
B = Temp;
rd.close();
return(1);
}
}
Please note that Java has the char data type which is a 16bit unsigned integer holding a UTF-16 code point. int is in Java always a signed 32 bit integer. So if you want a C like Arrays of chars representing the content of a String, you should use a char[][]
To convert the content of your List<String> into a 2d array you can use the following code:
char[][] twoDarray = new char[textFile.size()];
for(int i = 0; i < textFile.size(); i+)
{
twoDarray[i] = textFile.get(i).toCharArray();
}
The array twoDarray then contains all Strings each as a char array.
This line won't compile
splitarray[j] = textFile.get(i).split(" ");
as splitarray[j] is of type String and split returns an array of Strings
Do the following instead:
for(int row=0;row<textFile.size();row++){
String[] splitarray = textFile.get(row).split(" ");
for(int col=0;col<splitarray.length;col++){
tmp[row][col] = Integer.parse(splitarray[col]);
}
}
if the input matrix dimentions are dynamic or jagged you can use
List<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
to read numbers and than copy it to raw 2d array if you want.
java.util.Scanner has many handy methods for reading "typed" data from input
Here's an example reading file to 2D array
public static int[][] read2DArray(String fileName) throws FileNotFoundException {
Scanner sc = null;
List<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
int columnCount = 0;
int[][] arr = null;
try {
sc = new Scanner(new File(fileName));
while (sc.hasNextLine()) {
// Read line
String line = sc.nextLine();
// Split it
String[] nums = line.split(" ");
if (nums.length > columnCount) {
columnCount = nums.length;
}
// Convert to integers and add to list
list.add(new ArrayList<Integer>());
for (String n : nums) {
list.get(list.size() - 1).add(new Integer(n));
}
}
// Convert list to array
int rowCount = list.size();
arr = new int[rowCount][columnCount];
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < list.get(i).size(); j++) {
arr[i][j] = list.get(i).get(j);
}
}
} finally {
if (sc != null) {
sc.close();
}
}
return arr;
}
Assuming your data file contains ascii-represented numbers that you want parsed into integers:
11 -9 13
12 55 102
1 1 1024
Then you can use the Integer(String s) constructor to parse your string objects.
Also, I suggest splitting each row only once. It won't matter much for small arrays, but the larger your inputs get, the more you'll needlessly recompute the splits.
An (untested) re-writing:
int tmp[][] = new int [rows][cols];
for(int i=0;i<rows;i++){
splitarray = textFile.get(i).split(" ");
for(int j=0;j<cols;j++){
tmp[i][j] = Integer(splitarray[j]);
}
}
Related
I need to execute by command line a code that will provide a multidimensional array with elements with not necessarily equal lengths.
The execution string is bellow:
start /wait java -jar testMSMWithIndex.jar Foursquare_weather_day_root-type_type 0,1,2-4
I'm considering to pass the parameter 0,1,2-4 and then convert it in a multidimensional array with elements of different lengths in this case, i.e. {{0}, {1}, {2, 4}}.
Note that {{0, null}, {1, null}, {2, 4}} does not work to my problem.
Do you guys know how to develop a method or even get directly as an array from args?
I really appreciate any help you can provide.
It's doubtful that anything already exists to do this for you, so you'll have to parse the string for yourself. Something like this would do it:
public static int[][] parseRaggedArrayFromString(String s)
throws NumberFormatException {
String[] ss = s.split(",");
int[][] result = new int[ss.length][];
for (int i = 0; i < ss.length; ++i) {
if (!ss[i].contains("-")) {
result[i] = new int[1];
result[i][0] = Integer.parseInt(ss[i]);
} else {
String[] range = ss[i].split("-", 2);
int lo = Integer.parseInt(range[0]);
int hi = Integer.parseInt(range[1]);
int size = hi - lo + 1;
result[i] = new int[size > 0 ? size : 1];
int j = 0;
do {
result[i][j] = lo;
++lo;
++j;
} while (lo <= hi);
}
}
return result;
}
It's basically a split on , and -. From there is just handling the data. Comments in the code.
/**
* #author sedj601
*/
public class Main {
public static void main(String[] args) {
String input = "0,1,2-3";
String[] firstArray = input.split(",");//Split on ,.
String[][] outputArray = new String[firstArray.length][];//The array that will be holding the output
//Used to process the firstArray
for (int i = 0; i < firstArray.length; i++) {
if (firstArray[i].length() > 1) {//If the lenght is greater than one. split on -.
String[] secondArray = firstArray[i].split("-");
//Subtract the two numbers and add one to get the lenght of the array that will hold these values
int arrayLength = Integer.parseInt(secondArray[1]) - Integer.parseInt(secondArray[0]) + 1;
String[] tempArray = new String[arrayLength];
int increment = 0;//Keeps up with the tempArray index.
//loop from the first number to the last number inclusively.
for (int t = Integer.parseInt(secondArray[0]); t <= Integer.parseInt(secondArray[1]); t++) {
tempArray[increment++] = Integer.toString(t);//Add the data to the array.
}
outputArray[i] = tempArray;//Add the array to the output array.
} else {//If the lenght is 1, creat an array and add the current data.
String[] tempArray = new String[1];
tempArray[0] = firstArray[i];
outputArray[i] = tempArray;
}
}
//Print the output.
for (String[] x : outputArray) {
for (String y : x) {
System.out.print(y + " ");
}
System.out.println();
}
}
}
Output:
--- exec-maven-plugin:1.5.0:exec (default-cli) # JavaTestingGround ---
0
1
2 3
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 1.194 s
Finished at: 2021-01-08T00:08:15-06:00
------------------------------------------------------------------------
I really think that's possible when you create an array of type Object .(not a good idea) Since multi-D arrays can only hold arrays of same length (int[][]). Then you create and retrieve values from array by casting...
I am trying here to be creative and adopt to your requirements..
public class x {
public static void main(String[] args) {
Object[] arguments = new Object[args.length];
// Then make a loop to capture arguments in array..
// or add manually
arguments[0] = new String[]{args[0]};
arguments[1] = new String[]{args[1],args[2]};
//Then retrieve info from object later by casting
System.out.println(java.util.Arrays.toString((String[]) arguments[1]));
}
}
...
Although, please consider using a collection...
While I waited for the answer, I found a way to solve the problem.
The relevant information here is that we do not need to set the second array dimension in its instantiation.
The code is below:
// INPUT string = "2-3,1,4-5"
private static String[][] featuresConversion(String string) {
String[] firstLevel = string.split(","); // 1st lvl separator
String[][] features = new String[firstLevel.length][]; // Sets 1st lvl length only
int i = 0;
for (String element : firstLevel) {
features[i++] = element.split("-");
}
return features;
}
I want to thank you all. All suggested solutions also work fine!
I'm a beginner in java and I am trying to fill a 2d character array from an input file. To do this I constructed a method which takes in a 2d character array as a parameter variable, then reads the file and stores it as a character array. So far I have done everything except fill the array, as when I run the code the program throws a NoSuchElement exception. If anyone could help me with this I would greatly appreciate it.
public static char [][] MakeWordArray (char [][] givenArray)
{
try
{
File wordFile= new File ("words.txt");
Scanner in= new Scanner (wordFile);
int rows =0;
int col=0;
while (in.hasNextLine())
{
rows = rows + 1;
col = col + 1;
in.next();
}
char [][] words = new char [rows][col];
File wordFile2= new File ("words.txt");
Scanner in2= new Scanner(wordFile2);
for ( int i = 0; i < rows; i++)
{
for (int j = 0; j < col; j++)
{
String wordly = in2.nextLine();
words [i][j] = wordly.charAt(i);
}
}
return words;
}
catch (FileNotFoundException e)
{
System.out.println("File Does Not Exist");
}
return null;
}
I think your counting methods have some problems.
If you want to count how many lines your .txt have:
int counter = 0;
while (in.hasNextLine())
{
counter++;
in.nextLine();
}
If you want to count how many char your .txt have:
int counterWithoutSpace = 0, counterWithSpace = 0;
while (in.hasNextLine())
{
String line = in.nextLine();
Scanner inLine = new Scanner(line);
while (inLine.hasNext())
{
String nextWord = inLine.next();
counterWithoutSpace += nextWord.length();
counterWithSpace += nextWord.length() + 1;
}
counterWithSpace--;
}
If you want to count how many char you have on each line, I recommend ArrayList. Because the size of your array is dynamic.
Note that you can also you can use the char counter logic above with List too.See as follows:
List<Integer> arr = new ArrayList<Integer>();
while (in.hasNextLine())
{
arr.add(in.nextLine().length());
}
And if you realy needs the static array, you can use:
Integer[] intArr = arr.toArray(new Integer[0]);
You can transform its entire function as below to get a list of every Character of the .txt:
List<Character> arr = new ArrayList<Character>();
while (in.hasNextLine())
{
String line = in.nextLine();
for (char c : line.toCharArray())
{
arr.add(c);
}
}
Try using a do while loop instead of the while
do
{
rows=rows+1;
col=lol+1;
in.next();
}
while(in.hasNext());
There are multiple questions here.
1) Why did you provide a char[][] parameter when you are not even using it?
2) Why are you using two files when all you need to do is read from a file and convert it in 2d Array?
3) The method name should follow camel casing convention.
From what i understood from your question, This is a code i've tried.
NOTE- because the requirement is of an Array and not dynamic datatypes like List ArrayList etc., the data entered into char array might be lost
Saying that here is what works.
public class StackOverflow{
public static char [][] makeWordArray ()
{
try{
File f = new File("C:\\docs\\mytextfile.txt");
Scanner scan = new Scanner(f);
int row = 0, col = 0;
String readData = "";
while(scan.hasNextLine()){
readData += scan.nextLine();
row++;
}
double range = (readData.length()/row);
col = (int)Math.ceil(range);
char[][] arr = new char[row][col];
int count = 0;
for (int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
arr[i][j] = readData.charAt(count++);
System.out.println("Pos: ["+ i +"][" + j + "]" + arr[i][j]);
}
}
return arr;
}
catch(FileNotFoundException fe){
System.err.println(fe.getMessage());
return null;
}
}
public static void main(String[] arg){
char[][] myarr = StackOverflow.makeWordArray();
//print your array
}
}
Say I am using this code to convert a String (containing numbers) to an array of characters, which I want to convert to an array of numbers (int).
(Then I want to do this for another string of numbers, and add the two int arrays to give another int array of their addition.)
What should I do?
import java.util.Scanner;
public class stringHundredDigitArray {
/**
* #param args
*/
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Enter the number: ");
String num1 = in.nextLine();
char[] num1CharArray = num1.toCharArray();
//for (int i = 0; i < num1CharArray.length; i++){
//System.out.print(" "+num1CharArray[i]);
//}
int[] num1intarray = new int[num1CharArray.length];
for (int i = 0; i < num1CharArray.length; i++){
num1intarray[i] = num1CharArray[i];
}
for (int i = 0; i < num1intarray.length; i++){ //this code prints presumably the ascii values of the number characters, not the numbers themselves. This is the problem.
System.out.print(" "+num1intarray[i]);
}
}
}
I really have to split the string, to preferably an array of additionable data types.
try Character.getNumericValue(char); this:
for (int i = 0; i < num1CharArray.length; i++){
num1intarray[i] = Character.getNumericValue(num1CharArray[i]);
}
Try This :
int[] num1intarray = new int[num1CharArray.length];
for (int i = 0; i < num1CharArray.length; i++)
{
num1intarray[i]=Integer.parseInt(""+num1CharArray[i]);
System.out.print(num1intarray[i]);
}
Short and simple solution!
int[] result = new int[charArray.length];
Arrays.setAll(result, i -> Character.getNumericValue(charArray[i]));
I need read data from csv file and much more convinience for me is put there to 2D array (to my mind it's easiest way to work with this "schedule" data).
Each file line contained information in following format:
Instructor, Course, Group, Student, Result
as follows example:
Paul Schwartz,Introduction to Computer Architecture,I1,Ben Dunkin,88
Muhamed Olji,Object Oriented Programming,I4,Mike Brown,73
But my code needs some simplify. But I don't know how to make it easier and ask of You.
Code:
private String[][] fileContent(String pathToCSVFile) {
final int ROWS = 100;
final int COLUMNS = 5;
String fileData[][] = new String[ROWS][COLUMNS];
Scanner scanner = new Scanner(pathToCSVFile);
boolean done = false;
int i, j;
while (!done) {
for (i = 0; i >= 0; i++) {
for (j = 0; j >= 0; j++) {
String str[] = scanner.nextLine().split(",");
for (int element = 0; element < str.length; element++) {
fileData[i][element] = str[element];
if (i >= ROWS) {
Arrays.copyOf(fileData, fileData.length * 2);
}
}
}
}
if (!scanner.hasNextLine()) done = true;
}
return fileData;
}
How to refactor this snippet of code for better simplicity?
Does exist any better way for partially filled array (than Arrays.copyOf(fileData, fileData.length * 2))?
Using openCSV, you can get a list containing all the lines and convert it to an array (or just keep the list):
try (CSVReader reader = new CSVReader(new BufferedReader(
new FileReader(pathToCSVFile)));) {
List<String[]> lines = reader.readAll();
return lines.toArray(new String[lines.size()][]);
}
(using Java 7 try-with-resources syntax)
First of all, be careful with those for loops. They are "almost" undefined loops, because they start with i,j=0, and loop while >=0 (always, until they overflow into a negative number).
And why do you need them anyway? I think with you while and the for(element) you are done, right?
Something like that (I didn't tried, is just to explain the concept)
private String[][] fileContent(String pathToCSVFile) {
final int ROWS = 100;
final int COLUMNS = 5;
String fileData[][] = new String[ROWS][COLUMNS];
Scanner scanner = new Scanner(pathToCSVFile);
boolean done = false;
int i=0;
while (!done) {
String str[] = scanner.nextLine().split(",");
for (int element = 0; element < str.length; element++) {
fileData[i][element] = str[element];
if (i >= ROWS) {
Arrays.copyOf(fileData, fileData.length * 2);
}
}
if (!scanner.hasNextLine())
done = true;
else
i++;
}
return fileData;
}
By the way, why don't you use objects, like an ArrayList? It would make your life easier, so you don't have to worry about memory handling. You just add new objects.
Something like an ArrayList <ArrayList <String>>
I have to read a text file into a 2d Array.
The only problem I am having, is the width of the array varies, with a maximum size of 9 columns.
I don't know how many rows there will be.
Some lines will have 6 columns for example, and some will have 9.
here is a small section of my CSV file:
1908,Souths,Easts,Souths,Cumberland,Y,14,12,4000
1909,Souths,Balmain,Souths,Wests,N
1910,Newtown,Souths,Newtown,Wests,Y,4,4,14000
1911,Easts,Glebe,Glebe,Balmain,Y,11,8,20000
1912,Easts,Glebe,Easts,Wests,N
1913,Easts,Newtown,Easts,Wests,N
and here is my code so far
import java.io.*;
import java.util.*;
public class ass2 {
public static void main(String[] args) throws IOException {
readData();
}
public static void readData() throws IOException{
BufferedReader dataBR = new BufferedReader(new FileReader(new File("nrldata.txt")));
String line = "";
ArrayList<String[]> dataArr = new ArrayList<String[]>(); //An ArrayList is used because I don't know how many records are in the file.
while ((line = dataBR.readLine()) != null) { // Read a single line from the file until there are no more lines to read
String[] club = new String[9]; // Each club has 3 fields, so we need room for the 3 tokens.
for (int i = 0; i < 9; i++) { // For each token in the line that we've read:
String[] value = line.split(",", 9);
club[i] = value[i]; // Place the token into the 'i'th "column"
}
dataArr.add(club); // Add the "club" info to the list of clubs.
}
for (int i = 0; i < dataArr.size(); i++) {
for (int x = 0; x < dataArr.get(i).length; x++) {
System.out.printf("dataArr[%d][%d]: ", i, x);
System.out.println(dataArr.get(i)[x]);
}
}
}
The error I get is:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
at ass2.readData(ass2.java:23)
at ass2.main(ass2.java:7)
Can someone please help :'(
Thank you!
You can use OpenCSV for read the CSV file.
// Read all
CSVReader csvReader = new CSVReader(new FileReader(new File("nrldata.txt")));
List<String[]> list = csvReader.readAll();
// Convert to 2D array
String[][] dataArr = new String[list.size()][];
dataArr = list.toArray(dataArr);
The problem is with your inner loop. You are trying to access 9 elements of value regardless of how many values there are on the line. First, you should move the assignment to value to be before the inner loop. Then, you need to limit the loop iterations to the minimum of 9 and the length of value:
String[] value = line.split(",", 9);
int n = Math.min(value.length, data.length);
for (int i = 0; i < n; i++) { // For each token in the line that we've read:
data[i] = value[i]; // Place the token into the 'i'th "column"
}
Note that the trailing elements of data will be null.
You get the error, because you try to access a 7th token (index 6) on a line that contains only 6. Replace that:
for (int i = 0; i < 9; i++) { // For each token in the line that we've read:
String[] value = line.split(",", 9);
data[i] = value[i]; // Place the token into the 'i'th "column"
}
with this:
String[] value = line.spkit(",", 9); // Split the line into max. 9 tokens
for (int i = 0; i < value.length; i++) {
data[i] = value[i]; // Add each token to data[]
}
You could, in fact, replace the whole while-loop body with this one-liner:
dataArr.add(Arrays.copyOf(line.split(",", 9), 9));
See, also, this short demo.
Instead of array, you can use ArrayList of List. As List is dynamically growable so you do't need to think of it size either.
List<List<String>> dataArr = new ArrayList<List<String>>();
and
while ((line = dataBR.readLine()) != null){
for (int i = 0; i < 9; i++)
dataArr.add(Arrays.asList(line.split(",", 9)));
}