How to write to properties file in a java package using java class in another package.
Here is the code for writing properties file
String filePath1 = "com/...../application.properties";
File applicationProperties = new File(filePath1);
FileOutputStream fileOutputStream = new FileOutputStream(applicationProperties);
Date todayDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
properties.setProperty("application.database.backup.date", sdf.format(todayDate));
properties.store(fileOutputStream, "storing index values to properties file");
fileOutputStream.close();
Getting FileNotFoundException.But file is exist in this package.while reading these file get the output.
String filePath = "com/....../application.properties";
InputStream inputStream = getClass().getResourceAsStream(filePath);
Properties properties = new Properties();
properties.load(inputStream);
if (properties.getProperty("application.grouping.mode") != null || !properties.getProperty("application.grouping.mode").isEmpty()) {
String lastBackupDate = properties.getProperty("application.grouping.mode");
}
How to solve this Exception.
There are three problems here, which are related. Basically, you're assuming that get because you can read from a resource, you can write to a file in the same folder structure, relative to the current directory. That's a flawed assumption because:
The resources may not be on the file system as separate files to start with. For example, Java applications are usually packaged up into jar files. The classloader knows how to read resources from a jar file, but the folder structure isn't present on disk
Even if the files are on disk as separate files in the right folder structure, they may not be rooted in the process's working directory. For example:
# Running in /home/jon/Documents
$ java -cp /home/jon/java/bin com.foo.bar.SomeApplication
Here SomeApplication.class would be in /home/jon/java/bin/com/foo/bar, but new File("com/foo/bar/something.properties") would refer to /home/jon/Documents/com/foo/bar/something.properties.
Finally, even if you were trying to write to the right place, you may not have write access - very often the binaries for applications are stored in read-only directories, with the reasonable justification that the code and read-only application data should be separated from the application's changing state. Aside from anything else, this makes updates/repairs much easier - just blow away the old version's directory, knowing that you won't have lost any user data.
Your context isn't clear, but I would suggest that you find some appropriate way of passing a filename to the application, and write to that and read from it where you need to.
Make sure your property file is in class path. after that you should be able to load it as
String filePath = "/application.properties";
InputStream inputStream = getClass().getResourceAsStream(filePath);
Your com is in the src directory. So your file path must be src/com/...... It must start with src/ and not com/
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.
This is a chunk of data I'd like to access by a method.
I'm doing the following to read my file:
String fileName = "file.txt"
InputStream inputStream = new FileInputStream(fileName);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
My file.txt is in the same package, but I still get FileNotFoundException.
I didn't use a path url to point to the file because I thought since this it going to be an android application, hard-coding the path might not work when deployed... Please correct me if I am wrong. Thanks bunch!
This shows how to do that. https://stackoverflow.com/a/14377185/2801237
Also the 'package' your class is in has nothing to do with the 'path' where the file is being executed from. (two different concepts, 'package' = folder hierarchy of java source code files), 'path' = location on a filesystem of a specific file, your APK is being 'executed' in a particular place, and the location it writes a file is associated with that (I actually don't know where 'offhand' it writes by default, because I always get cache dir, or sd card root, etc.)
You may use:
InputStream inputStream = this.getClass().getResourceAsStream(fileName);
My app needs to get an existing file for processing. Now I have the path of the file in String format, how can I get the File with it? Is it correct to do this:
File fileToSave = new File(dirOfTheFile);
Here dirOfTheFile is the path of the file. If I implement it in this way, will I get the existing file or the system will create another file for me?
That's what you want to do. If the file exists you'll get it. Otherwise you'll create it. You can check whether the file exists by calling fileToSave.exists() on it and act appropriately if it does not.
The new keyword is creating a File object in code, not necessarily a new file on the device.
I would caution you to not use hardcoded paths if you are for dirOfFile. For example, if you're accessing external storage, call Environment.getExternalStorageDirectory() instead of hardcoding /sdcard.
The File object is just a reference to a file (a wrapper around the path of the file); creating a new File object does not actually create or read the file; to do that, use FileInputStream to read, FileOutputStream to write, or the various File helper methods (like exists(), createNewFile(), etc.) for example to actually perform operations on the path in question. Note that, as others have pointed out, you should use one of the utilities provided by the system to locate directories on the internal or external storage, depending on where you want your files.
try this..
File fileToSave = new File(dirOfTheFile);
if(fileToSave.exists())
{
// the file exists. use it
} else {
// create file here
}
if parent folder is not there you may have to call fileToSave.getParentFile().mkdirs() to create parent folders
I have two resources folders.
src - here are my .java files
resources - here are my resources files (images, .properties) organized in folders (packages).
Is there a way to programmatically add another .properties file in that resources folder?
I tried something like this:
public static void savePropertiesToFile(Properties properties, File propertiesFile) throws IOException {
FileOutputStream out = new FileOutputStream(propertiesFile);
properties.store(out, null);
out.close();
}
and before that created:
new File("/folderInResources/newProperties.properties");
But it looks for that path on the file system. How can I force it to look in the resources folder?
EDIT: Let me say what is it about. I have a GUI application and I support 2 languages (2 .properties files in resources folder). Now I added a option that user can easily translate application and when he finishes I save that new .properties on a disk in some hidden folder and read it from there. But I was hoping I could save that new .properties files (new language) next to the current languages (resources folder). I have a static Messages class which knows how to load resources both from the disk and both the default ones in resources folder. But if user takes this .jar file on some other machine, he would't have that new languages since they are on disk on that computer, not inside .jar file.
Java 8 Solution
Path source = Paths.get(this.getClass().getResource("/").getPath());
Path newFolder = Paths.get(source.toAbsolutePath() + "/newFolder/");
Files.createDirectories(newFolder);
This will surely create new folder in resource folder. but you will find new folder in your target runtime.
which will be ProjectName/target/test-classes/newFolder. if you are running this code in test case. Other wise it would be in target/classes
Don't try to find new folder in your src/resources.
it will be surely in target/test-classes or target/classes.
As other people have mentioned, resources are obtained through a ClassLoader. What the two current responses have failed to stress, however, is these points:
ClassLoaders are meant to abstract the process of obtaining classes and other resources. A resource does not have to be a file in a filesystem; it can be a remote URL, or anything at all that you or somebody else might implement by extending java.lang.ClassLoader.
ClassLoaders exist in a child/parent delegation chain. The normal behavior for a ClassLoader is to first attempt to obtain the resource from the parent, and only then search its own resources—but some classloaders do the opposite order (e.g., in servlet containers). In any case, you'd need to identify which classloader's place for getting stuff you'd want to put stuff into, and even then another classloader above or below it might "steal" your client code's resource requests.
As Lionel Port points out, even a single ClassLoader may have multiple locations from which it loads stuff.
ClassLoaders are used to, well, load classes. If your program can write files to a location where classes are loaded from, this can easily become a security risk, because it might be possible for a user to inject code into your running application.
Short version: don't do it. Write a more abstract interface for the concept of "repository of resource-like stuff that I can get stuff from," and subinterface for "repository of resource-like stuff that I can get stuff from, but also add stuff from." Implement the latter in a way that both uses ClassLoader.getContextClassLoader().getResource() (to search the classpath) and, if that fails, uses some other mechanism to get stuff that the program may have added from some location.
Problem would be the classpath can contain multiple root directories so distinguishing which one to store would be hard without an existing file or directory.
If you have an existing file loaded.
File existingFile = ...;
File parentDirectory = existingFile.getParentFile();
new File(parentDirectory, "newProperties.properties");
Otherwise try an get a handle on a directory you know is unique in your resources directory. (Not sure if this works)
URL url = this.getClass().getResource("/parentDirectory");
File parentDirectory = new File(new URI(url.toString()));
new File(parentDirectory, "newProperties.properties");
Cut the main project folder of the compiled subfolders ("/target/classes", "target/test-classes") and you have the basic path to reconstruct your project folders with:
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
public class SubfolderCreator {
public static void main(String... args) throws URISyntaxException, IOException {
File newResourceFolder = createResourceSubFolder("newFolder");
}
private static File createResourceSubFolder(String folderName) throws URISyntaxException, IOException {
java.net.URL url = SubfolderCreator.class.getResource("/EXISTING_SUBFOLDER/");
File fullPathToSubfolder = new File(url.toURI()).getAbsoluteFile();
String projectFolder = fullPathToSubfolder.getAbsolutePath().split("target")[0];
File testResultsFolder = new File(projectFolder + "src/test/resources/" + folderName);
if (!testResultsFolder.exists()) {
testResultsFolder.mkdir();
}
return testResultsFolder;
}
}
The following code writes into the classes directory, along with the class files.
As others have noted, beware of overwriting class files. Best to put your new files into a separate directory; however, that directory needs to already exist. To create it, create a sub-directory within the resources in the source, perhaps containing an empty file. For example src\main\resources\dir\empty.txt.
public class WriteResource {
public static void main(String[] args) throws FileNotFoundException {
String thing = "Text to write to the file";
String dir = WriteResource.class.getResource("/").getFile();
//String dir = WriteResource.class.getResource("/dir").getFile();
OutputStream os = new FileOutputStream(dir + "/file.txt");
final PrintStream printStream = new PrintStream(os);
printStream.println(thing);
printStream.close();
}
}
This does the trick, but I'd be nervous about deploying this outside of a strictly controlled environment. I don't really like the idea of unauthorised persons writing to my classes directory!
Based on the below code you get or create a file and use it as a util method.
public static File getFileFromResource(String filePath) {
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
return new File(Objects.requireNonNull(classloader.getResource(filePath)).getFile());
}
Project structure
You should specify the relative path to file or folder. Usage:
getFileFromResource("application.properties");
Output:
File with path C:\Users\????\IdeaProjects\back-end\target\classes\application.properties
The code basically allows the user to input the name of the file that they would like to delete which is held in the variable 'catName' and then the following code is executed to try and find the path of the file and delete it. However, it doesn't seem to work, as it won't delete the file this way. Is does however delete the file if I input the whole path.
File file = new File(catName + ".txt");
String path = file.getCanonicalPath();
File filePath = new File(path);
filePath.delete();
If you're deleting files in the same directory that the program is executing in, you don't need specify a path, but if it's not in the same directory that your program is running in and you're expecting the program to know what directory your file is in, that's not going to happen.
Regarding your code above: the following examples all do the same thing. Let's assume your path is /home/kim/files and that's where you executed the program.
// deletes /home/kim/files/somefile.txt
boolean result = new File("somefile.txt").delete();
// deletes /home/kim/files/somefile.txt
File f = new File("somefile.txt");
boolean result = new File(f.getCanonicalPath()).delete();
// deletes /home/kim/files/somefile.txt
String execPath = System.getProperty("user.dir");
File f = new File(execPath+"/somefile.txt");
f.delete();
In other words, you'll need to specify the path where the deletable files are located. If they are located in different and changing locations, then you'll have to implement a search of your filesystem for the file, which could take a long time if it's a big filesystem. Here's an article on how to implement that.
Depending on what file you want to delete, and where it is stored, chances are that you are expecting Java to magically find the file.
String catName = 'test'
File file = new File(catName + '.txt');
If the program is running in say C:\TestProg\, then the File object is pointing to a file in the location C:\TestProg\test.txt. Since the file object is more of just a helper, it has no issues with pointing to a non-existent file (File can be used to create new files).
If you are trying to delete a file that is in a specific location, then you need to prepend the folder name to the file path, either canonically, or relative to the execution location.
String catName = 'test'
File file = new File('myfiles\\'+ catName +'.txt');
Now file is looking in C:\TestProg\myfiles\test.txt.
If you want to find that file anywhere, then you need a recursive search algorithm, that will traverse the filesystem.
The piece of code that you provided could be compacted to this:
boolean success = new File(catName + ".txt").delete();
The success variable will be true if the deletion was successful. If you do not provide the full absolute path (e.g. C:\Temp\test for the C:\Temp\test.txt file), your program will assume that the path is relative to its current working directory - typically the directory from where it was launched.
You should either provide an absolute path, or a path relative to the current directory. Your program will not try to find the file to delete anywhere else.