Program works fine in compiler but not in jar (Java) - java

I Exported my program into a jar file but when I ran it, it seems as if the .properties file isn't found by the program. I made sure it was in the jar file & it worked fine prior to exporting it. I read something about using getClass().getResourceAsStream() instead of FileInputStream and FileOutputStream but can't seem to understand how that would help. Any ideas? These are the two methods that use the file.
private void UpdateData() throws IOException{
FileInputStream in = new FileInputStream("config.properties");
Properties props = new Properties();
props.load(in);
in.close();
FileOutputStream out = new FileOutputStream("config.properties");
props.setProperty("prop1", prop1TextArea.getText().toString());
props.setProperty("prop2", prop2TextArea.getText().toString());
props.setProperty("prop3", prop3TextArea.getText().toString());
props.store(out, null);
out.close();
}
private void setText() throws IOException {
FileInputStream in = new FileInputStream("config.properties");
Properties props = new Properties();
props.load(in);
in.close();
FileOutputStream out = new FileOutputStream("config.properties");
prop1TextArea.setText(props.getProperty("prop1"));
prop2TextArea.setText(props.getProperty("prop2"));
prop3TextArea.setText(props.getProperty("prop3"));
out.close();
}

To access resources in your .jar file you have to access them as resources not as files.
The .properties are not in the filesystem anymore and therefore you cannot access them via FileInputStream.
If you want to save them afterwards you have to create new .properties on the first start of your program. So you have to check first if the file exists (e.g. via File.exists()) and either work without the properties from the file or create a new file and use this then.

Related

How to attach file to jar that can be edited inside this jar?

