I am working through an assignment and have run into a few snags.
My program prints output to the screen, (not how I need it yet) but only prints the first entry to the file. Below is a snippet of the code. The file appears to be reading in the data from the input file, but the loop does not output to the file past the first entry.
Scanner in = new Scanner(System.in); //Scanner object to read input from the file
System.out.println("Enter filename to read "); //file name prompt
String inputFileName = in.nextLine(); //line input reads next line
/*
* TODO 2) Use an unbuffered file input stream to open listings.txt file
* and read in property listings.
*/
Scanner reader = null;
try {
reader = new Scanner(new File(inputFileName));
} catch (FileNotFoundException e) {
System.out.println("Try Again"); //error window if name is null
JOptionPane.showMessageDialog(null, "You must enter a filename", "File input error", JOptionPane.ERROR_MESSAGE);
return;
}
PrintWriter out = new PrintWriter("agentreport.txt"); //This method prints out the file readfile.txt a word at a time
while (reader.hasNextLine()) { //It needs to output to the text file. Currently a file is created, but it is empty?
Scanner s2 = new Scanner(reader.next());
#SuppressWarnings("unused")
boolean b;
while (b = s2.hasNext()) {
String output = s2.next();
String output2 = output.toUpperCase(); //converts output to upper case
System.out.println(output2);
out.print(output2); //only printing the first entry to the agentsreport.txt file. Not stepping thru the file for some reason?
}
Even if you are using automatic flushing, which you aren't in this case, the PrintWriter object would output anything in its internal buffer unless you do one of two things:
1) Use the println(), printf(), or format() to methods
2) Make a call to the flush() method every time you print, this way all of the data in the internal buffer gets written out.
Note: The print() method does not cause the PrintWriter object to flush() its buffer.
try adding a call to flush() after you call print()
Example of split()
PrintWriter out = new PrintWriter("agentreport.txt");
while (reader.hasNextLine()) {
String words = reader.nextLine().split();
#SuppressWarnings("unused")
boolean b;
for(String word : words) {
String output = word ;
String output2 = output.toUpperCase(); //converts output to upper case
System.out.println(output2);
out.print(output2);
}
One thing that immediately jumps out is that you aren't handling your resources properly.
Any time you use an IO resource such as a reader/database connection/etc., you should always close it using a finally block, using this sort of pattern:
Reader reader = /* construct it however */
try {
/* do something with the reader */
}
finally {
reader.close();
}
If you don't do this, there's no guarantee that the reader will actually be closed, and your application will leak file descriptors/connection pool connections/etc., until eventually it won't be able to get hold of any more and your app crashes. (This won't always have fatal consequences, but it's such a straightforward pattern you should use it every time until it becomes automatic).
In this case, you aren't closing your writer at all, which means that it's not guaranteed that it ever actually flushes its output to the file. It would be perfectly in accordance with the Writer interface for it to write everything or nothing - without the flush, you have no guarantees. Note that closing the writer will automatically call flush, so that's the best bet once you're done with it.
So the latter part of your code should look like:
PrintWriter out = new PrintWriter("agentreport.txt");
try {
// Existing code here
}
finally {
// This closes the file and frees the descriptor, but also flushes the buffers
out.close();
}
Also, how are you handling the IOExceptions that can be thrown by the reading and writing? Are you catching them and swallowing them somewhere? If so, it's possible that your code is throwing an exception telling you exactly why it can't write, and you're just ignoring it and then looking puzzled.
Not to put too fine a point on it, error handling is probably the most significant part of good software development. It's not too hard to write software that works when everything's fine; the most challenging part is handling things well when you run out of space on the hard drive, or the network is temporarily down, etc.
In this case the most pragmatic approach would be to just let the exception be thrown out of the top of your main method. In this case your application will "crash", and you'll get a stacktrace + error message on the console, which will make it immediately clear that something went wrong, and give you a very good idea of what it was.
try
out.println(output2);
http://docs.oracle.com/javase/6/docs/api/java/io/PrintWriter.html
also I'd use a var other than "out" as when system.out is imported to use the shortcode 'out.println()', this could cause variable confusion
edit: good point #Hunter McMillen, changed to println as append is for a CharSequence.
try (
Scanner reader = new Scanner(new File(inputFileName));
PrintWriter writer = new PrintWriter(new FileOutputStream("agentreport.txt"), true);
) {
while (reader.hasNextLine()) {
String output = reader.nextLine().toUpperCase();
System.out.println(output);
writer.println(output);
}
} catch (FileNotFoundException e) {
System.out.println("Try Again"); //error window if name is null
JOptionPane.showMessageDialog(null, "You must enter a filename", "File input error", JOptionPane.ERROR_MESSAGE);
}
Related
I'm writing a program and have been having some trouble with my code. I invoke a method called secondChance() which gives users a second opportunity to enter a valid input. The method is defined as follows:
Scanner input2 = new Scanner(System.in);
StringBuilder html = new StringBuilder();
String val;
try {
System.out.println("Please enter file name you would like to view (include .csv at the end):");
String fileName = input2.nextLine(); //LINE 191
if (!(fileName.equals("doctorList.csv"))) {
input2.close();
throw new FileNotFoundException();
} else {
BufferedReader br = new BufferedReader(new FileReader(file2));
while ((val = br.readLine()) != null) {
html.append(val);
}
br.close();
input2.close();
String output = html.toString();
System.out.println(output);
}
} catch (FileNotFoundException e) {
System.out.println("Invalid file input. Terminating program.");
System.exit(0);
} catch (IOException e) {
System.out.println("Error occured. Terminating program.");
input2.close();
System.exit(0);
}
}
The output/error I get is:
Please enter file name you would like to view (include .csv at the end):
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at CSV2HTML.secondChance(CSV2HTML.java:191)
at CSV2HTML.main(CSV2HTML.java:68)
Line 68 in the exception is the line where the method is invoked. The code that is in the method for asking user input is identical to the code shown inside the secondChance() method. For reference, here is the code which invokes the secondChance() method:
} catch (FileNotFoundException e) {
System.out.println("Invalid file input. Now initiating second chance.");
secondChance(); //THIS IS LINE 68
}
EDIT: I've added input2 at the top of my code block, to show where/how it is initialized.
There are only 2 explanations for scanner.nextLine() throwing that exception. From the way you wrote the question, only one of those two is feasible here:
You have close()d System.in!
System.in is your applications standard input. Assuming you just started the app as normal, that'll be 'the keyboard', effectively, which is endless, and therefore that exception cannot ordinarily happen. If you start it with java -jar yourapp.jar <somefile.txt, you're telling the OS to use somefile.txt as 'the keyboard', and that certainly can run out of lines, and that's the other unlikely explanation. (If you're actually starting your app that way, then that's your explanation: The scanner's consumed all lines. There's probably a bug in your code which results in reading 'too many' lines, step through with a debugger).
However, you can close this resource, which means any further attempts to read from System.in will just fail exactly like you're seeing. The solution is trivial: Do not ever close System.in.
Scanner is a filter and if you close a scanner, then the scanner closes the underlying resource. Thus, assuming you have a scanner of System.in (new Scanner(System.in)), the rule "do no close System.in" expands to: "... and also never close those scanners either".
You have either written:
scanner.close();
or you have written:
try (Scanner s = new Scanner(System.in)) {
// stuff with scanner here
}
That construct invokes the close() method on the thing in the try parentheses when the code 'walks out' of the try block, regardless of how it walks out (control flow, such as a return statement, exception thrown, or just run to the end of it).
Some IDEs will notice you're using a class marked as being a resource (or even just anything that can be used in a try-with as above) and will warn you that you should use try-with. The editor / linting tool is WRONG and you must ignore it. The concept of 'which things should be closed or not' is vastly more complicated than these simplistic tools act like they are. This is one of those resources that you must in fact not close.
Just get rid of it. Delete scanner.close() / replace:
try (Scanner s = new Scanner(System.in)) {
codeHere();
}
with just:
Scanner s = new Scanner(System.in);
codeHere();
I'm trying to read the text contents off of a given URL, then print the contents, as well as write it to a text file using BufferedWriter. I need to include a code block that allows only 35 lines of text to be printed out at a time until the user presses enter using an instance of Scanner, but write the entire text file immediately. All of this must be done within a try-with-resource block. Here is my code:
try(InputStream stream = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true))){
Scanner input = new Scanner(System.in);
String newLine;
int PAGE_LENGTH = 1;
while(((newLine = reader.readLine()) != null)) {
writer.write(newLine + "\n");
//writer.flush();
if(PAGE_LENGTH % 35 == 0) {
System.out.println("\n- - - Press Enter to Continue - - -");
input.nextLine();
}
else {
System.out.println(newLine);
PAGE_LENGTH++;
}
}
writer.close();
}
Prior to implementing the 35 line limit restriction, the writer was correctly writing a text file. I tried adding writer.flush(); in the loop, which resulted in only 35 lines being written, so I know that the problem occurs as soon as the 'if' statement is triggered (it must write several hundred lines of text). I noticed that if I comment out input.nextLine(); that the writer functions again.
How is the Scanner instance preventing BufferedWriter from writing the text file? What am I not considering? Any help/feedback would be greatly appreciated!
How is the Scanner instance preventing BufferedWriter from writing the text file?
Well, then I would say that it is simply because input.nextLine blocks your program, so that you have the time to open the file and check if anything is written.
If you don't flush, nothing will be actually written until the buffer is full (and 35 lines of your text file doesn't fill the buffer apparently), or until you close the file. This is the main feature of a buffered writer, as opposed to a non-buffered one.
It doesn't matter whether you have a scanner or not. It's just that without a scanner, the program runs too quickly that you can only check the file after it has been closed, at which point everything would have been written into it.
Also, you should increment PAGE_LENGTH no matter which branch of the if statement is executed, otherwise it will keep hitting the "if" branch, waiting for you to press enter, once PAGE_LENGTH reaches 35.
if(PAGE_LENGTH % 35 == 0) {
System.out.println("\n- - - Press Enter to Continue - - -");
input.nextLine();
}
else {
System.out.println(newLine);
}
// move this outside of the if statement!
PAGE_LENGTH++;
I have the following code:
CSVmaker(LinkedList data) {
String [] myLines = makeStrings(data);
// for (int k = 0; k<myLines.length; k++)
// System.out.println(myLines[]);
this.file = new File("rawdata.csv");
try {
BufferedWriter buff = new BufferedWriter(new FileWriter(file));
for (int i = 0; i<myLines.length; i++){
buff.write(myLines[i]);
buff.newLine();
System.out.println("done");
}
} catch (IOException ex) {
System.out.println("except");
}
}
No, I checked for the contents of myLines, these are correct.
Also, I get the print which prints "done" just as often as I should.
The csv is created.
However, if I open it manually, it is empty.
What can be the reason for this?
You never flush the buffer, or close the BufferedWriter.
After the for loop, make the following calls:
buff.flush();
buff.close();
Even with other resources, closing them when done is a good idea.
You have to close() the stream after use.
Call buff.close() after write loop; BufferedWriter will flush data to file at close.
Though the question is answered . I would like to add how buffer works.
whenever you try to write to a file using buffer,whatever you write gets added to the buffer. When the buffer is full the contents are written to the file . This way we are reducing the number of hits to the hard-drive hence improving the efficency.
If we want to forcefully write to a file without the buffer getting full , we use flush() method.
Starting with Java 8, one would simply do it with a try with resources, which automatically closes the BufferedWriter. Also see the usage of the new class Files
try (BufferedWriter writer = Files.newBufferedWriter(somePath, yourCharset)){
writer.write(output);
}
I am trying to make a method that reads words from a file and saves them in a string named common.
After this, it should compare the words in common to the words in a list of strings (not an ArrayList) and remove any of the nodes in the list that appear in the file (or the string common).
When I compile this program, it works fine. It also runs. However, for some reason, it just skips over the while loop.
private void removeCommonEnglishWords() {
Scanner infile = null;
try {
infile = new Scanner( new FileInputStream( "filename" ) );
} catch(Exception e) {
System.out.println("Nope");
}
String common = "";
while (infile.hasNext()) {
common = common + infile.next() + " ";
}
for (int k = 0; k < terms.size(); k++) {
if (common.contains(terms.get(k))) {
terms.remove(k);
}
}
}
If it's skipping over the while loop, then that means your only possible problem is "infile" is not getting defined, and it is either null from your initialization, or it is simply empty.
Actually, from looking at this code snibbit, that would make sense. Above in your code this is the only thing that is running in your try block:
try {
infile = new Scanner( new FileInputStream( "filename" ) );
}
// By the way you should use this instead
try( /*initialized resources here */ ) {
//Do work here
}
All your work needs to be inside this try block. This is because if something were to happen with the input stream, or your code fires an exception, it needs to be properly handled. The try (with resources) block I mentioned above automatically tries closing your declared resources directly after the try block, before the code execution continues. This is mainly a security reason, so other users can't get a hold of your resource and manipulate it.
For instance your code block might look something like the bellow (I'm putting dummy example code here):
try ( FileOutputStream fos = new FileOutputStream("server/file.txt")) {
// Do work.
byte[] byteArray = new byte[9]();
fos.write(byteArray);
// Try with resources block will automatically try closing the resources,
//but if there are any errors, they are suppressed. You can still print the
//supressed errors, but you will have to write extra code for this.
} catch(Exception e) {
// Always print out logs, so you know what went wrong!
e.printStackTrace();
System.out.println("Whoops! There was an error, please fix.");
}
Here is the docs on try with resources, if you want to read more :)
Also, you didn't specify anything about the file name, but are you sure you have the right path to your file?
I'm trying to write a program that gets a users input that is then written to an output file called userStrings.txt. I'm also trying to stop the processing once the user inputs 'done', but I'm not sure how to accomplish this.
Here is my code:
import java.io.*;
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) throws IOException {
// Name of the file
String fileName = "userStrings.txt";
Scanner scan = new Scanner(System.in);
try {
// FileReader reading the text files in the default encoding.
FileWriter fileWriter = new FileWriter("userStrings.txt");
// Wrapping FileReader in BufferedReader.
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("A string");
bufferedWriter.write("Another string");
bufferedWriter.write("Yet more text...");
System.out.println("Enter something, DONE to quit: ");
String input = scan.nextLine();
// Closing file
bufferedWriter.close();
}
catch (IOException ex){
System.out.println("Error writing to file " + "userStrings.txt" + "");
}
} // End of method header
} // End of class header
In order to write to a file, do I still use System.out.println? and is the bufferedWriter.write even necessary? I'm just trying to understand the I/O and writing to files better.
Thanks!
In order to write to a file, do I still use System.out.println?
No. That writes to standard output, not to your file.
If you are using println then you need to wrap your BufferedWriter with a PrintWriter. (Look at the javadocs for the System class where the out field is documented.)
and is the bufferedWriter.write even necessary?
If you are going to write directly to the BufferedWriter then yes, it is necessary, though you probably need to an appropriate "end of line" sequence. And that's where it gets a bit messy because different platforms have different native "end of line" sequences. (If you use PrintWriter, the println method picks the right one to use for the execution platform.)
I'm also trying to stop the processing once the user inputs 'done', but I'm not sure how to accomplish this.
Hint: read about the Scanner class and System.in.
Right under you take input from the console, run a while loop to test that input is not equal to "done". Inside the while loop, add input to your file and get the next line of input.
while(!input.toLowerCase().Equals("done"))
{
bufferedWriter.write(input);
input = scan.nextLine();
}