java.io.FileNotFoundException on one computer but not another [long post] - java

I'm working on a mod to generate random plants in Unreal World. I posted the initial version of the mod on the game's forum, and I've been told about an issue with the Windows version of the mod. The problem is specifically with the name generation; it just returns null for each name. The user who reported this problem to me posted this stacktrace (it's the same error repeated several times; no need to read them all):
This is the method where the error is occurring:
private static String getName(Random rn, boolean full) {
try {
String name;
int prefix = rn.nextInt(179);
int suffix = rn.nextInt(72);
Scanner sc1 = new Scanner(new File("srcwin\\Prefixes.txt")); // error occurs on this line
for (int i=0; i<prefix; i++) {
sc1.nextLine();
}
name = sc1.next();
if (name.contains("'")) {
name += " ";
}
if (full || rn.nextInt(3) == 0) {
if (rn.nextInt(3) == 0 && !name.contains(" ")) {
name += " ";
}
Scanner sc2 = new Scanner(new File("srcwin\\Suffixes.txt"));
for (int i=0; i<suffix; i++) {
sc2.nextLine();
}
name += sc2.next();
}
return name;
} catch (FileNotFoundException ex) {
Logger.getLogger(UrWPlantMod.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
This program is contained in a JAR containing the directories modwin, srcwin, and META-INF. The class files are contained in modwin, while the source code and txt files are contained in srcwin. The user who reported this problem is running Windows 10 Home (Version 1511, Build 10586). Another user, running Windows 8.1 (no other specifics given), can run this just fine, with no FileNotFoundExceptions or null names.
If it's relevant, I am running Ubuntu 14.04, with the only difference in this code being that the file path is src/Prefixes.txt instead of srcwin\\Prefixes.txt, and it runs just fine for me.
If you'd like to see the other lines of code mentioned in the stacktrace:
berries[i] = new Plant(getName(rn, false) + "berry " + getBerryName(rn), rn.nextInt(4)+1, getImg(rn, "berry"));
and
createBerries(rn); // the above line of code is in the method called here

new Scanner(new File("srcwin\\Prefixes.txt")) will open the file srcwin\Prefixes.txt from the current directory.
Directories inside a Jar file cannot be access this way.
So, either the current directory is not what you think it is, or the files are not there (in folder srcwin on the file system).
To load content of a file inside your Jar (which is on the classpath, we presume), use getResourceAsStream().
try (Scanner sc1 = new Scanner(MyClass.class.getResourceAsStream("/srcwin/Prefixes.txt"))) {
// code here
}
Note the change to the file name. It starts with / and uses /.
Also note that you should always close the Scanner when done with it (except when used with System.in), hence the try-with-resources block.

Related

JOptionPanel.showMessageDialog doesn't show up when program is run through the .jar file

I did a little bit of searching around for the answer to my question, but didn't find anything that quite matched mine, maybe I didn't search hard enough, but I'm new to this site.
So I use NetBeans IDE 8.0.2, and when I run my program through the IDE, everything works fine. But when I run it through its Executable Jar file, I get the first 2 input boxes, but the final alert doesn't come up.
The program simply takes in 2 names (player) from input, then assigns each one a team to use in Fifa, taken from an external list called, "teams.txt". I made it for me and my roommates to use when we play Fifa 19 and we want to use random teams, but don't want to get stuck with a 1-2 star team.
public class Main {
public static void main(String[] args) {
List<String> teams = new ArrayList<>();
// Read file, then store each new line item in the ArrayList.
try {
Scanner s = new Scanner(new File("teams.txt"));
while (s.hasNext()) {
teams.add(s.nextLine());
}
} catch (FileNotFoundException ex) {
System.out.println("File Not Found");
}
// Take user input from dialog box and store it in variables player1 and player2.
String player1 = JOptionPane.showInputDialog("Player 1: Enter your name.");
String player2 = JOptionPane.showInputDialog("Player 2: Enter your name.");
//Print the values given in the Java console.
System.out.println("Player 1: " + player1);
System.out.println("Player 2: " + player2);
// Random team generator within dialog box.
Random r = new Random();
String msg1 = player1 + ": " + teams.get(r.nextInt(teams.size()));
String msg2 = player2 + ": " + teams.get(r.nextInt(teams.size()));
Component frame = null;
ImageIcon icon = new ImageIcon("icon2.png");
JOptionPane.showMessageDialog(frame, msg1 + "\n" + msg2, "Fifa Team Picker", PLAIN_MESSAGE, icon);
}
}
You cannot read individual .jar file entries as files, because they are not separate files. They are just subsequences of bytes indicating compressed data. This means your Scanner is failing, and your teams collection is empty, which in turn causes teams.get to throw an exception.
If you run the .jar file on the command line, you can see this for yourself. Such a command typically looks like: java -jar myteamsproject.jar
A file that is part of your application is called a resource. You must read it with the getResource or getResourceAsStream method of Class:
Scanner s = new Scanner(Main.class.getResourceAsStream("teams.txt"));
Similarly, you must pass a resource as a URL to ImageIcon, rather than a filename:
ImageIcon icon = new ImageIcon(Main.class.getResource("icon2.png"));
Of course, the above lines will not work unless teams.txt and icon2.png are actually in the .jar file. When the .jar file is built, you should examine its contents and verify that those entries are present.

.jar not running when passed valid file in args

I am building an application that takes input through an XML file and executes a number of operations based on it. I know the application works, because I can supply a file for an XML directly in code and it will run as it should.
The problem arises when I try to pass the path to an XML file in through the commandline args of the packaged .jar.
My main looks like this:
public static void main(String[] args) {
LogWriter.openWriter();
LogWriter.log("Main start.");
Controller controller = new Controller();
LogWriter.log("Controller created.");
List<Parameters> parameters = new ArrayList<Parameters>();
for (int i = 0; i < args.length; i++) {
LogWriter.log("Got arg: " + args[i]);
File file = new File(args[i]);
LogWriter.log("Parameter file: " + file.getAbsolutePath());
if (file.exists()) {
LogWriter.log("File exists. Getting parameters.");
Parameters para = controller.getParameters(file);
LogWriter.log("Attempting to add parameters.");
parameters.add(para);
LogWriter.log("Added parameters.");
} else {
LogWriter.log("File is not valid.");
}
}
}
The script I use to run it looks like this:
java -jar PDFRedacter.jar C:\Users\je\Downloads\XMLConfig.xml
What is really strange about is, is that it only fails when I give it a valid file. If I supply an invalid file, it runs, and logs that the file is invalid, and as mentioned it also runs if I input a valid file directly in the code.
However, with a valid path written in the batch, not even the first 'Main start' is logged, so the code does not run at all. Is this perhaps some access problem?
EDIT: The logger is not my issue, it works as intended both with and without a valid file. Example of 'Invalid file' log:
Main start.
Controller created.
Got arg: C:\Users\je\Downloads\XMLConfig
Parameter file: C:\Users\je\Downloads\XMLConfig
File is not valid.
To clarify, the issue is not actually reading a file. The issue is, that when I supply a valid file through the batch script, it seems like my code doesn't run at all.
FINAL EDIT:
It turns out the problem was simply with the packaging of my .jar, lacking a dependecy. As someone else suggested, my logger was only flushing at the very end of excecution, and that's why it didn't write anything. Thanks for your comments.
As Thomas suspected, there must be another reason for the program to fail, because your function should work. If you reduce it to detecting if a file exists and once you made shure it works, add the parameter list, controller and logger one after another you may find the reason for the failure.ยด
Here is the example I tested - and it works perfectly for all existing files or directories.
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println("Got arg: " + args[i]);
File file = new File(args[i]);
System.out.println("Parameter file: " + file.getAbsolutePath());
if (file.exists()) {
System.out.println("File exists. Getting parameters.");
} else {
System.out.println("File is not valid.");
}
}
}

FileNotFoundException - Reading a text file in java

I'm getting a file not found exception from this code even though it's within the try catch statement and I'm not sure what's wrong, the file is within the project folder and is called 'someFile.txt'. This is the main method:
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("no arguments given");
return;
}
double FRE = sortFile(args[0]);
System.out.println("Readability of file " + args[0] + "= " + FRE);
}
And this is the sortFile method where the exception occurs:
public static double sortFile(String FileName) {
int nWords = 0;
int nSyllables = 0;
int nSentences = 0;
File text = new File(FileName);
try {
Scanner sc = new Scanner(text);
while (sc.hasNext()) {
contents.add(sc.next());
++nWords;
}
sc.close();
for (String e : contents) {
getNumSyllables(e);
}
} catch (FileNotFoundException e) {
System.out.println("The file" + FileName + "could not be opened.");
e.printStackTrace();
}
double FRE = getFRE(nWords, nSyllables, nSentences);
return FRE;
}
Thanks for any help :)
well, the file does not exist in that location. Try to add
System.out.println(text.getAbsolutePath())
to see where the file is expected. Note, when you provide a relative path (e.g. some/path/filename.ext), this is relative to the working directory. The working directory is the folder your java program is started in.
If you're using an IDE (e.g. Eclipse, IntelliJ, Netbeans) you can define the working directory in your run configuration.
See:
Javadoc of java.io.File to learn how relative paths work inside a Java environment: http://docs.oracle.com/javase/7/docs/api/java/io/File.html
working dir: Getting the Current Working Directory in Java
I'm getting a file not found exception from this code even though it's
within the try catch statement
The try-catch does not prevent the Exception from being thrown. It merely executes the code in the catch block when an Exception is thrown, and you are just printing the stack trace in the catch block, which is what usually printed anyways on uncaught exceptions.
To resolve your actual issue, first try passing the full path to the file, verify that it works and then use Tim's answer to debug your absolute path.
Try launching your program with the absolute path.
java yourclassname absolutepath_to_someFile.txt