I am making a program that works with MySQL database,for now i store URL, login, password e.t.c as public static String. Now i need to make it possible to work on another computer, so database adress will vary, so i need a way to edit it inside programm and save. I would like to use just external txt file, but i don't know how to point it's location.
I decided to make it using Property file, i put it in src/res folder. It work correct while i'm trying it inside Intellij Idea, but when i build jar (artifact) i get java.io.FileNotFoundException
I tried two ways:
This one was just copied
private String getFile(String fileName) {
StringBuilder result = new StringBuilder("");
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
System.out.println(file.length());
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
System.out.println(obj.getFile("res/cfg.txt"));</code>
And second one using Properties class:
try(FileReader reader = new FileReader("src/res/cfg.txt")) {
Properties properties = new Properties();
properties.load(reader);
System.out.println(properties.get("password"));
}catch (Exception e) {
e.printStackTrace();
System.out.println(e);
}
In both ways i get java.io.FileNotFoundException. What is right way to attach config file like that?
Since the file is inside a .JAR, it can't be accessed via new File(), but you can still read it via the ClassLoader:
Properties properties = new Properties();
try (InputStream stream = getClass().getResourceAsStream("/res/cfg.txt")) {
properties.load(stream);
}
Note that a JAR is read-only. So this approach won't work.
If you want to have editable configuration, you should place your cfg.txt outside the JAR and read it from the filesystem. For example like this:
Properties properties = new Properties();
File appPath = new File(MyClass.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile();
try (InputStream stream = new FileInputStream(new File(appPath, "cfg.txt"))) {
properties.load(stream);
}
There are multiple places your can place your configuration options, and a robust deployment strategy will utilize some (or all) of the following techniques:
Storing configuration files in a well known location relative to the user's home folder as I mentioned in the comments. This works on Windows (C:\Users\efrisch), Linux (/home/efrisch) and Mac (/Users/efrisch)
File f = new File(System.getProperty("user.home"), "my-settings.txt");
Reading environment variables to control it
File f = new File(System.getenv("DEPLOY_DIR"), "my-settings.txt");
Using a decentralized service such as Apache ZooKeeper to store your database settings
Use Standalone JNDI
(or the JNDI built-in to your deployment target)
Use a Connection Pool

how to write to a file when it's an executable in java

HI
I have a problem with writing to files, It works in the program(netbeans), but when it's exported to a jar file, it throws an exception, "FileNotFound." I checked inside the file folder inside the jar, and it was there, I think I need to use streams just as I use them in reading files:
InputStream u= FM.class.getResourceAsStream("/genex/files/data.txt");
try (InputStreamReader f = new InputStreamReader(u)) {what I wrote}
and that works perfectly fine, I just need a method like a getResourceAsStream() for OutputStreams
(btw, FM is the class name)
UPDATE: For those of you who really wanted to write files inside the jar, well, it's impossible. BUT, I found another way to store all of your files:
-writing
File file = new File("/GH/GX/save.txt");
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
try (PrintWriter writer = new PrintWriter(file)) {what you want to write}
-reading
File file = new File("/GH/GX/save.txt");
if (!file.exists()) {
return;
}
try (FileReader f = new FileReader(file)) {
//fr = new FileReader(f);
try (BufferedReader br = new BufferedReader(f)) {what you want to read}}
So I hope this article helped you :)
You can only read from files inside a jar not write to them.

Create file in jsp servlet

When I create a file in java servlet, I can't find that file for opening. This is my code in servlet:
FileOutputStream fout;
try {
fout = new FileOutputStream("title.txt");
new PrintStream(fout).println(request.getParameter("txttitle"));
fout.close();
System.out.println(request.getParameter("txttitle"));
} catch (Exception e) {
System.out.println("I can't create file!");
}
Where I can find that file?
if you create file first as in
File f = new File("title.txt");
fout = new FileOutputStream(f);
then you use getAbsolutePath to return the location of where it has been created
System.out.println (f.getAbsolutePath());
Since you have'nt specified any directory for the file, it will be placed in the default directory of the process that runs your servlet container.
I would recommand you to always specify the full path of your your file when doing this kind of things.
If you're running tomcat, you can use System.getProperty("catalina.base") to get the path of the tomcat base directory. This can sometimes help.
Create a file object and make sure the file exists:-
File f = new File("title.txt");
if(f.exists() && !f.isDirectory()) {
fout = new FileOutputStream(f);
new PrintStream(fout).println(request.getParameter("txttitle"));
fout.close();
System.out.println(request.getParameter("txttitle"));
}
If the servlet cannot find the file give the full path to the file specified, like new File("D:\\Newfolder\\title.txt");
you should check first if the file doesn't exist ,create it
if(!new File("title.txt").exists())
{
File myfile = new File("title.txt");
myfile.createNewFile();
}
then you can use FileWriter or FileOutputStream to write to the file i prefer FileWriter
FileWriter writer = new FileWriter("title.txt");
writer.write("No God But Allah");
writer.close();
simply simple

Java Properties.store is deleting other entries

I am trying to modify a config file in Java using Properties. I try to modify two of the multiple entries like this:
Properties properties = new Properties();
FileInputStream fin = null;
FileOutputStream fout = null;
fin = new FileInputStream(mCallback.getConfFile());
fout = new FileOutputStream(mCallback.getConfFile());
properties.load(fin);
properties.setProperty(Wrapper.GAME_PATH_KEY, (String)gamePathText.getText());
properties.setProperty(Wrapper.GAME_TYPE_KEY, (String)selectedGame.getSelectedItem());
properties.store(fout, null);
But when I check the file after the result I find out that the whole file was overwritten, leaving only these two entries. This is an android app though I guess it's not relevant to the problem here. What I am doing wrong?
You have to read all properties and then modify the ones you want. After that you have to write all to file. You cannot do only an item modification. The Properties API doesn't provide that functionality to modify.
Edit:
Interchange these two statements-
fout = new FileOutputStream(mCallback.getConfFile());
properties.load(fin);
You should load first before you create a file with the same name.
From Properties:
public void store(OutputStream out,
String comments)
throws IOException
Writes this property list (key and element pairs) in this Properties table to the output > stream in a
format suitable for loading into a Properties table using the
load(InputStream) method.
Properties from the defaults table of this
Properties table (if any) are not written out by this method.
This method outputs the comments, properties keys and values in the
same format as specified in store(Writer), with the following
differences:
So, Load the data first, then set the required data, then store it.
Properties prop =new Properties();
prop.load(new FileInputStream(filename));
prop.setProperty(key, value);
prop.store(new FileOutputStream(filename),null);
The previous poster was kind of right, just not at the right place.
You need to open the FileOutputStream after you've loaded the properties otherwise it clears the file's content.
Properties properties = new Properties();
FileInputStream fin = null;
FileOutputStream fout = null;
fin = new FileInputStream(mCallback.getConfFile());
// if fout was here, the file would be cleared and reading from it would produce no properties
properties.load(fin);
properties.setProperty(Wrapper.GAME_PATH_KEY, (String)gamePathText.getText());
properties.setProperty(Wrapper.GAME_TYPE_KEY, (String)selectedGame.getSelectedItem());
fout = new FileOutputStream(mCallback.getConfFile());
properties.store(fout, null);

Java properties not loading

I am trying to set up a java .properties file outside of the packaged jar. This is my code to load it:
public static final String FILENAME = "test.properties";
public static void load() throws IOException {
FileInputStream fis = null;
try {
props = new Properties();
fis = new FileInputStream(FILENAME);
props.load(fis);
System.out.println("Properties successfully loaded: "+props);
validateProperties();
} catch (FileNotFoundException e) {
System.err.println("Properties file not found. Creating...");
new File(FILENAME).createNewFile();
//fill with default properties
System.out.println("Properties file successfully created");
} finally {
if (fis != null) try {fis.close();} catch(Exception e) {}
}
}
Unfortunately, when I run this, I get the following output:
Properties successfully loaded: {}
Here is test.properties:
#no comment
#Sun Jun 23 19:21:45 CDT 2013
port=55142
handSize=10
maxPlayers=8
timeout=1500
I have confirmed, by manually reading and printing, that the FileInputStream is reading from the correct file. So why aren't my properties loading?
EDIT: Here is some code which loads the contents of the properties file directly:
public static void test() throws IOException {
FileInputStream fis = new FileInputStream(FILENAME);
byte[] b = new byte[fis.available()];
fis.read(b);
String text = new String(b);
System.out.println(text);
}
and it outputs:
#no comment
#Sun Jun 23 19:21:45 CDT 2013
port=55142
handSize=10
maxPlayers=8
timeout=500
so the FIS must be reading from the correct file.
EDIT 2: Ok, so I don't know what the problem was, but I restarted eclipse and now it's working. Very sorry to have wasted your time.
Check what line separator your java system uses. Eg:
System.out.println((int)System.getProperty("line.separator").charAt(0));
On UNIX that will give 10, which is newline \n, on Windows that will be 13 (eg: the first char of \r\n).
I think your java code is reading the file using Windows encoding, yet the property file is edited in UNIX, hence everyting appears to be in "one single line" -- which will result in empty properties because your first line is commented
As your properties file is not present in the classpath so you cannot read it without giving the proper path. There are multiple approaches to read an external properties file from a jar. One of the simplest way is to use the -D switch to define a system property on a java command line. That system property may contain a path to your properties file.
E.g
java -cp ... -Dmy.app.properties=/path/to/test.properties my.package.App
Then, in your code you can do :
public static final String FILENAME = "test.properties";
public static void load() throws IOException {
FileInputStream fis = null;
String propPath = System.getProperty(FILENAME);
try {
props = new Properties();
fis = new FileInputStream(propPath);
props.load(fis);
System.out.println("Properties successfully loaded: "+props);
validateProperties();
} catch (FileNotFoundException e) {
System.err.println("Properties file not found. Creating...");
new File(propPath ).createNewFile();
//fill with default properties
System.out.println("Properties file successfully created");
} finally {
if (fis != null) try {fis.close();} catch(Exception e) {}
}
}
When there is no absolute path mentioned, JVM tries to load resources from the JVM & project classpath. In your case, empty output signifies that JVM is trying to load property file from classpath but the file is not there.
Solutions:
1) Either place your property file in your classpath
2) Or mention absolute path to property file.
A ResourceBundle offers a very easy way to access key/value pairs in a properties file in a Java...
You can refer following.
http://www.avajava.com/tutorials/lessons/how-do-i-read-a-properties-file-with-a-resource-bundle.html
You can directly specify your properties file name while loading the bundle when it is present in the same folder as your jar/classes.

Categories

Resources