Edit: I've solved this. I was not properly reading in the second number at the top of the file so I was getting a square array. I solved it by skipping the first number with a scanner.next(). I'll post the corrected code below. Thanks for everyone's help.
I'm trying to learn file i/o and the project has you read a file you create. The file begins with two numbers that are the number of students in a class and the number of projects to be graded and then after that there is a large matrix beginning with names and then scores to be averaged. Something like this:
2 3
John 44.4 55 66.1
Lisa 33 44 55
The completely corrected method (though still needs fine-tuning for exception handling):
public static double[][] getArrays(String fileName, int num1, int num2) {
double[][] twoDArray = new double[num1][num2];
String[] names = new String[num1];
try {
Scanner fileReader = new Scanner(new File(fileName)); //Create a scanner
fileReader.nextLine();
do {
for (int i = 0; i < num1; i++) {
names[i] = fileReader.next();
System.out.println(names[i]);
for (int j = 0; j < twoDArray[0].length; j++) {
twoDArray[i][j] = fileReader.nextDouble();
}
fileReader.nextLine();
}
} while (fileReader.hasNext());
} catch (FileNotFoundException | NoSuchElementException ex) { //Catch any exceptions
System.out.println("Exception caught");
}
return twoDArray;
}// end of get2DArray method
Your question is titled,
read a 2d array from file-Java
But I think that the last thing you want to do here is to create a 2D array, and your code is completely ignoring the student's name.
Instead you should create a Student class, one that has two fields, a String field to hold the student's name, and an ArrayList<Double> or double[], your choice, to hold the grades.
Then put each Student object, which you create on reading in a line of data from the file, into either an ArrayList<Student> or a Student[] array, again your choice.
If you go with arrays (which I'm guessing is your requirement for your class), then pseudo code could be:
create File Scanner object, fileScanner
read line,
create line Scanner with line,
get both ints studentCount and gradeCount, and store in variables.
dispose of line Scanner
Create Student array
??? possibly read an empty line (if your file representation is accurate).
for index goes from 0 to < student count
read line with File Scanner
create line Scanner with line
next token goes into a name String
create 1-D double array
for other index goes from 0 to < gradeCount
use line scanner to get doubles and put into one double array
end for loop
dispose of line scanner
create Student object with name and double array,
place Student object into Student array
end for loop
dispose of file scanner
I believe from looking at your code that you are never actually putting values into the array and due to the fact that when you a print an initialized array that has never had any values associated it will automatically print 0.0
What is causing you not to put any values in the array is your while(fileReader.hasNextDouble()) this is searching for a double next but a string is located there so your while loop isn't happening. (For future reference in debugging adding a simple System.out.println("Hit"); inside your while loop will tell you if you are getting there). There are a couple of changes based on the structure of your txt file that I would do and i have put the code below.
while (fileReader.hasNext()) {
for (int i = 0; i < num1FromFile; i++) {
fileReader.next();
for (int j = 0; j < num2FromFile; j++) {
twoDArray[i][j] = fileReader.nextDouble();
}
}
}
let me know if this works for you!
public static double[][] getArrays(String fileName) throws Exception {
Scanner scanFile = new Scanner(new File(fileName));
int numNames = scanFile.nextInt();
int numScores = scanFile.nextInt();
double[][] scores = new double[numNames][numScores];
String[] names = new String[numNames];
for(int i = 0; i < numNames; i++) {
names[i] = scanFile.next();
for(int j = 0; j < numScores; j++) {
scores[i][j] = scanFile.nextDouble();
}
}
scanFile.close();
return scores;
}
Try to understand the logic before you use it. There might be typo errors in the code above as I am directly typing it in here. The names are read into an array but not used. I believe you are not interested in names, as your method is only returning double[][]. Also I am assuming that the file is perfect, without any comments etc.
Related
I have a program that has two String arrays defined and initialized. I now want to accept inputs from the user to fill out the indexes of each array. I want the user to input index[i] for array 1 and then index[i] for array 2 and so on until both arrays are filled.
I attempted to use a nested loop to do this, but I was getting an out of bounds error.
Unfortunately, Google was not helpful as I kept finding the .fill() method, which I cannot currently use in my course.
The code below contains elements for the rest of the program which I haven't written. The below code is meant to complete the first part of the program and that is to get the list of words into the first two arrays and then output them to make sure they were filled correctly.
EDIT: Even though I got my answer, I tried updating the question for clarity. It looks like I was vastly overthinking the problem. It was my first time working with more than one array.
import java.util.Scanner;
public class LabProgram {
public static int findWordInWordList(String[] wordList, String wordToFind, int numInList) {
return -1; //Will replace words in a sentence, to be used coded and used later.
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] ogWords; //words to replace.
String[] newWords; //words to replace with.
String[] sentence; //the sentence that will be searched and have words replaced.
int pairSize; //size of the first two arrays.
pairSize = sc.nextInt();
ogWords = new String[pairSize];
newWords = new String[pairSize];
for (int i = 0; i < ogWords.length; i++) {
ogWords[i] = sc.next();
for (int j = 0; j < newWords.length; j++) {
newWords[j] = sc.next();
}
}
for (int i = 0; i < pairSize - 1; i++) { //Testing arrays
System.out.println(ogWords[i] + " " + newWords[i]);
}
}
}
The final for loop is just to test that the arrays were filled correctly, which isn't working right now :p.
Unless I've misunderstood your question, I think you're after:
for (int i = 0; i < pairSize; i++) {
ogWords[i] = sc.next();
newWords[i] = sc.next();
}
I'm trying to create a program that takes user input and sorts it alphabetically as it comes in using compareTo String operations (not array.sort) and prints the final sorted array at the end. I've got most of the body of this problem down but am lost once I get to the sort function. Does anyone have any ideas on how I might be able to finish out the SortInsert method?
import java.util.*;
public class SortAsInserted {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int array_size = GetArraySize();
String[] myArray = new String[array_size];
for (int i = 0; i < array_size; i++){
String nextString = GetNextString();
String[] sortedArray = SortInsert(nextString, myArray);
}
PrintArray(sortedArray);
}
input.close();
}
}
public static String[] SortInsert(String nextString, String[] myArray){
for(int i = 0; i < myArray.length;)
if (nextString.compareToIgnoreCase(myArray[i]) > 0) {
i++;
//if current text is less(alphabetically) than position in Array
}else if (nextString.compareToIgnoreCase(myArray[i]) < 0){
}
}
public static int GetArraySize(){
Scanner input = new Scanner(System.in);
System.out.print("How many items are you entering?: ");
int items_in_array = input.nextInt();
return items_in_array;
}
public static void PrintArray(String[] x) {
for (int i = 0; i < x.length; i++){
System.out.print(x[i]);
}
}
public static String GetNextString(){
Scanner input = new Scanner(System.in);
System.out.println("Enter the next string: ");
String next_string = input.nextLine();
return next_string;
}
}
There are a number of problems with this code. First I'll answer your immediate question, then enumerate some of the other problems.
The SortInsert method takes a String[] that will have been initialized with null values, so you will need to take that into account. The for loop would look something like this. (I'm using comments instead of writing the actual code since I'm not doing the project)
for (int i=0; i<myArray.length; ++i) {
if (myArray[i] == null) {
// we found a blank spot. use it to hold nextString.
break;
} else if (nexString.compareToIgnoreCase(myArray[i]) < 0) {
// nextString should be in spot i, so make room for it
// by shuffling along whatever is in the array at "i" and later
// by one place, then put nextString into position "i"
break;
}
// otherwise we'll just move to the next position to check
}
Now for the other issues.
You have a Scanner object in main that is never used. There's no point in having it and closing it at the end if your other methods make their own.
myArray will always be the sorted array so there's no point in making a local variable called sortedArray and return it from SortInsert. Note that your attempt to print sortedArray would fail anyway because that local variable is only in scope within the for loop.
When printing it should be myArray being passed to PrintArray.
If you're going to sort as you go, the TreeMap data structure is what you should be using, not an array. However, if you want to sort as you go with an array, you need to add some lines into your else if clause in SortInsert (should be sortInsert, BTW). (Another question: why is it else if rather than just else?)
The lines should create a new array of size one greater than the existing array, copy the first i-1 elements of the old array to the new array, put the new element in position i, then copy the remaining elements of the old array into positions one greater in the new array.
Once you find the position you wish to insert at, you have to shift all of the following elements down by one. Something like the following:
String temp = array[position];
for (int j = position+1; j < array_size-1; j++) {
String temp2 = array[j];
array[j] = temp;
temp = temp2;
}
array[array_size-1] = temp;
I'm reading from a file and copying that into an array. My file has five lines of text, a sentence each. I get my output "Array size is 5" but nothing after that. If I do add a print line of the array, it gives me 5 nulls...
Can someone help explain what I did wrong? Thanks!
public static int buildArray() throws Exception
{
System.out.println("BuildArray is starting ");
java.io.File textFile; // declares a variable of type File
textFile = new java.io.File ("textFile.txt"); //reserves the memory
Scanner input = null;
try
{
input = new Scanner(textFile);
}
catch (Exception ex)
{
System.out.println("Exception in method");
System.exit(0);
}
int arraySize = 0;
while(input.hasNextLine())
{
arraySize = arraySize + 1;
if (input.nextLine() == null)
break;
}
System.out.println("Array size is " + arraySize);
// Move the lines into the array
String[] linesInRAM = new String[arraySize];// reserve the memory
int count = 0;
if (input.hasNextLine())
{
while(count < arraySize)
{
System.out.println("test");
linesInRAM[count] = input.nextLine();
System.out.println(linesInRAM[count]);
count = count + 1;
}
}
In this code
int count = 0;
if (input.hasNextLine())
The above hasNextLine will always be false as you have already read all the way through the file.
Either reset the scanner to the beginning of the file, or use a dynamic list e.g. ArrayList to add the elements to.
My Java is a bit rusty, but the basic gist of my answer is that you should create a new Scanner object so that it reads from the beginning of the file again. This is the easiest way to "reset" to the beginning.
Your code is currently not working because when you call input.nextLine() you're actually incrementing the scanner, and thus at the end of that first while() loop input is sitting at the end of the file, so when you call input.nextLine() again it returns null.
Scanner newScanner = new Scanner(textFile);
Then in the bottom of your code, your loop should look like this instead:
if (newScanner.hasNextLine())
{
while(count < arraySize)
{
System.out.println("test");
linesInRAM[count] = newScanner.nextLine();
System.out.println(linesInRAM[count]);
count = count + 1;
}
}
I Really would appreciate it if someone can help me with this. I am trying to do external sorting and I am stuck on the part of merging. I get how I should merge it just not sure what function to use.
Right now I am trying to read in the first words of multiple small text files and store them in a string array of the size of the amount of files. So basically I will have a string array of the first word of each file. Then I determine which one is the smallest alphabetically wise and write that to a new file, after that I would read the next word of the file of that smallest word. This word would be placed in the position of the smallest word that got outputted in string array and compare it to the rest of the first word from the other file. This will keep repeating till all words are sorted.
The main problem I am running into is the fact that I was using scanner and after the first run of comparing it cant switch the smallest word with the next word in the file because scanner don't keep a point of what it has read. I know readline do but since my files are all words separated by only a white space I can't use readline. Can someone please guide me to a sufficient reading function that can't help me solve this problem.
for (int i = 0; i<B;i++)
{
try
{
BufferedReader ins = new BufferedReader(new FileReader(Run-"+ i + ".txt"));
Scanner scanner2 = new Scanner(ins);
temp3[i] = scanner2.next();
System.out.println(temp3[i]);
}
catch(IOException e)
{
}
}
for(int i=0;i<N;i++)
{
String smallest = temp3[0];
int smallestfile = 0;
for(j=0;j<B;j++)
{
int comparisonResult = smallest.compareTo(temp3[j]);
if(comparisonResult>0)
{
smallest = temp3[j];
smallestfile = j;
}
}
BufferedReader ins = new BufferedReader(new FileReader("C:/Run-"+ smallestfile + ".txt"));
Scanner scanner2 = new Scanner(ins);
if(scanner2.hasNext())
{
temp3[smallestfile]=scanner2.next();
}
}
}
catch(Exception e)
{
}
If the files are small enough read the entire file to memory, and use String.split() to separate the strings in arrays and do your magic.
If the the files are bigger, keep then open and read each byte until you find and space, then do it for all the files, compare the strings, do your magic and repeat until all the files reach the end.
EDIT :
how to read the files with BufferedReader
how to split the lines with String.split()
String line = readeOneLineFromTheCurrentFile();
String[] words = line.split(" ");
As for temporarily sorting/storing the words, use a PriorityQueue (not an array). Sorry, I'm too busy watching baseball to add more.
I'm not sure, if I understood you right, but a Scanner does keep the position in a file. You need just as many of them as there are files
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class so {
// returns the index of the smallest word
// returns -1 if there are no more words
private static int smallest(String[] words) {
int min = -1;
for (int i = 0; i < words.length; ++i)
if (words[i] != null) {
if (min == -1 || words[i].compareTo(words[min]) < 0)
min = i;
}
return min;
}
public static void main(String[] args) throws FileNotFoundException {
// open all files
Scanner[] files = new Scanner[args.length];
for (int i = 0; i < args.length; ++i) {
File f = new File(args[i]);
files[i] = new Scanner(f);
}
// initialize first words
String[] first = new String[args.length];
for (int i = 0; i < args.length; ++i)
first[i] = files[i].next();
// compare words and read following words from scanners
int min = smallest(first);
while (min >= 0) {
System.out.println(first[min]);
if (files[min].hasNext()) {
first[min] = files[min].next();
} else {
first[min] = null;
files[min].close();
files[min] = null;
}
min = smallest(first);
}
}
}
Tested with
a.txt: a d g j
b.txt: b e h k m
c.txt: c f i
Update:
In your example, you open and close the file inside the outer for loop. When you reopen a file the next time, it starts at the beginning of the file, of course.
To prevent this, you must keep the file open and move the scanner2 variable and its initialization in front of the outer for loop. You also need multiple Scanner variables, i.e. an array, to keep multiple files open simultaneously.
When I say a grid, I mean a multidimensional array. I want this because I am making a 2D game and I want to be able to load levels from data text files. Lets say, for example, I have this 2D array level[3][3]. A simple 3x3 map. And I also have a text file that reads:
1 2 3
4 5 6
7 8 9
In c++, I can simply do:
for (x=0; i<map_width; x++)
{
for (y=0; y<map_height; y++)
{
fscanf(nameoffile, "%d", map[x][y]);
}
}
And that would put all the contents of the text file accordingly into the array.
HOWEVER
I have no idea how to do this in java. Is there any sort of equivalent that will just place the data into the array accordingly? I already know about the scanner class, but I don't know how to use it. I have searched google, to no avail. It doesn't explain much.
Please help! Specifically, I want to know how to scan the file and put whatever int it reads IN THE APPROPRIATE PLACE in the array.
My current code is this, however, it throws a NoSuchElementException:
public void loadMap() {
Scanner sc = null;
try {
sc = new Scanner(inputmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
map[x][y] = sc.nextInt();
}
}
Where inputmap is the file, map[][] is a grid of data for each of the tiles on the map and width and height are pre-specified in a constructor.
Your question is very unhelpful when it comes to how your text files will be actually formatted. For example,
123
456
789
is very different from
1 2 3
4 5 6
7 8 9
and furthermore, you haven't mentioned whether they are always ints, or
1 2 3
4 5 6
a b c
etc. If you gave us a precise description of exactly what goes in these text files we could help you more. The best I can do is show you how to use Scanner to input stuff in general:
The for loop would look similar in Java, but you have to initialize a Scanner object.
Scanner input = new Scanner(myFile); //whatever file is being read
for (x=0; i<map_width; x++)
{
for (y=0; y<map_height; y++)
{
int nextTile = input.nextInt(); //reads the next int
// or
char nextTile = input.nextChar(); //reads the next char
}
}
Beyond that, I would need to know more about what is actually inside these input files.
EDIT:
I copied your for loop directly from your code, but you may want to swap the inner and outer for loops. Shouldn't the width be the inner parameter (reading left to right)?
In Java, it works similar - create a java.util.Scanner object for your file and use it's nextInt method instead of fscanf.
If you don't know the dimensions of the grid
static int[][] readFile(String filename) {
try {
File textfile = new File (GridSearchTest.class.classLoader.getResource(filename).toURI());
Scanner fileScanner = new Scanner(textfile);
int size = Integer.parseInt(fileScanner.next());
String line = fileScanner.nextLine();
int[][] grid = new int [size][size];
int i = 0; int j = 0;
while (fileScanner.hasNextLine()) {
line = fileScanner.nextLine();
System.out.println (line);
Scanner lineScanner = new Scanner(line);
while (lineScanner.hasNext()) {
grid[i][j] = Integer.parseInt(lineScanner.next());
i++;
}
lineScanner.close();
i=0;
j++;
}
fileScanner.close();
return grid;
} catch (IOException e) {
System.out.println("Error reading file: "+ e.getMessage());
System.exit(0);
};
}