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();
}
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 need to dialogue with an external c++ console program (read output and write input). I read from the application with a Thread (and it works), but when it needs input, it works only the first time, then the stream probably remains empty, and it doesn't receive the second input (and external program closes).
The application i'm using is a simple .exe wrote in c++ that:
print "Insert first input"
scan input1
print input1
print "Insert second input"
scan input2
print input2
Main class:
import java.io.*;
import java.util.Scanner;
public class ExampleCom {
public static Communication com = new Communication();
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
String s;
com.read();
while(true)
{
s = in.nextLine();
com.write(s);
}
}
Communication class:
public class Communication
{
Process p;
OutputStream writer;
public InputStream reader = null;
Read r; //Class that with a loop read all exe input
Communication()
{
try{
p = Runtime.getRuntime ().exec ("C:\\esempio.exe");
writer = p.getOutputStream();
reader = p.getInputStream();
}catch(Exception e){}
}
public void read()
{
r = new Read();
Thread threadRead = new Thread(r);
threadRead.start();
}
public void write(String s)
{
try{
writer.write(s.getBytes());
writer.flush();
writer.close();
}catch(Exception e){}
}
}
How can I send my string (like "writer.write('hello')") when the external application needs it?
The problem is that in your write() method, you have the line
writer.close();
which means that after calling it the first time, you are closing the input stream to your C++. As far as it is concerned, it sees the "end of file" marker after your first input.
What you should do is put the close() in a separate method, and call that method only when you are done working with that process.
Now, as your target program expects text input and will only interpret the input if it gets an end-of-line (as per your answer to the question in my comment), you should supply that end-of-line to it.
Instead of doing raw byte-writes, I think a better approach would be to use a PrintWriter for that output stream, and use as naturally as you use System.out.println(). It can also save you on the flush() part.
You are interpreting it incorrectly when you see that your program is not reading the input until you close(). It's not waiting - it sends it as soon as you call flush(). But the C++ waits for either an end-of-file or an end-of-line, and since you are not giving it an end-of-line, then only close(), that sends it end-of-file, causes it to accept the input. But then you can no longer send any further data.
So the solution is, first, to define your writer as a PrintWriter. Instead of
OutputStream writer;
Use
PrintWriter writer;
And instead of
writer = p.getOutputStream();
Use
writer = new PrintWriter(p.getOutputStream(), true);
The true there will give you auto-flush whenever you use the println() command.
Now, your write method should be:
public void write(String s)
{
writer.println(s);
}
Note that a PrintWriter doesn't produce exceptions, so if you care about errors, you have to check for them using checkError().
And of course, have the close() in a separate method, as I mentioned before.
Because the write() method might throw an IOException, it is advisable to call the close() method inside a finally block.Place the writer.close() method outside the try clause:
finally {
if(writer != null) {
writer.close();
}
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);
}
I know how to use string args to get the input from the command-line, and it is working fine with input = args[0] where my input is java.exe program s1.in
But I need to run a compare program in terminal. So my input must have the "<" symbol. However, then I can't get my input values using input = args[1]. When I type this in, the args.length become 0. Why does this happen?
As an aside, does anyone know how to best search for this kind of term in google? Itthink google does not recognize "<" in the search entry.
Thank you
It's because when you use xyzzy <inputfile, your shell runs xyzzy and "connects" that file to your standard input. It then expects you to read that standard input to get your data - you never see the argument because it's removed from the command line (or, more likely, never added to your argument list).
That's why many programs will process a file if given, otherwise they'll read their data from standard input. And that's exactly what you need to do here.
For doing this, you'll probably want something like:
import java.io.*;
class Test {
public static void main(String args[]) {
InputStreamReader inp = null;
Boolean isStdIn = false;
try {
if (args.length > 0) {
inp = new InputStreamReader(new FileInputStream(args[0]));
} else {
inp = new InputStreamReader(System.in);
isStdIn = true;
}
// Now process inp.
if (isStdIn)
inp.close();
} catch (Exception e) {
System.exit(1);
}
}
}
It selects either the file (if available) or the standard input stream for reading.
Often, the most easy way is to use Scanner:
Scanner scaner = new Scanner (System.in);