I have an assignment and we have a couple of classes given, one of them is a filereader class, which has a method to read files and it is called with a parameter (String) containing the file path, now i have a couple of .txt files and they're in the same folder as the .java files so i thought i could just pass along file.txt as filepath (like in php, relatively) but that always returns an file not found exception!
Seen the fact that the given class should be working correctly and that i verified that the classes are really in the same folder workspace/src as the .java files i must be doing something wrong with the filepath String, but what?
This is my code:
private static final String fileF = "File.txt";
private static final ArrayList<String[]> instructionsF =
CreatureReader.readInstructions(fileF);
Put this:
File here = new File(".");
System.out.println(here.getAbsolutePath());
somewhere in your code. It will print out the current directory of your program.
Then, simply put the file there, or change the filepath.
Two things to notice:
check if "File.txt" is really named like that, since it won't find "file.txt" -> case sensitivity matters!
your file won't be found if you use relative filenames (without entire directory) and it isn't on your classpath -> try to put it where your .class files are generated
So: if you've got a file named /home/javatest/File.txt, you have your source code in /home/javatest/ and your .class files in that same directory, your code should work fine.
If you class is in package and you have placed the files as siblings then your path must include the package path. As suggested in other answers, print out the path of the working directory to determine where Java is looking for the file relative from.
Related
So I have a project, and this is one of the demands:
You should have a class named Project3, containing a main method.
This program reads the levels information from a file whose name is
specified as a command-line parameter (The file should also be
relative to the class-path as described here:)
All the file names specified in the levels and block definition files
should be relative to the class path. The reason we want them to be
relative to the class path is that later we will be able to read the
files from inside a jar, something we can not do with regular File
references.
To get an input stream relative to the class path (even if it's inside
a jar), use the following:
InputStream is =
ClassLoader.getSystemClassLoader().getResourceAsStream("image.png");
The idea is to keep a folder with files(definitions and images) and
then add that folder to the class path when running the JVM:
java -cp bin:resources ... If you don't add the resources folder to
you class path you wont be able to load them with the command from
above.
When run without parameters, your program should read a default level
file, and run the game accordingly. The location of the default level
file should be hard-coded in your code, and be relative to the
classpath_.
When run without parameters, your program should read a default level file, and run the game accordingly. The location of the default level file should be hard-coded in your code, and be relative to the classpath_.
The part of the code that handles the input is:
public Void run() throws IOException {
LevelReader level = new LevelReader();
List<level> chosenLevels = new ArrayList<>();
if (args.length >= 1) {
File f = new File(args[0]);
if (f.exists()) {
chosenLevels = level.makeLevel(args[0]);
}
}
if (chosenLevels.size() == 0) {
game.runLevels(defaultLevels);
} else {
game.runLevels(chosenLevels);
}
return null;
}
So my question is:
An argument should be the full path of a file which means:
D:\desktop\level3.txt
Is it possible to read a file from every location on my computer?
Because right now I can do it only if my text file is in the
project's directory (not even in the src folder).
I can't understand the rest of their demands. What does is mean "should be hard-coded in your code, and be relative to the
classpath_." and why is it related to InputStream method(?)
I'm confused all over this.
Thanks.
A classpath resource is not the same as a file.
As you have correctly stated, the full path of a file is something like D:\desktop\level3.txt.
But if ever want to distribute your application so it can run on other computers, which probably won’t have that file in that location, you have two choices:
Ask the user to tell the program where to find the file on their computer.
Bundle the file with the compiled program.
If you place a non-.class file in the same place as .class files, it’s considered a resource. Since you don’t know at runtime where your program’s class files are located,¹ you use the getResource or getResourceAsStream method, which is specifically designed to look in the classpath.
The getResource* methods have the additional benefit that they will work both when you are developing, and when the program is packaged as a .jar file. Individual entries in a .jar file are not separate files and cannot be read using the File or FileInputStream classes.
If I understand your assignment correctly, the default level file should be an application resource, and the name of that resource is what should be hard-coded in your program. Something like:
InputStream is;
if (args.length > 0) {
is = new BufferedInputStream(
new FileInputStream(args[0]));
} else {
// No argument provided, so use program's default level data.
is = ClassLoader.getSystemClassLoader().getResourceAsStream("defaultlevel.txt");
}
chosenLevels = level.makeLevel(is);
¹ You may find some pages that claim you can determine the location of a running program’s code using getProtectionDomain().getCodeSource(), but getCodeSource() may return null, depending on the JVM and ClassLoader implementation, so this is not reliable.
To answer your first question, it doesn't seem like they're asking you to read from anywhere on disk, just from within your class path. So that seems fine.
The second question, "What does is mean 'should be hard-coded in your code, and be relative to the classpath'?". You are always going to have a default level file in your project directory. Define the path to this file as a String in your program and that requirement will be satisfied. It's related to the InputStream because the stream requires a location to read in from.
The following code file.renameTo(new File(newPath)); dosen't rename all the files properly it skips over some I have even used Files.move(file.toPath(), Paths.get(newPath)); but i get an exception error in eclipse saying java.nio.file.FileAlreadyExistsException which i think is occurring because there are sets of files that when they are cut off they will have the same name is there a way to bypass this error in eclipse or fine tune the renameTo()?
I also have tried .substring(0,22);, name.replaceFirst("-2017.*", ""); and
name.substring(0, file.getName().indexOf("-2017") same result.
example:
orginal file name: 3-M-ALABAMA-SUIQUARTER2-2017200346-CD6140
Console Output: 3-M-ALABAMA-SUIQUARTER2
some of Files in folder unchanged: 3-M-ALABAMA-SUIQUARTER2-2017200346-CD6140
for(File file:filesInDir) {
String name = file.getName().substring(0, file.getName().indexOf("-2017"));
String newName = name;
System.out.println(newName); // prints prints to file
String newPath = absolutePathOne + "\\" + newName;
file.renameTo(new File(newPath));
or
Files.move(file.toPath(), Paths.get(newPath));
You can not rename a particular file to a file name that already exists within the folder you are renaming the file in. IMHO ... Even if you can, you shouldn't for a bunch of common sense reasons.
In other words, if we have a folder (directory) named: All_My_Files and in this folder we have two text files, one is named MyFile-2016.txt and the other is named MyFile-2017.txt. Now, we want to rename each of these two files so that the dash and the year (ie: -2016 or -2017) from each file name no longer exists. Essentially what you will end up trying to do is have both file names be MyFile.txt which is not allowed. Your first rename will be fine since on the first go at it there is no file within the folder named MyFile.txt but once the second rename attempt is done on the second file name it's simply going to fail since the name MyFile.txt already exists within that folder which was done from the first rename attempt. This not a code problem, this is an issue with the local file system. Those are the rules of the local file system (No file can have the same name within the same folder). Look at the file names you are going to rename, are there any that will actually create the very same file name once you remove the unwanted text? If there are then those will fail to rename.
The same applies to Moving files. You can not move a file to a folder (directory) that already contains a file with the very same name. The file system rule above applies. You can however overwrite the existing duplicate file name within the destination path if it exists during a move if you tell the Files.move() method to do so:
Files.move(sourcePathAndFileName, destinationPathAndFileName,
StandardCopyOption.REPLACE_EXISTING);
You will need to import:
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
Keep in mind though, before you blatantly overwrite an existing file you better make pretty sure that this is what you want to do. Prompting the User to carry out an overwrite would be a normal course of action but doesn't necessarily need to be the case for specific in house operations.
I have a file named "word.txt".
It is in the same directory as my java file.
But when I try to access it in the following code this file not found error occurs:
Exception in thread "main" java.io.FileNotFoundException: word.txt
(The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.util.Scanner.<init>(Unknown Source)
at Hangman1.main(Hangman1.java:6)
Here's my code:
import java.io.File;
import java.util.*;
public class Hangman1 {
public static void main(String[] args) throws Exception {
Scanner input = new Scanner(new File("word.txt"));
String in = "";
in = input.nextLine();
}
}
Put the word.txt directly as a child of the project root folder and a peer of src
Project_Root
src
word.txt
Disclaimer: I'd like to explain why this works for this particular case and why it may not work for others.
Why it works:
When you use File or any of the other FileXxx variants, you are looking for a file on the file system relative to the "working directory". The working directory, can be described as this:
When you run from the command line
C:\EclipseWorkspace\ProjectRoot\bin > java com.mypackage.Hangman1
the working directory is C:\EclipseWorkspace\ProjectRoot\bin. With your IDE (at least all the ones I've worked with), the working directory is the ProjectRoot. So when the file is in the ProjectRoot, then using just the file name as the relative path is valid, because it is at the root of the working directory.
Similarly, if this was your project structure ProjectRoot\src\word.txt, then the path "src/word.txt" would be valid.
Why it May not Work
For one, the working directory could always change. For instance, running the code from the command line like in the example above, the working directory is the bin. So in this case it will fail, as there is not bin\word.txt
Secondly, if you were to export this project into a jar, and the file was configured to be included in the jar, it would also fail, as the path will no longer be valid either.
That being said, you need to determine if the file is to be an embedded-resource (or just "resource" - terms which sometimes I'll use interchangeably). If so, then you will want to build the file into the classpath, and access it via an URL. First thing you would need to do (in this particular) case is make sure that the file get built into the classpath. With the file in the project root, you must configure the build to include the file. But if you put the file in the src or in some directory below, then the default build should put it into the class path.
You can access classpath resource in a number of ways. You can make use of the Class class, which has getResourceXxx method, from which you use to obtain classpath resources.
For example, if you changed your project structure to ProjectRoot\src\resources\word.txt, you could use this:
InputStream is = Hangman1.class.getResourceAsStream("/resources/word.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
getResourceAsStream returns an InputStream, but obtains an URL under the hood. Alternatively, you could get an URL if that's what you need. getResource() will return an URL
For Maven users, where the directory structure is like src/main/resources, the contents of the resources folder is put at the root of the classpath. So if you have a file in there, then you would only use getResourceAsStream("/thefile.txt")
Relative paths can be used, but they can be tricky. The best solution is to know where your files are being saved, that is, print the folder:
import java.io.File;
import java.util.*;
public class Hangman1 {
public static void main(String[] args) throws Exception {
File myFile = new File("word.txt");
System.out.println("Attempting to read from file in: "+myFile.getCanonicalPath());
Scanner input = new Scanner(myFile);
String in = "";
in = input.nextLine();
}
}
This code should print the folder where it is looking for. Place the file there and you'll be good to go.
Your file should directly be under the project folder, and not inside any other sub-folder.
If the folder of your project is named for e.g. AProject, it should be in the same place as your src folder.
Aproject
src
word.txt
Try to create a file using the code, so you will get to know the path of the file where the system create
File test=new File("check.txt");
if (test.createNewFile()) {
System.out.println("File created: " + test.getName());
}
I was reading path from a properties file and didn't mention there was a space in the end.
Make sure you don't have one.
Make sure when you create a txt file you don't type in the name "name.txt", just type in "name". If you type "name.txt" Eclipse will see it as "name.txt.txt". This solved it for me. Also save the file in the src folder, not the folder were the .java resides, one folder up.
I have the same problem, but you know why? because I didn't put .txt in the end of my File and so it was File not a textFile, you shoud do just two things:
Put your Text File in the Root Directory (e.x if you have a project called HelloWorld, just right-click on the HelloWorld file in the package Directory and create File
Save as that File with any name that you want but with a .txt in the end of that
I guess your problem is solved, but I write it to other peoples know that.
Thanks.
i think it always boils to the classpath. having said that if you run from the same folder where your .class is then change Scanner input = new Scanner(new File("word.txt")); to Scanner input = new Scanner(new File("./word.txt")); that should work
I've tried several different things to get this to work, and none of them have. I'm trying to create a file inside of a folder in Java. The project needs to have several text files that all relate to each other, and it would be more manageable to have them all together in one folder. Ideally, this folder would be stored outside of scr/.
Here is my current code for it (I do check for file existence first):
File testFile = new File("\\appts\\Appointments" + name + ".txt");
try {
testFile.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
However, I get an IOException when I try to run the code. I have tried it how it is above, also /appts/Appointments, appts/Appointments, appts\\Appointments. I tried searching online but couldn't find anything that worked.
Edit: Here is how my project setup currently looks like:
Project_Folder
src
com
weebly
roboticplayer
appointmentbook
CLASSES
Here is how I want it to look:
Project_Folder
src
com
weebly
roboticplayer
appointmentbook
CLASSES
appts
There are two easy ways to do this:
1) Absolute path
"C:\\users\\....\\parent_folder\\filename.txt";
2) relative path,
. (Single dot) is current directory
..(double dots) is parent directory
For example, you want to create text files under project folder. And the following is your file structure.
Project_folder
src
Java_main_file.java
appts
You want to create a file under appts from Java_main_file.java
String filename = "..\\appts\\filename.txt"
Then, create your file with filename. Here is a link how to create a text file.
Note that you need to make sure the folder under which you create the files exists. If it doesn't exist, you will get an error.
You can't create a file and its non-existent parent directories in one step, but you can create the parent directories first with File.mkdirs() and then create the file.
If your using JDK7 you can use nio package.
Path path = Paths.get("C:\\appts\\Appointments");
Files.createDirectories(path);
If you want to do a path relative to your current folder:
FileSystems.getDefault().getPath("appts", "Appointments");
If you want to see the absolute pathname:
FileSystems.getDefault().getPath("appts", "Appointments").toAbsolutePath().toString();
If you need that file object:
FileSystems.getDefault().getPath("appts", "Appointments").toFile();
You can also do .toFile() after the call toAbsolutePath().
This is the problem I have: If part or all of the path does not already exist, the server should create additional directories as necessary in the hierarchy and then create a new file as above.
Files.createDirectories(path);
That's what I am currently using, but it does not create the end file. For example is the path="/hello/test.html" it will create a directory called "hello" and one called "test.html", I want the test.html to be a file. How can I do that?
This is what I did to solve this "problem" or misuse of the libraries.
Files.createDirectories(path.getParent());
Files.createFile(path);
The first line will get the parent directory, so lets say this is what I want to create "/a/b/c/hello.txt", the parent directory will be "/a/b/c/".
The second like will create the file within that directory.
Have you looked at the javadoc? createDirectories only creates... directories. If you're intent on using Files.createDirectories, parse off the file name, call createDirectories passing only the path portion, then create a new file passing the entire path. Otherwise this is a better approach.
Files.createDirectories(path.substring(0, path.lastIndexOf(File.separator)+1));
File yourFile = new File(path);
you can parse the 'path' variable to isolate the file and the directory using delimiter as '/', and do File file = new File(parsedPath); This would work only when you know that you ALWAYS pass the file name at the end of it.
If you know when you are a) creating a directory b) creating a directory and file, you can pass the boolean variable that would describe if file needs to be created or not.