I'm trying to read a 2D array into a file. On compiling, it says that readFile, the Scanner variable may be uninitialized (which I know is because the initialization is in the try catch blocks). When I set readFile to null, however, it manages to count the number of lines but skips everything else.
Do I need to close and remake the scanner and file stuff for the actual reading in of the data? Or is there another error that I'm missing somewhere?
Also, I'm aware that the code for the actual reading in of the 2d array isn't done in the code sample below, but I'm trying to make sure it reads in correctly before I do anything else.
//2D table example I'm trying to read in
0 1 1 0
1 0 0 0
1 0 0 1
0 0 1 0
boolean[][] relationTable;
Scanner keyboard = new Scanner(System.in);
String fileName;
File relationFile;
Scanner readFile;
boolean error = false;
System.out.print("Please enter the name of the table file: ");
do{
fileName = keyboard.next();
try
{
relationFile = new File(fileName);
readFile = new Scanner(relationFile);
error = false;
}
catch(FileNotFoundException fnfe)
{
System.out.println("File was not found. Please enter a new file name:");
error = true;
}
}while (error == true);
//finds number of lines correctly
int count = 0;
while (readFile.hasNextLine())
{
count++;
readFile.nextLine(); //notes the error here when not initialized
}
System.out.println(count); //using the example table above it prints out 4
relationTable = new boolean[count][count];
int i = 0, j = 0, temp = 0;
//doesn't appear to do this section at all.
String[] lines= new String[count];
while (readFile.hasNextLine())
{
lines[i] = readFile.nextLine();
System.out.println(lines[i]);
i++;
}
// finds number of lines correctly
int count = 0;
List<String> lines = new ArrayList<String>();// use arrayList instead of arrays if you dont know the number of lines like we have here.
while (readFile.hasNextLine()) {
count++;
lines.add(readFile.nextLine()); // notes the error here when not
// initialized
}
System.out.println(count); // using the example table above it prints
// out 4
relationTable = new boolean[count][count];
int i = 0, j = 0, temp = 0;
your mistake here is that you were looping using readFile.hasNextLine() but the file was already read and readFile.hasNextLine() always returned false
// here is a loop that works even though its not needed, we could have added the print statement in the loop above.
for (int x = 0; x < count; x++) {
System.out.println(lines.get(x));
}
The problem is that you're already gone through all the lines in the file.
while (readFile.hasNextLine())
{
count++;
readFile.nextLine(); //notes the error here when not initialized
}
After this point, your readFile object has not more lines left. So when you reach
String[] lines= new String[count];
while (readFile.hasNextLine())
{
lines[i] = readFile.nextLine();
System.out.println(lines[i]);
i++;
}
There are not lines left. So in order to solve your problem you have to read the file again before the second while.
relationFile = new File(fileName);
readFile = new Scanner(relationFile);
Related
I am struggling to use scanner class to read in a text file while skipping the blank lines.
Any suggestions?
Scanner sc = new Scanner(new BufferedReader(new FileReader("training2.txt")));
trainingData = new double[48][2];
while(sc.hasNextLine()) {
for (int i=0; i<trainingData.length; i++) {
String[] line = sc.nextLine().trim().split(" ");
if(line.length==0)
{
sc.nextLine();
}else{
for (int j=0; j<line.length; j++) {
trainingData[i][j] = Double.parseDouble(line[j]);
}
}
}
}
if(sc.hasNextLine())
{
sc.nextLine();
}
sc.close();
I am currently trying to get it working like this. But it is not working
Scanner sc = new Scanner(new BufferedReader(new FileReader("training.txt")));
trainingData = new double[48][2];
while(sc.hasNextLine()) {
String line = sc.nextLine().trim();
if(line.length()!=0)
{
for (int i=0; i<trainingData.length; i++) {
String[] line2 = sc.nextLine().trim().split(" ");
for (int j=0; j<line2.length; j++) {
trainingData[i][j] = Double.parseDouble(line2[j]);
}
}
}
}
return trainingData;
while(sc.hasNextLine()) {
for (int i=0; i<trainingData.length; i++) {
String[] line = sc.nextLine().trim().split(" ");
You can't just check the scanner once to see if it has data and then use a loop to read the lines of data. You can't assume that you have 48 lines of data just because you define your array to hold 48 lines of data.
You need to go back to the basics and learn how to read data from a file one line at a time and then you process that data.
Here is a simple example to get you started:
import java.util.*;
public class ScannerTest2
{
public static void main(String args[])
throws Exception
{
String data = "1 2\n\n3 4\n\n5 6\n7 8";
// First attempt
System.out.println("Display All Lines");
Scanner s = new Scanner( data );
while (s.hasNextLine())
{
String line = s.nextLine();
System.out.println( line );
}
// Second attempt
System.out.println("Display non blank lines");
s = new Scanner( data );
while (s.hasNextLine())
{
String line = s.nextLine();
if (line.length() != 0)
{
System.out.println( line );
}
}
// Final attempt
String[][] values = new String[5][2];
int row = 0;
System.out.println("Add data to 2D Array");
s = new Scanner( data );
while (s.hasNextLine())
{
String line = s.nextLine();
if (line.length() != 0)
{
String[] digits = line.split(" ");
values[row] = digits;
row++;
}
}
for (int i = 0; i < values.length; i++)
System.out.println( Arrays.asList(values[i]) );
}
}
The example uses a String variable to simulate data from a file.
The first block of code is how you simply read all lines of data from the file. The logic simply:
invokes the hasNextLine() method so see if there is data
invokes the nextLine() method to get the line of data
display the data that was read
repeats steps 1-3 until there is no data.
Then next block of code simply adds an "if condition" so that you only display non-blank data.
Finally the 3rd block of code is closer to what you want. As it reads each line of data, it splits the data into an array and then adds this array to the 2D array.
This is the part of code you will need to change. You will need to convert the String array to an double array before adding it to your 2D array. So change this code first to get it working. Then once this works make the necessary changes to your real application once you understand the concept.
Note in my code how the last row displays [null, null]. This is why it is not a good idea to use arrays because you never know how big the array should be. If you have less that 5 you get the null values. If you have more than 5 you will get an out of bounds exception.
Try adding this to your code:
sc.skip("(\r\n)");
It will ignore blank lines. For More information: Scanner.skip()
I have a text file "names" which contains 10 names, each name on its own line. What I want to do is put these names into an array "anArray". Just to check that I'm doing an alright job, I outputted a line as you can see.
Here's the code I used to try to do that:
public static void main(String[] args) throws FileNotFoundException
{
File file=new File("names.txt");
Scanner my_input= new Scanner(file);
String [] anArray;
anArray = new String[10];
String a = my_input.nextLine();
while(my_input.hasNextLine())
{
for(int i = 0; i<10;i++)
{
while (!(a.equals("\n")))
{
anArray[i] = a;
System.out.println("Element" + i + "of the array is: " + anArray[i]);
}
i++;
a=my_input.next();
}
}
my_input.close();
}
However this code fails, what happens is "Element 0 of the array is: name 1" is outputted an infinite amount of times, "name 1" being the first name in the text file. I don't know what I'm doing wrong here, could anybody enlighten me?
You currently have an infinite loop on your inner while loop, you don't update a so that will loop forever once entered. I think you wanted to check that i is less than 10 and your input still has more lines. You can do that with a singe loop. I would also prefer a try-with-resources over explicitly closing. And you can guard against empty lines with String.isEmpty(). Something like,
File file = new File("names.txt");
try (Scanner my_input = new Scanner(file)) {
String[] anArray = new String[10];
for (int i = 0; i < 10 && my_input.hasNextLine(); i++) {
String line = my_input.nextLine();
if (line.isEmpty()) {
continue;
}
anArray[i] = line;
System.out.printf("Element %d of the array is: %s%n", i, anArray[i]);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
The condition in the innermost while loop never changes, so the contents will repeat indefinitely.
Something to change the value of the phrase
while (!(a.equals("\n")))
must occur in the body of the loop, otherwise it will stay true if it starts out true.
My knowledge with java language is very new. Most of my knowledge are from googling up on how to do things. I've been working on a console program in java that uses a switch statement. The entire program utilizes an String [20][5] array. I've written the code to now be able to add entry, save array to file, load entries from file into the array.
The problems now is edit and removing entries. I am able to return values to null but it'll look like this [[null], [null, null, null, null, null].
I want the value to return to [null, null, null, null, null], [null, null, null, null, null].
The Edit entry some reasons return an java.lang.ArrayIndexOutOfBoundsException:1 .
Could someone point out my error? Also the Array is globally declare.
public static String[][] rem(){
Scanner input = new Scanner(System.in);
int x,y=0;
//for(int i=0;i<array.length;i++){
//if(array[i][0]!=null){
System.out.println(Arrays.deepToString(array));//}
//}
System.out.println("Which entry would you like to remove? "
+ "\n" + "Enter number 0 - 20");
x = input.nextInt();
array[x][y]=null;
return array;}
public static String[][] edit(){
Scanner input = new Scanner(System.in);
String k;
int j;
int g;
// for(int i=0;i<array.length;i++){
//if(array[i][0]!=null){
//System.out.println(Arrays.deepToString(array));}
//}
System.out.println("Which entry would you like to edit? "
+ "\n" + "Enter number 0 - 20");
j = input.nextInt();
System.out.println("What would you like to edit? "
+"\n" + "Enter number 0 - 5");
g = input.nextInt();
System.out.println("You are now editing.");
k = input.next();
array[j][g] = k;
return array;}
Update
I think I figure my issue. The array properly edit values I manually input. It's when I load data into the array that causes problem because when it loads data it loads as String []. I need a code that will load the data as String[][] or as array of arrays.
public static String[][] load()throws FileNotFoundException, IOException{
menu();
copyFile();
String file = ("c:/temp/Address.txt");
Scanner scan = new Scanner(new FileReader(file));
// initialises the scanner to read the file file
//String[][] entries = new String[100][3];
// creates a 2d array with 100 rows and 3 columns.
//int i = 0;
while(scan.hasNextLine()){
array[i][i] = scan.next().split("," , "\t");
i++;
}
//loops through the file and splits on a tab
//for (int row = 0; row < array.length; row++) {
// for (int col = 0; col < array[0].length; col++) {
// if(array[row][col] != null){
// System.out.print(array[row][0] );
// }
// }
// if(array[row][0] != null){
// System.out.print("\n");
//}
// }
//prints the contents of the array that are not "null"
selectMenu();
return array;}
Update 2
I have found the solution to solving the loading data issue. The solution is simple! I'll leave the code here for reference. Though, all of the codes could use some beautifying.
public static String[][] load()throws FileNotFoundException, IOException{
menu();
copyFile();
String file = ("c:/temp/Address.txt");
Scanner scan = new Scanner(new FileReader(file));
FileReader fr = new FileReader("c:/temp/Address.txt");
BufferedReader br = new BufferedReader(fr);
//int j=0;
//int lineNo = 0;
//String line = br.readLine();
//while(line!=null)
//{
//for(int i = 0; i < 5; i++)
//{
//array[lineNo][i] = line.substring(i,4);
//}
// lineNo++;
//line = br.readLine(); // This is what was missing!
//}
//while(scan.hasNextLine()){
//while(scan.hasNext()){
//for(j=0;j<5;j++){
for(int i = 0; i < 20; ++i){
for(int j = 0; j < 5; ++j)
{
if(scan.hasNext())
{
array[i][j] = scan.next();
//i++;
//j++;
}
//i++;
}
}
selectMenu();
return array;}
Update 3
So after figuring out on how to use the delimiter it sorts of give me a weird issue. It adds return at the end of the column. [null, null, null, null, null return]. I used ",|\n" as my delimiter. Is there a better method? Update: Added a .trim(); solve the final issue with load. Now it's perfected in its current job. Though, I'm sure there might be less primitive methods.
public static String[][] load()throws FileNotFoundException, IOException{
copyFile();
//delimiter removes the comma or return to the next line. "\n" new line
Scanner scan = new Scanner(new FileReader(file)).useDelimiter(",|\n");
for(int i = 0; i < 20; ++i){
for(int j = 0; j < 5; ++j){
if(scan.hasNext())
array[i][j] = scan.next().replace(",", "").trim();
}
}
System.out.println("File loaded successfully!!");
scan.close();
return array;}
This is an off by one error, very subtle mistake:
Although you have 20 rows and 5 columns, arrays use a 0 based index(start counting from 0 instead of 1).
Use your fingers to count from 0 - 5 and you will see that there are actually 6 numbers instead of 5 which is causing your OutOfBoundsException as you don't have a 6th element.
Therefore to access your rows and columns, the range should be between:
0 - 19 (for the columns) and 0 - 4 (for the rows)
Or
1 - 20 (for the columns) and 1 - 5 (for the rows) and then subtract 1 from your scanners input since remember arrays use 0 based index.
update for the file reading:
public static String[][] load() {
try{
FileReader fr = new FileReader("c:/temp/Address.txt");
BufferedReader bf = new BufferedReader(fr);
String presentLine = "";
for(int i = 0; i < 20; i++) {
for(int j = 0; i < 5; j++) {
if ((presentLine = bf.readLine()) != null) {
array[i][j] = presentLine;
}
}
}
} catch(Exception e) {
System.out.println(e);
}
selectMenu();
return array;
}
Although this could be made way better but it's okay.
You could store 20 and 5 as static variables called rows and columns respectively to avoid using hard coded numbers.
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.