Currently trying to write a program to take input from a file and store it in an array. However, whenever I try to run the program the file cannot be found (despite file.exists() and file.canRead() returning true).
Here is my code:
public void getData (String fileName) throws FileNotFoundException
{
File file = new File (fileName);
System.out.println(file.exists());
System.out.println(file.canRead());
System.out.println(file.getPath());
Scanner fileScanner = new Scanner (new FileReader (file));
int entryCount = 0; // Store number of entries in file
// Count number of entries in file
while (fileScanner.nextLine() != null)
{
entryCount++;
}
dirArray = new Entry[entryCount]; //Create array large enough for entries
System.out.println(entryCount);
}
public static void main(String[] args)
{
ArrayDirectory testDirectory = new ArrayDirectory();
try
{
testDirectory.getData("c://example.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
(In it's current state the method is only designed to count the number of lines and create the array)
The console output is as follows: true true c:/example.txt
The program seems to throw a 'FileNotFoundException' on the line where the scanner is instantiated.
One thing I have noticed when checking the 'file' object when debugging is although it's 'path' variable has the value "c:\example.txt", it's 'filePath' value is null. Not sure if this is relevant to the issue or not
EDIT: After Brendan Long's answer I have updated the 'catch' block. The stack trace reads as follows:
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at assignment2.ArrayDirectory.getData(ArrayDirectory.java:138)
at assignment2.ArrayDirectory.main(ArrayDirectory.java:193)
Seemingly the scanner doesn't recognize the file and thus can't find the line
This code probably doesn't do what you want:
try
{
testDirectory.getData("c://example.txt");
}
catch (Exception ex)
{
new FileNotFoundException("File not found");
}
If you catch any exception, you run the constructor for a FileNotFoundException and then throw it away. Try doing this:
try
{
testDirectory.getData("c://example.txt");
}
catch (Exception ex)
{
ex.printStackTrace();
}
According to the javadoc for Scanner, nextLine() throws this exception when there is no more input. Your program seems to expect it to return null, but that's now how it works (unlike, say, BufferedReader which does return null at the end of the input). Use hasNextLine to make sure there's another line before using nextLine.
Related
on netbeans, im trying to read a file and display its contents on a swing graphics tab. This is how im reading the file
FileReader reader;
ArrayList<String> file = new ArrayList<String>();
Scanner scan = null;
try
{
reader = new FileReader(filename);
scan = new Scanner(reader);
while(scan.hasNext())
{
file.add(scan.nextLine());
}
return file;
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
scan.close();
}
return null;
This is how I'm writing the file
public String writeFile(ArrayList<String> data)
{
String writer = "";
for (String line : data)
{
writer += (line + lineSeparator);
}
return writer;
}
This is how I'm trying to display it
FileIO file = new FileIO();
String filePath="squeeze.txt";
ArrayList<String> data = file.readFile(filePath);
jTextField1.setText(file.writeFile(data));
And I getting an error on
scan.close();
Your problem here is that scan has not been initialized prior to the try block. Anything in the try block might throw an exception, so therefore you have to write your code assuming that all code in the try block will never be run. Luckily, Java has a syntax just for this situation called try-with-resources. Try-with-resources handles your resources for you, and automatically closes them at the end of the try block. Here is your code, modified to use try-with-resources:
try (FileReader reader = new FileReader(filename);
Scanner scan = new Scanner(reader)) {
while(scan.hasNext()) {
file.add(scan.nextLine());
}
return file;
} catch (IOException e) {
e.printStackTrace();
}
return null;
I also notice that in your catch block, you simply print the stack trace. This is perfectly fine as far as syntax goes, and the compiler will accept it, but I wouldn't recommend swallowing errors like this. If you don't want to do anything special, the best all-purpose line you can use is throw new RuntimeException();. This just throws a generic runtime exception, which will print the stack trace and then terminate the program. This also has the added benefit that you don't need the return null; line at the bottom, since the runtime exception will exit the program anyway, and then any method that calls this method can safely assume that this method returns a non-null value.
jTextField1.setText(file.writeFile(data));
A JTextField is for single lines of text. For multiple lines, use a JTextArea.
As to the problem at hand, the easiest solution is to use methods available to any JTextComponent (which includes both of the above).
Namely JTextComponent.read(Reader,Object) & JTextComponent.write(Writer).
This is my source:
public static void main(String[] args)
{
File file = null;
Scanner scan = null;
Charset cr = null;
Map<String, Charset> map = null;
try
{
file = new File("D:\\Tests\\New folder (2)\\doncho_encode.txt");
map = cr.availableCharsets();
for (Map.Entry<String, Charset> encoding : map.entrySet())
{
String s = encoding.getKey();
scan = new Scanner(file, s);
// System.out.println(s);
}
System.out.println(scan.nextLine());
}
catch (FileNotFoundException | NullPointerException | IllegalArgumentException e)
{
e.printStackTrace();
}
catch (NoSuchElementException e)
{
System.out.println("Try new encoding");
}
finally
{
if (scan != null)
{
scan.close();
}
}
}
I need to compare different charset value to
scan = new Scanner(file, s);
line and when it find correct to use it. In my example I catch "NoSuchElementException" in catch clause.
I understand, that method availableCharsets() returned to me SortedMap with all encodings, but why wen I compare keys to "scan" the exception is caught? How can look like correct iteration?
In my example text in file is with "UTF-16LE" encoding.
(I am not an expert in using java.util.Scanner, but...)
When looking at the Javadoc for the class I can see that:
the constructor doesn't declare throwing NoSuchElementException
but it's the nextLine method which actually does
So based on that, I guess your problem is not actually that the Scanner doesn't recognize a charset returned by availableCharsets. But actually the
program fails to read the next (first) line from the file.
By the way - what I am saying and suggesting for you to focus is most likely better observable if you add e.printStackTrace(); next to your System.out.println("Try new encoding");.
TLDR: I suspect the expection is thrown for a different reason than you think it is.
I am writing a function to take a text file and count how many lines it has while outputting the lines to an array of strings. Doing this I have several exceptions I need to look out for. The class function has several variables that should have a scope throughout the function but when I write a value to the function inside of an exception, the return statement cannot find it. I've moved the declaration around and nothing helps
The value returned "h5Files" "Might not have been initialized" Since I don't know how long the array will be I cannot initialize it to a certain length. I do this within the code and I need a way to tell the return statement that I now have a values
Here is the code
public String[] ReadScanlist(String fileIn){
int i;
String directory ="c:\\data\\"; // "\" is an illegal character
System.out.println(directory);
int linereader = 0;
String h5Files[];
File fileToRead = new File(directory + fileIn);
System.out.println(fileToRead);
try {
FileInputStream fin = new FileInputStream(fileToRead); // open this file
}
catch(FileNotFoundException exc) {
System.out.println("File Not Found");
}
try{
//read bytes until EOF is detected
do {
FileReader fr = new FileReader(fileToRead);// Need to convert to reader
LineNumberReader lineToRead = new LineNumberReader(fr); // Use line number reader class
//
while (lineToRead.readLine() != null){
linereader++;
}
linereader = 0;
lineToRead.setLineNumber(0); //reset line number
h5Files = new String[linereader];
while (lineToRead.readLine() != null){
h5Files[linereader] = lineToRead.readLine(); // deposit string into array
linereader++;
}
return h5Files;
}
while(i !=-1); // When i = -1 the end of the file has been reached
}
catch(IOException exc) {
System.out.println("Error reading file.");
}
try{
FileInputStream fin = new FileInputStream(fileToRead);
fin.close(); // close the file
}
catch(IOException exc) {
System.out.println("Error Closing File");
}
return h5Files;
}
Your code is very very odd. For example these two blocks make no sense:
try {
FileInputStream fin = new FileInputStream(fileToRead); // open this file
}
catch(FileNotFoundException exc) {
System.out.println("File Not Found");
}
try{
FileInputStream fin = new FileInputStream(fileToRead);
fin.close(); // close the file
}
catch(IOException exc) {
System.out.println("Error Closing File");
}
I don't know what you think they do, but besides the first one leaking memory, they do nothing at all. The comments are more worrying, they suggest that you need to do more reading on IO in Java.
Deleting those blocks and tidying the code a (moving declarations, formatting) gives this:
public String[] ReadScanlist(String fileIn) {
String directory = "c:\\data\\";
String h5Files[];
File fileToRead = new File(directory + fileIn);
try {
int i = 0;
do {
FileReader fr = new FileReader(fileToRead);
LineNumberReader lineToRead = new LineNumberReader(fr);
int linereader = 0;
while (lineToRead.readLine() != null) {
linereader++;
}
linereader = 0;
lineToRead.setLineNumber(0);
h5Files = new String[linereader];
while (lineToRead.readLine() != null) {
h5Files[linereader] = lineToRead.readLine();
linereader++;
}
return h5Files;
} while (i != -1);
} catch (IOException exc) {
System.out.println("Error reading file.");
}
return h5Files;
}
My first bone of contention is the File related code. First, File abstracts from the underlying OS, so using / is absolutely fine. Second, there is a reason File has a File, String constructor, this code should read:
File directory = new File("c:/data");
File fileToRead = new File(directory, fileIn);
But it should really be using the new Path API anyway (see below).
So, you declare h5Files[]. You then proceed to read the whole file to count the lines. You then assign h5Files[] to an array of the correct size. Finally you fill the array.
If you have an error anywhere before you assign h5Files[] you have not initialised it and therefore cannot return it. This is what the compiler is telling you.
I don't know what i does in this code, it is assigned to 0 at the top and then never reassigned. This is an infinite loop.
So, you need to rethink your logic. I would recommend throwing an IOException if you cannot read the file. Never return null - this is an anti-pattern and leads to all those thousands of null checks in your code. If you never return null you will never have to check for it.
May I suggest the following alternative code:
If you are on Java 7:
public String[] ReadScanlist(String fileIn) throws IOException {
final Path root = Paths.get("C:/data");
final List<String> lines = Files.readAllLines(root.resolve(fileIn), StandardCharsets.UTF_8);
return lines.toArray(new String[lines.size()]);
}
Or, if you have Java 8:
public String[] ReadScanlist(String fileIn) throws IOException {
final Path root = Paths.get("C:/data");
try (final Stream<String> lines = Files.lines(root.resolve(fileIn), StandardCharsets.UTF_8)) {
return lines.toArray(String[]::new);
}
}
Since I don't know how long the array will be I cannot initialize it
to a certain length.
I don't think an array is the correct solution for you then - not to say it can't be done, but you would be re-inventing the wheel.
I would suggest you use a LinkedList instead, something like:
LinkedList<String> h5Files = new LinkedList<>();
h5Files.add(lineToRead.readLine());
Alternatively you could re-invent the wheel by setting the array to an arbritary value, say 10, and then re-size it whenever it gets full, something like this:
h5Files = new String[10];
if (linereader = h5Files.size())
{
String[] temp = h5Files;
h5Files = new String[2 * linereader];
for (int i = 0; i < linereader; i++)
{
h5Files[i] = temp[i];
}
}
Either one of these solutions would allow you to initialize the array (or array alternative) in a safe constructor, prior to your try block, such that you can access it if any exceptions are thrown
Here is your problem. Please take a look on digested version of your code with my comments.
String h5Files[]; // here you define the variable. It still is not initialized.
try{
..................
do {
h5Files = new String[linereader]; // here you initialize the variable
} while(i !=-1); // When i = -1 the end of the file has been reached
..................
catch(IOException exc) {
// if you are here the variable is still not initialized
System.out.println("Error reading file.");
}
// you continue reading file even if exception was thrown while opening the file
I think that now the problem is clearer. You try to open the file and count lines. If you succeed you create array. If not (i.e. when exception is thrown) you catch the exception but still continue reading the file. But in this case you array is not initialized.
Now how to fix this?
Actually if you failed to read the file first time you cannot continue. This may happen for example if file does not exist. So, you should either return when first exception is thrown or just do not catch it at all. Indeed there is nothing to do with the file if exception was thrown at any phase. Exception is not return code. This is the reason that exceptions exist.
So, just do not catch exceptions at all. Declare your method as throws IOException and remove all try/catch blocks.
I think it's easier to just show the code and the output I'm getting than trying to explain it :)
This is from my main method:
//prompt user for filename
System.out.println("Please enter the text file name. (Example: file.txt):");
String filename = ""; //will be used to hold filename
//loop until user enters valid file name
valid = false;
while(!valid)
{
filename = in.next();
try
{
reader.checkIfValid(filename);
valid = true; //file exists and contains text
}
catch (Exception e)
{
System.out.println(e + "\nPlease try again.");
}
}
And this is the reader.checkIfValid method:
public void checkIfValid(String filename) throws InvalidFileException, FileNotFoundException
{
try
{
in = new Scanner(new File(filename));
if (!in.hasNextLine()) // can't read first line
throw new InvalidFileException("File contains no readable text.");
}
finally
{
in.close();
}
}
This is the output I get when a nonexistent file is entered:
Please enter the text file name. (Example: file.txt):
doesNotExist.txt
java.lang.NullPointerException
Please try again.
Why is the System.out.println(e) getting a NullPointerException? When I enter an empty file or a file with text, it works just fine. The empty file prints the InvalidFileException (a custom exception) message.
When I put a try-catch statement around the "in = new Scanner(new File(filename));", and have the catch block display the exception, I do get the FileNotFoundException printed out, followed by the NullPointerException (I'm not entirely sure why the catch block in the main method would be activated if the exception was already caught in the checkIfValid method...).
I've spent a while on this and I'm completely clueless as to what's wrong. Any help would be appreciated. Thanks!
edited: I think the null pointer comes from the call to reader, it is poor practise to catch all exceptions as you no longer know where they came from!
Maybe the checkIfValid method should just check if the filename is valid?
public boolean checkIfValid(String filename) {
try {
File file = new File(filename);
return file.exists();
} catch (FileNotFoundException) {
System.out.println("Invalid filename ["+filename+"] "+e);
}
}
Then the code calling it could look like;
filename = in.next();
valid = reader.checkIfValid(filename);
if (valid)
List<String> fileContents = readFromFile(filename);
Then contain all the file reading logic in it's own method like this;
public List<String> readFromFile(filename) {
List<String> fileContents = new ArrayList<String>();
try {
in = new Scanner(new File(filename));
while (in.hasNextLine()) {
fileContents.add(in.nextLine);
}
} catch (IOException e){
//do something with the exception
} finally {
in.close();
}
return fileContents;
}
My mistake was something only I could've seen. I was catching all the exceptions so I wasn't able to see where it was coming from. Thank you for helping!
public static Scanner getFileScanner()
{
try{
Scanner input = new Scanner(System.in);
String file = input.nextLine();
Scanner fs = new Scanner(new FileReader(file));
}catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
getFileScanner();
}finally{
return fs;
}
}
I keep getting the error that the variable fs isn't found. I can't figure out why for the life of me.
Your fs is declared under try block... to fix this, declare it outside the block:-
Scanner fs = null;
try {
...
fs = new Scanner(new FileReader(file));
}
catch (FileNotFoundException fe) {
...
}
finally {
return fs;
}
Variables declared inside a try block are not in scope inside the corresponding finally block. There are a number of issues with your approach in general... it's generally not a good idea to return inside a finally block, for example.
Here's what I'd do:
public static Scanner getFileScanner() {
Scanner input = new Scanner(System.in);
File file = null;
while (true) {
file = new File(input.nextLine());
if (file.exists() && file.isFile())
break;
System.out.println("Invalid filename. Try another:");
}
return new Scanner(new FileReader(file));
}
Lets start by listing the problems in your code:
The compilation error on the return statement is caused by fs being out of scope as described in other answers.
When you make the recursive call to getFileScanner(), you don't assign or return the result. So it won't make it back to the caller.
Using a return in a finally block is a bad idea. It will squash (throw away) any other exceptions that might be propagating at that point; e.g. exceptions that don't match a catch or exceptions thrown in a catch block.
The input.nextLine() call will throw an exception if the underlying stream has reached the EOF; e.g. the user typed [CONTROL]+D or whatever. You don't have to catch it (it is unchecked), but the return in the finally block squashes it (probably) resulting in the caller getting a null instead. Ughh ...
Hard-wiring System.in and System.out makes your method less reusable. (OK, this may not be an issue you should address in this particular case. And I won't, below ...)
In theory, your method could be made to throw a StackOverflowError; e.g. if the user hits [ENTER] a number of times. This problem is inherent in your recursive solution, and is a good reason not to do it that way.
Finally, here's a version of the method that addresses these problems:
public static Scanner getFileScanner() throws NoSuchElementException
{
Scanner input = new Scanner(System.in);
while (true) {
String file = input.nextLine();
try {
return new Scanner(new FileReader(file));
} catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
}
}
}
Note that I've replaced the recursion, gotten rid of the finally, and declared the exception that is thrown. (One could catch that exception and either report it, or rethrow it as an application specific exception.)
You declared fs in the try block and try to access it in a different scope (the finally block). The usual paradigms is to declare fs before the try block as null.
Declare it first:
public static Scanner getFileScanner() {
Scanner input = new Scanner(System.in);
Scanner fs = null;
while(fs == null) {
try{
String file = input.nextLine();
Scanner fs = new Scanner(new File(file));
}catch (FileNotFoundException fe) {
System.out.println("Invalid filename. Try another:");
}
}
return fs;
}
Just to expand on what the other guys indicated with their code samples...
Because you declare the fs variable within the try block the variable will only be scoped (visible) within the braces immediately after the try keyword.
By moving the fs variable declaration out of the try block and into the getFileScanner method body you are ensuring that the variable can be accessed by all blocks within the method body (try, catch and finally blocks).
Hope that helps!