Why is my program catching / throwing a FileNotFoundException when the file exists?

Java newbie here!
I'm writing a program to practice reading input and writing output to files. I've finished coding the program, but when I run it, the program just catches and proceeds with a FileNotFoundException.
The file is in the source folder for the program, and I've even tried placing it in every folder related to the program. I've tried:
Declaring the exceptions in the method header
Surrounding the section-in-question with a try/catch block.
Both of the above together.
Here's the relevant code that is causing problems. Is there something that sticks out that I'm missing?
public static void main(String[] args) throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
String playerHighestScore = "", playerLowestScore = "";
int numPlayers = 0, scoreHighest = 0, scoreLowest = 0;
System.out.println("Enter an input file name: ");
String inputFileName = keyboard.nextLine();
String outputFileName = getOutputFileName(keyboard, inputFileName);
File inputFile = new File(inputFileName);
try {
Scanner reader = new Scanner(inputFile);
reader.close();
}
catch (FileNotFoundException exception) {
System.out.println("There was a problem reading from the file.");
System.exit(0);
}
Scanner reader = new Scanner(inputFile);
PrintWriter writer = new PrintWriter(outputFileName);
The answer is simple. If you get a FilENotFoundException, obviously the reason is File Not Found in the given path.
If you use an IDE, path for the working directory is different from the source directory.
For example, if you are using NetBeans, your source files are inside /src. But your working directory (.) is the project directory.
In the other hand, the problem may be the thing that #Don mentioned. If you are going for a cross platform approach, you can use "/" in paths. It works irrespective to the OS.
Example : String fileName = "C:/Directory/File.txt";
And these paths are case sensitive. So make sure you use the correct case. (It won't be a problem in Windows, until you package the program.)

File.renameTo() doesn't have any effect

I'd like to be able to rename a list of folders in order to remove unwanted characters (a dot and double space have to become a single space, for example).
Upon clicking a button in the Gui, you'll see a messagebox with the correctly formatted name appear which indicates that both the formatting is correct and the function is called.
When I look at the test folders I've created, the names aren't changed (not even after refreshing). Using a hardcoded string doesn't work either.
What am I overlooking?
public void cleanFormat() {
for (int i = 0; i < directories.size(); i++) {
File currentDirectory = directories.get(i);
for (File currentFile : currentDirectory.listFiles()) {
String formattedName = "";
formattedName = currentFile.getName().replace(".", " ");
formattedName = formattedName.replace(" ", " ");
currentFile.renameTo(new File(formattedName));
JOptionPane.showMessageDialog(null, formattedName);
}
}
}
For future browsers: This was fixed with Assylias' comment. Below you will find the eventual code which fixed it.
public void cleanFormat() {
for (int i = 0; i < directories.size(); i++) {
File currentDirectory = directories.get(i);
for (File currentFile : currentDirectory.listFiles()) {
String formattedName = "";
formattedName = currentFile.getName().replace(".", " ");
formattedName = formattedName.replace(" ", " ");
Path source = currentFile.toPath();
try {
Files.move(source, source.resolveSibling(formattedName));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Well, first of all the File.renameTo is trying to rename a file on the same filesystem.
The following is from java doc
Many aspects of the behavior of this method are inherently platform-dependent:
The rename operation might not be able to move a file from one filesystem to
another, it might not be atomic, and it might not succeed if a file with the
destination abstract pathname already exists.
The call to getName() returns just the name of the file and not any directory information. So you may be trying to rename the file to a different directory.
Try adding the containing directory to the file object you pass into rename
currentFile.renameTo(new File(currentDirectory, formattedName));
Also like others have said you should be checking the return value of renameTo which is probably false, or use the new methods in Files class which I've found to throw pretty informative IOExceptions.
First of all check return value, File.renameTo returns true if the renaming succeeded; false otherwise. E.g. you cannot rename / move a file from c: to d: on Windows.
And most importantly, use Java 7's java.nio.file.Files.move instead.

Categories