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
Related
String path1, path2;
int count = 0, i = 0;
path1 = args[0];
File file = new File(path1);
FileReader reader = new FileReader(file);
Scanner inputFile = new Scanner(reader);
while(inputFile.hasNextInt()) {
inputFile.nextLine();
count++;
}
int[] array1 = new int[count];
while(inputFile.hasNextInt()) {
//inputFile.nextLine();
array1[i] = inputFile.nextInt();
i++;
}
I never had this issue before, but when I try to write values to an array from a text file containing only int values, one per line, my array only returns all "0"s. instead of the numbers in the text file. I'm not sure if it has to do with me using the command line, but it has the correct argument (file destination) entered in my IDE.
Thanks in advance!
Notice that the exit condition of both while loops are the same. If the first ends then the second one will be jumped over as the condition is immediately false. The pointer of the scanner is already at the end of the file (all numbers have been read by the first loop) so there is nothing left to read.
You have 2 options to fix this issue.
Use an ArrayList: Use an ArrayList<int> object to save the numbers in the first loop. The list grows as numbers are entered so you don't need to know the number of lines before making this object, as opposed to needing to know this to make an array.
Scan the file again: In between the loops close the previous filereader and scanner and create a new one. This new scanner will point to the start of the file again and the second loop will run smoothly.
So i'm working on a bowling calculator assignment that takes a series of inputs and calculates a score. The test input provided by my instructor has a number of test cases which denote how many strings will need to be computed to scores. The problem I am having is that I am not able to get all 3 strings (there are 3 test cases) into a single string, separated on different lines.
This is what the input is:
3
--,--,--,--,--,--,--,--,--,--
X,X,X,X,X,X,X,X,X,XXX
X,13,X,81,5/,X,18,33,X,X36
I am trying to get it to be formatted as such:
--,--,--,--,--,--,--,--,--,--
X,X,X,X,X,X,X,X,X,XXX
X,13,X,81,5/,X,18,33,X,X36
However, when I run my code I get this as the output:
--,--,--,--,--,--,--,--,--,--
X,X,X,X,X,X,X,X,X,XXX
X,13,X,81,5/,X,18,33,X,X36
Here is what I've got so far.
import java.io.*;
import java.util.*;
public class Bowling {
public static void main(String[] args) throws FileNotFoundException {
File inFile = new File("input.txt");
Scanner scanFile = new Scanner(inFile);
int tc = scanFile.nextInt();
String N = "";
for (int i=0; i < tc; i++)
N += scanFile.next();
System.out.println(N);
}
}
**UPDATE: Thank you everyone for the answers, I have learned quite a bit because of your responses. At the time of asking this question I was tied up on this problem and was not thinking straight. I looked over my code again and realized all i had to do was add this line before the strings were added to the variable:
N += "\n";
Again, thanks to all those who commented.
I recommend using a StringBuilder if you are going to be concating a lot of String's. But on every iteration of the loop, you can append a newline character:
StringBuilder sb = new StringBuilder();
for (int i=0; i < tc; i++) {
sb.append(scanFile.next());
sb.append("\n");
}
System.out.println(sb);
It is possible to:
• Make a String[] array
• Use dividers, like \t
• Use other methods
Also, don't forget to say that you want us to tell you how to use newline characters.
I'd love to use StringJoiner in your case,I totally agree with #GBlodgett's answer. But this too can serve as an alternate.
From the javadoc,
StringJoiner is used to construct a sequence of characters separated
by a delimiter
which exactly suits your case. Your loop reads as,
StringJoiner sj= new StringJoiner("\n"); // Here, "\n" is the delimiter between every join.
for (int i=0; i < tc; i++){
sj.add(scanFile.next());
}
System.out.println(sj.toString());
Also, this avoids appending unnecessary newline after the last appended line.
I've found a bug in your code that explains why the output is in one line.
The command System.out.println(N) should be inside the for loop.
The variable N is unnecessary - please omit it.
There is another problem of resource leakage in your code, because the Scanner was never closed. The scanner should be closed using the auto closeable mechanism (by using try with resource statement).
I propose the following code to solve the problem:
public static void main(String[] args) throws FileNotFoundException {
File inFile = new File("input.txt");
try (Scanner sc = new Scanner(inFile)){
int tc = sc.nextInt();
for (int i=0; i < tc; i++) {
System.out.println(sc.next());
}
}
}
I have a text file like this;
7-Georgia
1-Andrew
6-John
8-Luke
9-Erica
3-Kim
2-Jude
5-Phil
4-Leo
The first column is id and second is name. How can I get these id's and names? So far I wrote this;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
public class Main {
#SuppressWarnings("resource")
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
#SuppressWarnings("unused")
Scanner fromFile = new Scanner(new File("id_name.txt"));
fromFile.useDelimiter("-");
while(fromFile.hasNext()){
String temp = fromFile.next();
System.out.println(temp);
}
while(fromFile.hasNext()){
String temp= fromFile.next();
int[] fileID;
fileID= new int[9];
for(int i=0; i<9; i++){
fileID[i]= Integer.parseInt(temp);
}
System.out.println(fileID);
}
}
}
But this doesn't get the id's. I'm not sure how to fix this, I'd be grateful if you help me.
You have two while loops in your code. Typically one while loop will go through every item until the condition is no longer true. I think you need to rework this to have a better "flow of control" which might mean using only one while loop (with sections to grab the number and then the name.
I imagine that you are looking for results from the second while loop, but by the time you get to it, the first while loop will have exhausted all of your data.
Finally, printing an array will print out the array reference identifier. If you want to actually print the contents of the array, you need a loop over the elements within the array, and you need to print out each array element explicitly.
As an alternative to the array printing technique above (which you should master), you can also use the Arrays.toString(<insert array here>) method call. However, in many cases it will give you a format that is not desired. That's why you need to know the above technique too.
Also, you have one hidden issue. You (in the second while loop) make the assumption that there are only nine inputs. Pay close attention to what you are writing. Every time you have to reach for a number, consider whether it is a "magic" number. Magic numbers are numbers that are in your code with no explanation or reason why they exist. They are indicators of errors in the code made by assumptions that probably won't last the test of time.
For example, you are using the number 9 because you have seen the input file. The next input file will probably not have nine entries in it, and your program will probably not work right if you gave it an input with eight entries, or an input with ten entries. Perhaps you should rewrite the loop to remove the magic number, by making the logic process while there is still (some) input.
Try this on for size
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
Scanner fromFile = new Scanner(new File("id_name.txt"));
} catch (FileNotFoundException e) {
System.err.println("File not found");
}
String[] arr = new String[9];
String[] oth = new String[9];
int i = 0;
while(fromFile.hasNextLine()) {
String temp = fromFile.nextLine();
oth[i] = temp.substring(0,1);
arr[i] = temp.substring(2);
i++;
}
int[] fileID;
fileID = new int[9];
for(int j = 0; j < 9; j++) {
fileID[j] = Integer.parseInt(oth[j]);
}
}
}
this should go through and retrieve the numbers(.substring(0,1)) and then the names(.substring(2)), and then converting the numbers to int values.
Try the following:
File file=new File("id_name.txt");
int[] fileID;
fileID= new int[9];
String[] result = file.nextLine().split("-");
for (int x = 0; x < result.length; x++){
if (Character.isDigit(result[x])) { // use the isDigit method to get the ids
System.out.println("this is an id");
fileID[i]= Integer.parseInt(result[x]);
}
Actually my friend, there are several mistakes here.
1) When the first while loop completes, it leaves fromfile.hasNext() as false Hence the second loop never starts.
>> To fix this, You need to put it all in one while loop.
2) fileID is an array. You cannot print it using System.out.println(fileID).
>> You have to tell what kind of output you want. The code will depend on that. For simply printing all the values, you need to make a for loop that prints each value separartely. You should use fileID.length for the no. of times you need to loop it.
3) Basically, fromfile.next() is not the way to do it.
>> You need to use fromfile.nextLine().
BAR CHART
Write a Java program that reads today's sales figures (integers) for five stores from an existing text file called sales.txt and output to a new file called storeReport.txt
The program should display a bar chart comparing each store's sales. Create each bar in the bar chart by displaying a row of asterisks. Each asterisk should represent $100 of sales.
Below are the integers to be read from sales.txt:
1000
1200
1800
800
1900
The output file (storeReport.txt) should look like this:
Store 1: **********
Store 2: ************
Store 3: ******************
Store 4: ********
Store 5: *******************
Keep in mind, I'm only in Chapter 5: Intro to Loops and Files, of Intro to Java. The answer must be very simplistic. We haven't gotten to the following in my text yet, so please refrain from using them: int[ ], bufferedWriter, fstream, .length, out.print .....etc, etc
Thus, I must use the simplest of code such as:
Scanner inputFile = new Scanner (file)
File inputFile = new File (sales.text)
PrintWriter outputFile = new PrintWriter (storeReport.txt)
We may use for loops, while loops, and nested loops.
Below is the code that I've written thus far. I'm getting compile errors. Please help!! Thanks!
import java.util.Scanner;
import java.io.*;
public class BarChart
{
public static void main(String[] args) throws IOException
{
int store1,store2,store3,store4,store5;
int bar1,bar2,bar3,bar4,bar5;
Scanner inputFile = new Scanner(System.in);
File inputFile = new File("sales.txt");
File outputFile = new File("storeReport.txt");
PrintWriter outputFile = new PrintWriter("storeReport.txt");
outputFile.println("SALES BAR CHART\n");
bar1 = store1/100;
outputFile.println("store 1 : ");
for(int i = 1; i <= bar1; i++)
outputFile.println("*");
bar2 = store2/100;
outputFile.println("\nStore 2 : ");
for(int i = 1; i <= bar2; i++)
outputFile.println("*");
bar3 = store3/100;
outputFile.println("\nStore 3 : ");
for(int i = 1; i <= bar3; i++)
outputFile.println("*");
bar4 = store4/100;
outputFile.println("\nStore 4 : ");
for(int i = 1; i <= bar4; i++)
outputFile.println("*");
bar5 = store5/100;
outputFile.println("\nStore 5 : ");
for(int i = 1; i <= bar5; i++)
outputFile.println("*");
inputFile.close();
outputFile.close();
System.out.println("Data written to the storeReport.txt");
System.exit(0);
}
}
Well, you've got 2 variables named inputFile:
Scanner inputFile = new Scanner(System.in);
File inputFile = new File("sales.txt");
Try renaming the first one to inputScanner.
Same deal for outputFile.
It seems that your code would be able to successfully produce the desired output to storeReport.txt - if store1, store2 etc. had contained the numbers from sales.txt, which they don't. You have not told Java to read the numbers from the file and into the variables; they won't automatically get populated with data from the file. The compile error you're getting is probably related to using variables that haven't been initialized (i.e., they don't contain any data yet). Reread the part of your book that covers file input to find out how you can load data from a file into your variables. :-)
I would consider a method like this
static void printBar(int sales) {
int bar = sales / 100;
for(int i = 0; i < bar; i++) outFile.print("*");
outFile.println(""); // flush and finish line
}
You can employ this effectively for each of your inputs. You would have to set up your outFile variable as a static class variable, or pass it in as a parameter to printBar().
Hints:
You cannot have two local variables in the same scope with the same name. Particularly look at your declarations of inputFile.
You need to review the purpose of the Scanner and File classes. Read the javadocs, and look at the methods and constructors they declare.
The statement bar1 = store1/100; in the current version of the code will (once you've fixed other errors) give you a compilation error saying that store1 has not been initialized. Local variables must be initialized before you use them.
Creating a Scanner object doesn't actually read anything. You have to call methods on the object to make it do something.
What I'm trying to do is create lots of random files but I'm just completely lost. The code below just doesn't work, I'm wondering why it doesn't work and what can i do to fix it.
import java.io.*;
import java.util.*;
public class main {
public static void main(String arg[]){
Random rn = new Random();
int randn = 1+rn.nextInt(999999990);
String I_S = Integer.toString(randn);
Formatter file;
try{
for(int i = 0; i < 9999999; i++){
file = new Formatter("%s.txt", I_S);
}
}
catch(Exception ex){
System.err.println("Error");
}
}
}
By just generating random numbers, you may end up creating / overwriting the same file multiple times. To have an absolutely unique set, do something like this:
final int MAX = 9999999;
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < MAX; i++) {
list.add(i);
}
Collections.shuffle(list);
for (int i = 0; i < MAX; i++) {
// create files here
}
How to create multiple files, generating a random name for each file.
You probably want to have a look at File.createTempFile.
Looking at your code, you probably want something like
Random rn = new Random();
String file;
for (int i = 0; i < 100; i++)
file = String.format("%i.txt", 1+rn.nextInt(999999990));
I'm not sure exactly what you expect this code to achieve, but right now it effectively does nothing.
You're looping many, many times creating an instance of Formatter each time. This is not a file; instead, it's a class that knows how to replace tokens in strings to create other strings.
I think you're confused by the description of the constructor you're calling and the purpose of the class as a whole. The constructor takes as its first argument the name of the file to use for output - in your case, this will always be %s.txt. The second argument is the name of a supported charset to use for encoding the String to the file.
This code will always fail because:
Your I_S variable, e.g., "56437890" is not a valid encoding (whereas "UTF-8" would be). Hence the constructor will probably throw an exception when trying to work out the encoding scheme.
Even if the charset was miraculously right, you're still trying to write to the same file (%s.txt) every time, so you wouldn't get the desired multi-file behaviour.
This string may not even be a valid filename, depending on your OS, and so if the Formatter tries to create the file it will throw an exception.
If both arguments miraculously work out, you're still not actually doing anything with the formatter, so it doesn't have anything to write out to the file which thus may not be created.
Finally, you're not updating your random variable (I_S) in the loop - it gets set once, and then maintains the same value forever. So even if all the above problems weren't issues, you'd still create the same (single) randomly-named file over and over and over again.
And as I noted in the comments, when it fails, you're catching and swallowing the exception so you have absolutely no way of knowing what went wrong.
Fundamentally I think you're confused about the purpose of the Formatter class, and since I don't know what you're trying to achieve (should the files be empty? Have specific text in?) I can't suggest something which definitely works. However, if you just want to create empty files, try something like this inside your loop:
String filename = "%s.txt".format(I_S);
File file = new File(filename);
file.createNewFile();
// Add some logic to update the random variable here!
As a final point, adarshr's answer is entirely right that you stand a nontrivial chance of repeating random numbers, so you won't get exactly as many files as you expect. The answer goes on to describe a good way to avoid this, and it's worth following.
You may want to look into writing something more like this:
void Write()
{
try {
for(int i = 0; i < MAX_FILES; i++) {
FileWriter outFile = new FileWriter("C:\File" + i.toString() + ".txt");
PrintWriter out = new PrintWriter(outFile);
// Write text to file
out.println("This is line 1");
out.println("This is line 2");
out.print("This is line3 part 1, ");
out.println("this is line 3 part 2");
out.close();
}
}
catch (IOException e) {
e.printStackTrace();
}
}
// obviously this requires a import java.io.*; at the top of the class
Source: http://www.abbeyworkshop.com/howto/java/writeText/index.html