Scanning 2D String Array From a File - java

Scanner input = null;
try {
input = new Scanner (new File(filename));
} catch (FileNotFoundException ex) {
Logger.getLogger(Puzzle.class.getName()).log(Level.SEVERE, null, ex);
}
int m = 4;
int n = 4;
Puzzle = new String [m][n];
while (input.next()!=null){
for (int i=0;i<m;i++){
for (int j=0;j<n;j++){
Puzzle[i][j]= input.next();
System.out.println(Puzzle[i][j]);
}
}
}
I have a little problem with this piece of code. as I scan the input to put my puzzle array it skips the first string. for example in the first line, lets assume the 4 letter "A B C D" are on. It skips the "A" and continues with "B". I know maybe its too easy for you guys, but as a begginner I kinda need your help.

You are consuming multiple tokens in each iteration of the while loop - one when you call next() in the condition of the loop (which is not used) and multiple others when you call next() inside the for loops (which you store).
You should change the logic of your code. You don't need the while loop.
For example :
boolean done = false;
for (int i=0;i<m && !done;i++){
for (int j=0;j<n && !done;j++){
Puzzle[i][j]= input.next();
if (Puzzle[i][j] == null)
done = true;
System.out.println(Puzzle[i][j]);
}
}

Related

Using Scanner to analyse a string, letter by letter, in a for loop (Throwing IndexOutOfBoundExceptions)

I need to count the frequency at which a letter appears in a string.
To do this, I thought about using a scanner object, passing the string to it
Scanner s = new Scanner(String)
and using the next() method to analyse each char with a switch statement.
I've done a search on these boards and have devised the following :-
for (int i = 0; i < outputString.length(); i++) {
Scanner s = new Scanner(outputString);
char letter = s.next().charAt(i);
switch (letter) {
switch code;
}
This appears to work when the string I'm analysing contains anything (-_z1 etc..) other than whitespaces which will cause the program to throw a String.IndexOutOfBoundException (4).
Is there something else I can try or should I just remove all the whitespaces from the word (i.e. I'm thinking by creating a newword string using a for loop to add each string.charAt(i) != ' ').
Edit: I forgot that the scanner was in the for loop, I'll take it out. Secondly, not sure if it changes matters but I'm trying to count the no of times each letter in the alphabet in the string appears, not just one type of letter. Thanks for your comments!
Thanks in advance,
Here is an alternative way to solve this problem provided on another question. (can't leave comments yet.. so have to put as an answer...)
How to count frequency of characters in a string?
While having this:
Scanner s = new Scanner(outputString);
Inside the for loop, you're creating a new Scanner in every iteration (not efficient nor what you want).
If you already have a String called outputString you can access its characters / letters directly as follows:
for (int i = 0; i < outputString.length(); i++) {
char letter = outputString.charAt(i);
//The rest of you code here
}
I strongly think you're complicating things by using that approach. You can simply pass the String (and the char you are searching for) into a method just like the one below:
public int checkFreq(char letter, String word){
int freq = 0;
for(int i = 0; i < word.length(); i++){
if((word.charAt(i)) == letter){
freq++;
}
}
return freq;
}
I hope this helps.. Merry coding!
You should follow the above solution for getting repeated characters in a string. However, I will just give you a hint about why you are getting the exception
consider the following code:
String outputString = "Pre ";
for (int i = 0; i < outputString.length(); i++) {
Scanner s = new Scanner(outputString);
System.out.println(outputString.length()); // output is 4
System.out.println(s.next().length()); //output is 3, not considering the space
//char letter = s.next().charAt(i);
//System.out.println(letter);
}
First of all, you shold not create new Scanner each time when you ready next character. Do it only once, before for loop.
Second - to read scanner character by character, you have set delimeter as "". In this case, scan.next() returns next character.
Third - you use Scanner to analyze string, that's OK (not optimal and overhead, but OK). Then do create new Scanner isntance and rely on it's data, but not on length of the goven string; do use Scanner.hasNext() method. I mean that all you need, is just add hasNext() to be sure that more characters exists in the scanner's stream:
try (Scanner scan = new Scanner(outputString)) {
scan.useDelimiter(""); // to make scan.next() return one single character
while (scan.hasNext()) {
char ch = scan.next().charAt(0); // next() returns String with one character
// do your work
}
}
P.S. This is code examples, how you can cound character frequencey in the given string with different ways. Probably, one of them you'll find more relevant to your task.
// this is your approach
public static int characterFrequency(String str, char ch) {
try (Scanner scan = new Scanner(str)) {
scan.useDelimiter("");
int count = 0;
while (scan.hasNext())
count += scan.next().charAt(0) == ch ? 1 : 0;
return count;
}
}
// this one is the most efficient
public static int characterFrequency(String str, char ch) {
int count = 0;
for (int i = 0; i < str.length(); i++)
count += str.charAt(i) == ch ? 1 : 0;
return count;
}
// this one is the smallest of code
public static int characterFrequency(String str, char ch) {
return (int)str.chars().filter(e -> e == ch).count();
}

Putting names from a file into an array is causing an infinite loop

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.

Reading from a text file into an array - getting "nulls"

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;
}
}

A Good Method to read files in Java

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.

How to read a GRID of data from a text file in Java?

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);
};
}

Categories