I'm having some trouble understanding how Java uses Scanner to read lines from a file and was hoping to get some clarification after days of confusion.
I have a .txt file with one line that contains a name and then 5 doubles. I'm trying to figure out how I can assign each of those to a variable inside a loop so I can work with the data. My goal is to actually take the data from these lines and pass them as parameters to another method for validation, so if there's an easier way to do that, I'm all ears. I feel like I can't find a way to just iterate over each thing inside the nextLine, just over the entire line itself. I'm trying to do this without using an array, here's the relevant code snippet I have right now.
Scanner inputFile = new Scanner(file);
while (inputFile.hasNext())
{
String line = "";
accumulator++;
Scanner split = new Scanner(inputFile.nextLine());
while (split.hasNext())
{
}
stockName = inputFile.next();
shares = inputFile.nextDouble();
purchasePrice = inputFile.nextDouble();
purchaseCommission = inputFile.nextDouble();
salesPrice = inputFile.nextDouble();
salesCommission = inputFile.nextDouble();
System.out.println(stockName);
System.out.println(shares);
System.out.println(purchasePrice);
System.out.println(purchaseCommission);
System.out.println(salesPrice);
System.out.println(salesCommission);
System.out.print(line);
System.out.println("");
// checkValidity(line);
}
I'm having a hard time asking and articulating what I don't know, so any and all help is greatly appreciated... I've literally been working on this for three days and I'm at a total wall.
EDIT:
The layout of the text file looks like this
DELL: Dell Inc
125 25.567 0.025 28.735 0.025
MSFT: Microsoft
34.1 -15.75 0.012 15.90 0.013
You are almost there. You need to just remove the line:
while (split.hasNext())
{
}
This consumes all the elements given to split. You need to assign this to all the elements like stock, salesPrice etc.
So, the new snippet inside the outer while loop is
stockName = inputFile.nextLine();
Scanner split = new Scanner(inputFile.nextLine());
shares = split.nextDouble();
purchasePrice = split.nextDouble();
purchaseCommission = split.nextDouble();
salesPrice = split.nextDouble();
salesCommission = split.nextDouble();
Since, you are reading line by line, also make sure the outer while loop looks like:
while (inputFile.hasNextLine()) {
}
Related
I'm trying to use StringTokenizer to read in data from a text file. The program I am writing is to read in various burger orders. The data I am trying to read in (toppings from burger order) is stored as a String array of size 7. It seems like everything is working fine except for when I am reading in more than one burger order from the text file and it looks like the last array of toppings replaces all the other arrays, meaning that I think my index is overriding the previous index. I tried to copy the array to an temporary array but it seems maybe I'm not doing it correctly. Any help will be appreciated.
while (infile.hasNextLine())
{
line = infile.nextLine();
StringTokenizer tokens = new StringTokenizer(value,", ");
bun = tokens.nextToken();
size = tokens.nextToken();
line = infile.nextLine();
tokens = new StringTokenizer(line,",");
index = 0;
while(tokens.hasMoreTokens())
{
burger_toppings[index] = tokens.nextToken();
temporaryBurgerToppings= burger_toppings.clone();
index++;
}
who = new Burger(size,bun,toppings);
burger.add(who);
}
To solve the issue just create a new array for each Burger order(i.e declare the array again) at the beginning of the outer while loop.
I am assigned to write to another document using data from an input file, and calculating the mean and standard deviation from that file. I have an issue where my code is compiling correctly (according to Dr.Java) but is not giving an output to the output file. I have the code attached that I think is the problem area. It may either be the loops used or reading the file before the loops. Could anyone tell me if those places are the places of error?
// Create a File object passing it the filename
File readFile = new File(filename);
// Create a Scanner object passing File object
Scanner inputFile = new Scanner(filename);
// Perform a priming read to read the first line of the file;
line = inputFile.nextLine();
while (inputFile.hasNext()) //create a loop that continues until you are at the end of the file
{
while( Double.parseDouble(line) != -1)
{
sum += Double.parseDouble(line); //convert the line into a double value and add the value to the sum
count++; //increment the counter
line = inputFile.nextLine(); //read a new line from the file
}
mean = sum/count;
}
inputFile.close();
The output file code:
// Create a FileWriter object using "OutputFileProcess.txt"
File file = new File("OutputFileProcess.txt");
FileWriter fw = new FileWriter(file);
// Create a PrintWriter object passing the FileWriter object
PrintWriter outputFile = new PrintWriter("OutputFileProcess.txt");
// Print the results to the output file
outputFile.println(mean);
outputFile.println(stdDev);
// Close the output file
outputFile.close();
The code needs two loops, one to continue until the ned, and one to exclude any negative numbers in the text file. I should also introduce myself. I am Joe.
This might not be the core of your problem, but one of your while loops is obsolete.
If the inner condition
Double.parseDouble(line) != -1
becomes false, the outer while loop will not change the value of line and the inner while loop will never be entered anymore.
So at the moment the whole algorithm stops at the first -1.
A better way to write this down would be
while (inputFile.hasNext())
{
final String line = inputFile.nextLine();
final double lineAsDouble = Double.parseDouble(line);
if (lineAsDouble != -1D) {
sum += lineAsDouble;
count++;
}
}
final double mean = (double) sum / (double) count;
You should also consider parsing and comparing the values as Integers (if they all are), since comparing doubles with == is always dangerous.
Below are two functions in my class, I want to first read the number of lines from a text file, then store the contents in an array. The problem I am having is that if I do not comment out int aNumber = numOfObjects(newInput); the array does not get stored and printed, it's as if numOfObjects function got to the end of the text file, and I can no longer access it. If I comment it out it works fine. I tried adding a second Scanner object but it didn't help. What can I do to make it work?
public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){
newInput = new Scanner(inputFile);
forCapturing = new Scanner(inputFile);
int aNumber = numOfObjects(newInput);
System.out.println(aNumber);
for(int i=0; forCapturing.hasNextLine(); i++){
publicationArray[i] = new Publication();
publicationArray[i].publication_code = forCapturing.nextLong();
publicationArray[i].publication_name = forCapturing.next();
publicationArray[i].publication_year = forCapturing.nextInt();
publicationArray[i].publication_authorname = forCapturing.next();
publicationArray[i].publication_cost = forCapturing.nextDouble();
publicationArray[i].publication_nbpages = forCapturing.nextInt();
System.out.println(publicationArray[i]);
System.out.println("-----------------------------------\n");
}
}
private int numOfObjects(Scanner aScanner){
int count = 0;
while (aScanner.hasNextLine()){
count++;
aScanner.nextLine(); //if this isn't included you'll experience an infinite loop
}
System.out.println(count);
return count;
}
}
There is a way to do this as you want. i.e. by reading through the file 2 times. First to count and then to capture.
Just add below lines after your line int aNumber = numOfObjects(newInput); in correctListItems function.
public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){
newInput = new Scanner(inputFile);
int aNumber = numOfObjects(newInput);
newInput.close();
inputFile.close();
inputFile = new FileInputStream(
new File(
"inputfile.txt"));
System.out.println(aNumber);
forCapturing = new Scanner(inputFile);
for(int i=0; forCapturing.hasNextLine(); i++){
....
....
So basically closing the scanner as well as file is important. And then creating the fileinputreader stream again will reset the file pointer to the beginning of the file. As you might already know, If the input file is not from the project folder, you have to give the complete path.
As a good process, its always better to close both the scanner object and file object after you're done, And then reinitialize the objects to start working on them again.
Hope this helps.
It looks like the scanner class uses an iterator internally. This means that it needs to be closed at some point, which I cant find in your code. Therefore I would (1) add following line to the numOfObects function before the return: “aScanner.close()”.
(2) I would create the second Scanner instance after you called the function, just to be sure. Hope it works.
Cheers!
The scanner doesn't move to the next line unless you call nextLine. So the loop is infinite since you're always on the first line.
But why do you need to know the number of objects in advance? Why not simply use a list instead of publicationArray?
Well, I am not exactly sure but I can be quite certain that the FileInputStream object once the bytes has been read by Scanner once, the scanner will have a token to indicate that a particular line has been read.
How about you change your code to:
public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){
forCapturing = new Scanner(inputFile);
for(int i=0; forCapturing.hasNextLine(); i++){
publicationArray[i] = new Publication();
publicationArray[i].publication_code = forCapturing.nextLong();
publicationArray[i].publication_name = forCapturing.next();
publicationArray[i].publication_year = forCapturing.nextInt();
publicationArray[i].publication_authorname = forCapturing.next();
publicationArray[i].publication_cost = forCapturing.nextDouble();
publicationArray[i].publication_nbpages = forCapturing.nextInt();
System.out.println(publicationArray[i]);
System.out.println("-----------------------------------\n");
}
System.out.println("Number of lines: "+ i);
}
At least with this, you would not have to run 2 loops to the same set of data. better performance too and get the thing you need done in 1 round of a loop
I am using Scanner to read the text file which contains *, spaces and alphabets. Two or more spaces can occur one after the other. Eg:
**** AAAAA* * ****
******* AAAAAA*** *
I have written the following code:
lineTokenizer = new Scanner(s.nextLine());
int i=0;
if (lineTokenizer.hasNext()) {
//lineTokenizer.useDelimiter("\\s");
System.out.println(lineTokenizer.next());
//maze[0][i]=lineTokenizer.next();
i++;
}
The lineTokenizer doesn't read beyond the * from the input file not are the characters getting stored in the maze array. Can you tell me where I'm going wrong? Thanks!
You could also use FileInputStreams to read the file with a BufferedReader.
I personnally use the Scanner only for console input.
I think you should be using loops instead of just if.
Try changing the 3rd line to:
while (lineTokenizer.hasNext())
Since you are using an if condition, the pointer is not moving ahead. You should use a loop to continuously read data from scanner. Hope that helps.
I guess the code is changed many times while you tried different stuff.
I don't know how you handle the initialization of maze but to avoid any ArrayIndexOutOfBounds I would use a List in a List instead.
I made some guesses about what you wanted and propose this:
List<List<String>> maze = new ArrayList<>();
Scanner s = new Scanner("**** AAAAA* * ****\n ******* AAAAAA*** *");
while (s.hasNextLine()) {
List<String> line = new ArrayList<>();
Scanner lineTokenizer = new Scanner(s.nextLine());
lineTokenizer.useDelimiter("\\s+");
while (lineTokenizer.hasNext()) {
String data = lineTokenizer.next();
System.out.println(data);
line.add(data);
}
lineTokenizer.close();
maze.add(line);
}
s.close();
I did not fully understand your goals. Does this do about what you want?
The code above will give you the following list: [[****, AAAAA*, *, ****], [*******, AAAAAA***, *]]
Ok another question about my program that I'm writing called "Flight." In my tester I am creating an object from the Flight class called myFlight. The object has several fields (flight name, miles traveled, etc) but what I'm doing is reading the data from a file called input.txt and trying to put it into the object that I created. There are five lines of information on the file that I'm reading. For some reason I can't quite get it right, if anyone could help me fix this problem I would greatly appreciate it.
Here is the Constructor that has all the fields from my Flight class:
public Flight(String name, int num, int miles, String origin, String destination)
{
Airlinename = name;
flightnumber = num;
numofmiles = miles;
Origincity = origin;
Destinationcity = destination;
}
And the part of my program where I created the object and try to read the data from the file. I had created a blank constructor in my class too because I wasn't sure if I was supposed to put anything in the object when I created it.
Flight myFlight = new Flight();
File myFile = new File("input.txt");
Scanner inputFile = new Scanner(myFile);
while (inputFile.hasNext())
{
myFlight = inputFile.nextLine();
}
inputFile.close();
}
}
Just in case you use special characters, you need to modify your program so you can read them correctly.
Scanner inputFile = new Scanner(myFile, "UTF-8");
On the other hand, if the text file contains the following, possibly subsequent calls to nextInt() generate a runtime exception.
Gran España
1
1001
New York
Los Angeles
If that were the case, the reading should be different.
myFlight = new Flight(inputFile.nextLine(),
Integer.parseInt(inputFile.nextLine()),
Integer.parseInt(inputFile.nextLine()),
inputFile.nextLine(),
inputFile.nextLine());
As with any program, when adding more conditions to improve the model, it needs more and more code.
Good luck.
try
myFlight = new Flight(inputFile.next(), inputFile.nextInt(),
inputFile.nextInt(), inputFile.next(), inputFile.next());
You can't directly assign a string line to an object, you need to parse the line into parts and assign values to variables one by one.
How is your input text organized? The Scanner's nextLine() method is returning a String object and definitely you cannot assign that to a type Flight. There are different methods to get the different values in the Scanner like nextInt(), nextFloat().
Basically you can try like this
Flight myFlight = new Flight();
myFlight.setFlightName(inputFile.next());
myflight.setMiles(inputFile.nextInt();
etc.
This is just a sample, you need to check the format you have in the input.txt file.