File I/O Java prompt - java

I had a quick questions about prompting and accepting a file name, then making the file-text a scanner object.
I want the program to prompt the user to enter the name of a file, until he gets one which exists, then for the file-text to be used as a scanner object.
This is the code I have so far, it works to the point where I exit the while {} loop, but then when I try and process the scanner item like while (input.hasNextLine()) { it gives me an error saying it can't find the scanner item.
It's probably a silly mistake, but I just cannot seem to get it.
The whole code is below:
import java.io.*;
import java.util.*;
public class PersonalityTest {
public static void main(String[] args) throws FileNotFoundException {
boolean isFile = false;
Scanner sc = new Scanner(System.in);
System.out.print("Input file name? ");
String fileName = sc.next();
File inputFile = new File(fileName);
while (isFile == false) {
if (inputFile.exists()) {
Scanner input = new Scanner(inputFile);
isFile = true;
}
}
while(input.hasNextLine()) {
}
}

The scope of the input variable is local to the while (isFile == false) block. Declare it outside otherwise it won't be visible.
For the first part "I want the program to prompt the user to enter the name of a file, until he gets one which exists": Move this code:
Scanner sc = new Scanner(System.in);
System.out.print("Input file name? ");
String fileName = sc.next();
File inputFile = new File(fileName);
into a method and call it inside the while (isFile == false) block before the exists check (the method should return with the file or make the variable visible in the block by some other means).

You can't access input outside the if statement, sice the compiler is not sure, it will pass the test, you can do this:
Scanner sc = new Scanner(System.in);
Scanner input = null;
boolean isFile = false;
while (isFile == false){
System.out.print("Input file name? ");
String fileName = sc.next();
File inputFile = new File(fileName);
if (inputFile.exists()){
input = new Scanner(inputFile);
isFile = true;
}
}
But will throw a NullPointerException if it is null.
I changed the code a little bit, that way, it will not exceed if the file doesn't exist.

The Scanner input is local to your if statement. Your while (input.hasNextLine()) { statement will not work because of that. The Java compiler will treat input as a separate Scanner object and that is where the problems crop up, because to the Java compiler, the input that you are trying to use does not exist.
I would follow MouseEvent's suggested code as it does not run into the problem mentioned above.

The other answers have addressed your immediate question, but I want to point out a couple of other problems with your code:
The way that you are checking to see if the file can be opened is flawed. A better way to write the code is to attempt to open the file ... and retry when there is an exception. For example:
Scanner input = null;
do {
System.out.print("Input file name? ");
String fileName = sc.next();
File inputFile = new File(fileName);
try {
input = new Scanner(inputFile);
} catch (IOException ex) {
System.out.println("Cannot open: " + ex.getMessage());
}
} while (input == null);
Why is this better than calling File.exists()?
There are lots of reasons why you might be able to open a file. It might not exist at all. It might be a directory or a special file that can't be opened as a file. The application might not have permission. The file might be on a remote mounted file system and the remote mount might have just died.
There is a small time gap between the File.exists() call (and any others that you might make) and actually opening the file. In that time gap, it is possible that something to your program could do something to make the file unopenable; e.g. it could change its permissions or delete it.
The second problem is that your code potentially leaks a file descriptor because the scanner is not closed. In your specific application (as written) this doesn't matter because you are going to exit the application immediately after using the scanner. But if your weren't ... and this code was called lots of times ... you could find that you are unable to open files after a bit.
The correct way to deal with this would be to write your code something like this:
public static void main(String[] args) {
try (Scanner input = openInput()) {
while (input.hasNextLine()) {
// do stuff
}
}
}
This uses Java 7's new "try with resource" syntax, that ensures that the resource is closed when the try statement completes. (You can do the same thing in pre-Java 7 using a try / finally, but the code is a bit more cumbersome.)

Related

Java Scanner Error : java.util.NoSuchElementException: No line found -- java.base/java.util.Scanner.nextLine(Scanner.java:1651))

I am a beginner with java and programmin over all, So this the full code for a file reader program that counts words or displays text file content, I wanted to take user inputs for commands that I indicated using an if statement, but String printFileCommand = scan.nextLine(); is not working due to the error addressed below:
package com;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileReader {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanTwo = new Scanner(System.in);
System.out.println("Please Enter Your File Path");
String filePath = scanTwo.nextLine();
scanTwo.close();
File fileInput = new File(filePath);
Scanner fileScanner = new Scanner(fileInput);
System.out.println(fileScanner.nextLine());
fileScanner.close();
System.out.println("Commands: PRINT.FILE --> Prints all file COUNT.WORDS --> Counts all words");
System.out.println("Type Command:");
Scanner scan = new Scanner(System.in);
String printFileCommand = scan.nextLine(); <----ERROR HERE
scan.close();
if (printFileCommand.contains("PRINT.FILE")) {
while (fileScanner.hasNextLine()) {
System.out.println(fileScanner.nextLine());
}
} else if (printFileCommand.contains("COUNT.WORDS")) {
int wordCount = 0;
while (fileScanner.hasNext()) {
String fileWords = fileScanner.next();
wordCount++;
// System.out.println(wordCount);
}
System.out.println(wordCount);
}
else {
System.out.println("COMMAND INVALID!");
}
}
}
```
**Terminal Output:**
PS C:\Users\DR\Desktop\FIRST REAL PROGRAMMING> c:; cd 'c:\Users\DR\Desktop\FIRST REAL PROGRAMMING'; & 'c:\Users\DR\.vscode\extensions\vscjava.vscode-java-debug-0.30.0\scripts\launcher.bat' 'C:\Program Files\AdoptOpenJDK\jdk-15.0.1.9-hotspot\bin\java.exe' '--enable-preview' '-XX:+ShowCodeDetailsInExceptionMessages' '-Dfile.encoding=UTF-8' '-cp' 'C:\Users\DR\AppData\Roaming\Code\User\workspaceStorage\458dc35931a3067a355426e5ceeeee32\redhat.java\jdt_ws\FIRST REAL PROGRAMMING_e263b9bc\bin' 'com.FileReader'
Please Enter Your File Path
E://texttwo.txt
This is my text file.
Commands: PRINT.FILE --> Prints all file COUNT.WORDS --> Counts all words
Type Command:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at com.FileReader.main(FileReader.java:21)
PS C:\Users\DR\Desktop\FIRST REAL PROGRAMMING>
So why is `String printFileCommand = scan.nextLine();` not working? I tried alot, but its not working...
It doesn't work because your stream for System.in is closed.
You can check it for example System.out.println(System.in.available()); and you will see:
Exception in thread "main" java.io.IOException: Stream closed
at java.io.BufferedInputStream.getInIfOpen(BufferedInputStream.java:159)
at java.io.BufferedInputStream.available(BufferedInputStream.java:410)
you closed it in line: scanTwo.close();
I'm still trying to understand Java myself, but I think you don't exactly need to create and use multiple Scanners to collect data. Since you are searching for strings for the file creations, you could technically do something like:
Scanner scanner = new Scanner(System.in);
String filePath = scanner.nextLine();
With some of the other scanners you can keep since you're specifically calling the fileInputs within the Scanner, but when asking the user for data, I suggest using only one scanner source, but having something like the last line of code I shared as a template for updating your code! If I misunderstood something you're more than welcome to let me know. Thanks!
Please check this question:
NoSuchElementException - class Scanner
Your code will work if you remove the code:
scanTwo.close();
Or removing better:
Scanner scan = new Scanner(System.in);
And use scanTwo for reading (but you don't have to close the scanner with scanTwo.close()).
But I recommend you to read those answers to understand how it works.

Java is giving me an error of "java.io.ioexception is never thrown in body of corresponding try statement"

So I am making a program that renders pictures from .ppm files. I have got another version working but have now moved on to the other part which is reading multiple images from the same document and to basically use this to animate it with a small delay inbetween switching pictures, and then the following error has come up and am completely stumped by it:
java.io.ioexception is never thrown in body of corresponding try statement
Any help would be much appreciated.
public void renderAnimatedImage(){
String image = UI.askString("Filename: ");
int keepingCount =0; //Variables
int numCount = 1;
try{
Scanner fileScan = new Scanner(image); // making scanners
Scanner scan = new Scanner(image);
File myFile = new File(image); //making files
File myFile2 = new File(image);
int num = 0;
while(scan.hasNextLine()){
String Line = scan.nextLine();
Scanner keywordSc = new Scanner (Line);
while(keywordSc.hasNext()) {
String Keyword = keywordSc.next();
if (Keyword.equals("P3")) {
num++;
}
else { break; }
}
}
while (keepingCount< numCount) {
this.renderImageHelper(scan); // calling upon an earlier method which works.
keepingCount++;
}
}
catch(IOException e) {UI.printf("File failure %s \n", e); }
}
It means the code you're writing inside your try/catch is never throwing an IOException, which makes the clause unnecessary. You can just remove it and keep your code without it.
I bet that you think there could be an IOException because of this line:
Scanner fileScan = new Scanner(image); // making scanners
But that line is not doing what you think it does. Since image is a String this will use the Scanner(String) constructor. But that constructor treats its argument as a string to be scanned, not the name of a file to be scanned.
Hence new Scanner(image) is not doing any I/O and is not declared as throwing an IOException.
And the rest of the code in the block won't throw IOException either. The Scanner next / hasNext methods that you are using will throw a different exception if there is an I/O error while reading. (Check the javadocs.)
Also, you seem to be misunderstanding what File is / does.
File myFile = new File(image); //making files
The comment is incorrect. That does not make a file.
Actually, it makes a File object which is an in-memory representation of a filename / pathname. Creating a File object doesn't cause a file to be created in the file system. (Again, check the javadocs.)

Cannot get PrintWriter to replace text in file

I am trying to complete a simple program that uses the command line to replace a specified String in a file. Command line entry would be java ReplaceText textToReplace filename
The code completes, but the file does not replace the specified string. I have Googled similar situations but I cannot figure out why my code is not working.
import java.io.*;
import java.util.*;
public class ReplaceText{
public static void main(String[] args)throws IOException{
if(args.length != 2){
System.out.println("Incorrect format. Use java ClassName textToReplace filename");
System.exit(1);
}
File source = new File(args[1]);
if(!source.exists()){
System.out.println("Source file " + args[1] + " does not exist.");
System.exit(2);
}
File temp = new File("temp.txt");
try(
Scanner input = new Scanner(source);
PrintWriter output = new PrintWriter(temp);
){
while(input.hasNext()){
String s1 = input.nextLine();
String s2 = s1.replace(args[0], "a");
output.println(s2);
}
temp.renameTo(source);
source.delete();
}
}
}
Edit: edited the code so I am not reading and writing to the file at the same time, but it still does not work.
First of all you have a problem with your logic. You are renaming your temporary file then immediately deleting it. Delete the old one first, then rename the temporary file.
Another problem is that you are attempting to do perform the delete and rename within your try block:
try(
Scanner input = new Scanner(source);
PrintWriter output = new PrintWriter(temp);
){
...
temp.renameTo(source);
source.delete();
}
Your streams are not automatically closed until the try block ends. You will not be able to rename or delete while the stream is open. Both delete and renameTo return a boolean to indicate whether they were successful so it may be prudent to check those values.
Correct code may look something like:
try(
Scanner input = new Scanner(source);
PrintWriter output = new PrintWriter(temp);
){
while(...)
{
...
}
}
// Try block finished, resources now auto-closed
if (!source.delete())
{
throw new RuntimeException("Couldn't delete file!");
}
if (!temp.renameTo(source))
{
throw new RuntimeException("Couldn't rename file!");
}
You can't replace strings a file in general. You need to read the input line by line, replace each line as necessary, and write each line to a new file. Then delete the old file and rename the new one.

Reading from arguments files to process

I'm having some trouble reading in a file from the command line.
I've never used command line arguments before so I guess I'm a little lost.
Here's what I'm trying so far:
FileInputStream fin1 = null;
for (int i = 0; i < args.length; i++) //command line argument for file input
{
fin1 = new FileInputStream(args[i]);
}
//Scanner scan = new Scanner(fiin1);
I've commented out my scanner because I'm using a different method (into which I'm passing in fin1 as a parameter) and that method has a scanner in it. However, I'm not too sure if I still need the scanner there (maybe to pass into the other method as a param).
Anyway, if I run my code, I get a NullPointerException, which I assume comes from the fact that I initialized my FileInputStream as null. But if I'm changing it in the for loop, why does that matter?
Also, I need to keep my main method the way it is so I can do more in it.
Can anyone help?
Notice that it is called FileInputStream , and so we need to be using a File .
You can simply use a Scanner , and set it to System.in :
Scanner scanner = new Scanner(System.in);
And then afterwards, you can initialize that FileInputStream
How to Read Strings from Scanner in console Application JAVA?
Use following code.
if (args.length < 1) {
System.out.println("No file was given as an argument..!");
System.exit(1);
}
String fileName = args[0];
Scanner scanner = new Scanner(new File(fileName));
if you want to use a FileInputStream then change the last line to create a FileInputStream instance.
fin1 = new FileInputStream(fileName);
No need to use a for-loop if you are giving only one filename as the argument. You can run your code as follow.
javac MyClass.java //Compile your code(Assumed that your file is MyClass.java
java MyClass filename //Change filename with the path to your file
You are getting NullPointerException probably because you are not using filename as a argument when you run your java code.
First of all : when you run your code, you'll reach only the last argument.
You should do like this:
FileInputStream fileInputStream = null;
for (String argument : args) {
fileInputStream = new FileInputStream(argument);
//you should process your argument in block together with creating fis
Scanner scanner = new Scanner(fileInputStream);
//now, when a scanner copy is created, you can use it (or you can use your own
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
}

Read an instruction line by line java

I have a set of instructions in a text file:
LoadA 0
LoadB 1
Add
Store 0
LoadA 2
etc...
I know I can use Scanner and hasNextLine but not sure how to implement this and have the instructions read and understood.
As much as the people above would like you to do this on your own I will answer this question because I remember how difficult it was to learn. As long as you learn from the and don't just copy them this should be useful.
Scanner sc = new Scanner(System.in); //read from the System.in
while (sc.hasNextLine()) { //this will continue to itterate until it runs out
String[] x = sc.nextLine().split(" ");
//this takes your input and puts it into a string array where there is a
//space e.g. ["LoadA", "0"]
}
I hope this helps. You are still required to solve the problem. You now have the ability to get the content now. Good luck.
Scanner inFile = null;
try
{
// Create a scanner to read the file, file name is parameter
inFile = new Scanner (new File("whatever.txt"));
}
catch (FileNotFoundException e)
{
System.out.println ("File not found!");
// Stop program if no file found
System.exit (0);
}
then,
while(inFile.hasNextLine()){
(some variable) = inFile.nextLine();
(do something to that variable);
}
if this doesn't solve the question, I would recommend taking a look at http://www.cs.swarthmore.edu/~newhall/unixhelp/Java_files.html

Categories