Run Program and Config File using Command Line - java

I have a Java project which comprises of the program named runProgram and configuration file named config.properties inside the package pack. I am trying to run the project as a .jar file from the command prompt in Windows 7. But I don't know how to indicate the specific configuration file that I want to use. I tried "open file" with the file name and it didn't work.
Program:
package pack;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class runProgram {
public static void main(String[] args){
double value;
Properties configFile = new Properties();
try {
configFile.load(helloworld.class.getClassLoader().getResourceAsStream(
"\\pack\\config.properties"));
} catch (IOException e) {
e.printStackTrace();
}
value = Double.parseDouble(configFile.getProperty("value"));
System.out.println("Value is: "+value);
}
}
Config File:
value = 75

I give it a shot, but I don't know if I'm getting your question correctly.
But I don't know how to indicate the specific configuration file that I want to use.
If this is about running the tool, while specifying another config file every time, I'd go with Apache CLI, to parse and handle command line arguments. Then the user can specify the file every time he/she is running your tool.
(Under 'usage' you can find some examples, but I'm not allowed to post more than two links right now)
But if you want to know more about handling java properties files, here's a good tutorial:
http://www.mkyong.com/java/java-properties-file-examples/
Also, for OS independent path definitions, have a look at System.getProperty("file.separator"), which, as the name says, tries to receive the OS specific path separator (e.g., '\' for Windows, '/' for UNIX systems).
Hope this helps.

Related

Java/Gradle reading external config files

My project structure looks like below. I do not want to include the config file as a resource, but instead read it at runtime so that we can simply change settings without having to recompile and deploy. my problem are two things
reading the file just isn't working despite various ways i have tried (see current implementation below i am trying)
When using gradle, do i needto tell it how to build/or deploy the file and where? I think that may be part of the problem..that the config file is not getting deployed when doing a gradle build or trying to debug in Eclipse.
My project structure:
myproj\
\src
\main
\config
\com\my_app1\
config.dev.properties
config.qa.properties
\java
\com\myapp1\
\model\
\service\
\util\
Config.java
\test
Config.java:
public Config(){
try {
String configPath = "/config.dev.properties"; //TODO: pass env in as parameter
System.out.println(configPath);
final File configFile = new File(configPath);
FileInputStream input = new FileInputStream(configFile);
Properties prop = new Properties()
prop.load(input);
String prop1 = prop.getProperty("PROP1");
System.out.println(prop1);
} catch (IOException ex) {
ex.printStackTrace();
}
}
Ans 1.
reading the file just isn't working despite various ways i have tried
(see current implementation below i am trying)
With the location of your config file you have depicted,
Change
String configPath = "/config.dev.properties";
to
String configPath = "src\main\config\com\my_app1\config.dev.properties";
However read the second answer first.
Ans 2:
When using gradle, do i needto tell it how to build/or deploy the file
and where? I think that may be part of the problem..that the config
file is not getting deployed when doing a gradle build or trying to
debug in Eclipse.
You have two choices:
Rename your config directory to resources. Gradle automatically builds the resources under "src/main/resources" directory.
Let Gradle know the additional directory to be considered as resources.
sourceSets {
main {
resources {
srcDirs = ["src\main\config\com\my_app1"]
includes = ["**/*.properties"]
}
}
}
reading the file just isn't working despite various ways i have tried (see current implementation below i am trying)
You need to clarify this statement. Are you trying to load properties from an existing file? Because the code you posted that load the Properties object is correct. So probably the error is in the file path.
Anyway, I'm just guessing what you are trying to do. You need to clarify your question. Is your application an executable jar like the example below? Are trying to load an external file that is outside the jar (In this case gradle can't help you)?
If you build a simple application like this as an executable jar
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class Main {
public static void main(String[]args) {
File configFile = new File("test.properties");
System.out.println("Reading config from = " + configFile.getAbsolutePath());
FileInputStream fis = null;
Properties properties = new Properties();
try {
fis = new FileInputStream(configFile);
properties.load(fis);
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
if(fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
}
System.out.println("user = " + properties.getProperty("user"));
}
}
When you run the jar, the application will try to load properties from a file called test.properties that is located in the application working directory.
So if you have test.properties that looks like this
user=Flood2d
The output will be
Reading config from = C:\test.properties
user = Flood2d
And that's because the jar file and test.properties file is located in C:\ and I'm running it from there.
Some java applications load configuration from locations like %appdata% on Windows or /Library/Application on MacOS. This solution is used when an application has a configuration that can change (it can be changed by manually editing the file or by the application itself) so there's no need to recompile the application with the new configs.
Let me know if I have misunderstood something, so we can figure out what you are trying to ask us.
Your question is slightly vague but I get the feeling that you want the config files(s) to live "outside" of the jars.
I suggest you take a look at the application plugin. This will create a zip of your application and will also generate a start script to start it. I think you'll need to:
Customise the distZip task to add an extra folder for the config files
Customise the startScripts task to add the extra folder to the classpath of the start script
The solution for me to be able to read an external (non-resource) file was to create my config folder at the root of the application.
myproj/
/configs
Doing this allowed me to read the configs by using 'config/config.dev.properies'
I am not familiar with gradle,so I can only give some advices about your question 1.I think you can give a full path of you property file as a parameter of FileInputStream,then load it using prop.load.
FileInputStream input = new FileInputStream("src/main/.../config.dev.properties");
Properties prop = new Properties()
prop.load(input);
// ....your code

File not found in same folder Java

I am trying to read a file in Java. I wrote a program and saved the file in the exact same folder as my program. Yet, I keep getting a FileNotFoundException. Here is the code:
public static void main(String[] args) throws IOException {
Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
File f = new File("file.txt");
ArrayList<String> al = readFile(f, ht);
}
public static ArrayList<String> readFile(File f, Hashtable<String, Integer> ht) throws IOException{
ArrayList<String> al = new ArrayList<String>();
BufferedReader br = new BufferedReader(new FileReader(f));
String line = "";
int ctr = 0;
}
...
return al;
}
Here is the stack trace:
Exception in thread "main" java.io.FileNotFoundException: file.txt (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(Unknown Source)
at java.io.FileReader.<init>(Unknown Source)
at csfhomework3.ScramAssembler.readFile(ScramAssembler.java:26)
at csfhomework3.ScramAssembler.main(ScramAssembler.java:17)
I don't understand how the file can't be found if it's in the exact same folder as the program. I'm running the program in eclipse and I checked my run configurations for any stray arguments and there are none. Does anyone see what's wrong?
Because the File isn't where you think it is. Print the path that your program is attempting to read.
File f = new File("file.txt");
try {
System.out.println(f.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
Per the File.getCanonicalPath() javadoc, A canonical pathname is both absolute and unique. The precise definition of canonical form is system-dependent.
Check the Eclipse run configuration. Look on the second tab "Arguments", at the bottom pane where it says "Working Directory". That's the place where the program gets launched and where it will expect to find the file. Usually in Eclipse it launches your program with the current working directory set to be the base project directory. If you have the java class file in a source folder and are using proper package (e.g., "com.mycompany.package"), then the data file will be in a directory like "src/com/mycompany/package" which is quite a different directory from the project directory.
HTH
File needs to be in the class path and not in the source path. Copy the file in output/class files folder and it should be available.
You should probably check out this question: Java can't find file when running through Eclipse
Basically you need to be sure where the execution is taking place (current directory) and how your SO will resolve the relative paths. Try changing the working directory in Eclipse' Run Configurations>Arguments or provide the absolute filename
I'm extremely late to responding to this question, but I see that this is still an extremely hot topic to this day. It may not seem obvious, but what you want to use here is actually the newer file-handling i/o library, java.nio. The below explained example shows how to read a String from a file path, but I encourage you to take a look at the docs if you have a different use.
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Files;
public static void main(String[] args) throws IOException {
Path path = Path.of("app/src/main/java/pkgname/file.txt");
String content = Files.readString(path);
System.out.println(content); // Prints file content
}
Okay, code done, now time for the explanation. I'll start off with the import statements. java.io.IOException is necessary for some exception-handling. (Sidenote: Do not omit the throws IOException and/or the IOException import. Otherwise Files.readString() may throw an error in your editor, which I'll get to shortly). The Path class import is necessary to actually get the file, and the Files class import is necessary for file operations.
Now, the main function itself. The first line receives a Path object representing a file for you to actually read/write. Here the question of path name arises, which is the basis of the question. I have seen other solutions that tell you to take the absolute path of your file, but don't do that! It's extremely bad practice, especially with open-source or public code. Path.of actually allows you to use the path relative to your root folder (unless it isn't in a directory, simply inputting the file name does not work, I'm afraid). The example path name I gave is an example of a Gradle project. Next line, we get the content of the file as a String using a method from Files. Again, if you have a different use for a file, you can check the docs (a different method from the Files class will probably work for you). On the final line, we print the result. Hooray! Our output is just what we needed.
There you have it, using Path instead of File is the solution to this annoying bug. Hopefully this helps!

Paths for images and executables in a jar

I have created a java program in eclipse and I am now ready to export it as a jar. My program uses an image file and an executable file. When testing my program in eclipse I referred to these file with a full path, which I obviously cannot do for the jar. Therefore, I changed them like this:
public static final String DRIVERLOC = "./resources/IEDriverServer.exe";
//some other code
File file = new File(DRIVERLOC);
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
and
File pic = new File("./images/Open16.gif");
openButton = new JButton("Select the Text File", createImageIcon(pic.getAbsolutePath()));
I put the images and the resources and images directory in the same directory with the jar. Now for some reason when I run the jar the IEDriverServer works fine but the image does not work and the error is that it cannot find the image. I am confused since I cannot seems to tell the difference. I also used "images/Open16.gif" which did not work either. Why would one work but the other does not? What is the easiest way to fix this?
We do this exact same thing with Selenium Drivers.
What you need to do is take the executable file out of the jar and put it some where windows can run it. If you try and open a jar/zip in Windows Explorer and then double click the .exe inside of a jar/zip, windows will extract the file to a temp directory, and then run it. So do the same thing:
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class TestClass {
public static void main (String[] args) throws IOException {
InputStream exeInputStream = TestClass.class.getClassLoader().getResourceAsStream("resources/IEDriverServer.exe");
File tempFile = new File("./temp/IEDriverServer.exe");
OutputStream exeOutputStream = new FileOutputStream(tempFile);
IOUtils.copy(exeInputStream, exeOutputStream);
// ./temp/IEDriverServer.exe will be a usable file now.
System.setProperty("webdriver.ie.driver", tempFile.getAbsolutePath());
}
}
Let's say you save the jar and make it run this main function by default.
Running C:\code\> java -jar TestClass.jar Will run the jar from the C:\code directory. It will create the executable at C:\code\temp\IEDriverServer.exe
With your path set to "./resources/IEDriverServer.exe" you are referring to a file on the hard drive "." which does not exist.
You need to get the path of your .jar-file.
You can do this by using
System.getProperty("java.class.path")
This can return multiple values, seperated by semi-colons. The first one should be the folder your jar is in.
You can also use
<AnyClass>.class.getProtectionDomain().getCodeSource().getLocation()
I hope this helps :)
EDIT:
// First, retrieve the java.class.path property. It returns the location of all jars /
// folders (the one that contains your jar and the location of all dependencies)
// In my test it returend a string with several locations split by a semi-colon, so we
// split it and only take the first argument
String jarLocation = System.getProperty("java.class.path").split(";")[0];
// Then we want to add that path to your ressource location
public static final String DRIVERLOC = jarLocation + "/resources/IEDriverServer.exe";
//some other code
File file = new File(DRIVERLOC);
System.setProperty("webdriver.ie.driver", file.getAbsolutePath());
You can read about this here.

Property file not reflecting the modified changes using Apache Commons Configuration

I am trying to explore Apache commons configuration to dynamically load the property file and do modification in the file and save it.
I wrote a demo code for the same.
Code Snippet
package ABC;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
public class Prop {
public static void main(String[] args)
{
try {
URL propertiesURL = Prop.class.getResource("/d1.properties");
if (propertiesURL == null) {
System.out.println("null");
}
String absolutePath=propertiesURL.getPath();
PropertiesConfiguration pc = new PropertiesConfiguration(absolutePath);
pc.setReloadingStrategy(new FileChangedReloadingStrategy());
String s=(String)pc.getProperty("key_account_sales");
System.out.println("s is " + s);
pc.setAutoSave(true);
pc.setProperty("key_account_sales", "Dummy");
pc.save();
System.out.println("Modified as well");
String sa=(String)pc.getProperty("key_account_sales");
System.out.println("s is " + sa);
}catch(ConfigurationException ce)
{
ce.printStackTrace();
}
}
}
Although when I run the code multiple times, the updated value for the property is being properly shown but the changes are not seen in the Property file.
I tried refreshing the entire workspace and the project but still the property file shows the previous entry whereas this code displays the updated entry in console.
Why my property file is not getting updated?
Well I noticed that a new file with same name was formed inside bin
directory of my IDE workspace. This new file contains the required
changes.
However I still want that the old file should be updated with the new
value and instead of creating a new file, it should update in the old
file itself.
My property file is located inside a Web Application package say
Dem1
by the name of
Prop1.prop
I want to read this property file from in another class say
Reading.java
located inside another package
Dem2
, do changes in this same property file and show it to another user. It is a web application being deployed on an application server.
Even after using the absolute path in a simple file (main function) it is not reflecting the changes in the same file but updating it in new file.
I am doing a very slight mistake but can someone please help.
Using absolute path I am not able to make changes in the same property file in normal main method also. Please suggest.
New file in bin directory is created instead of updating the same file
in src folder.
You should be able to solve this using absolute paths. The PropertiesConfiguration class is finding your properties file somewhere on the classpath and only knows to write back to "d1.properties"; hence you have a file appearing in your bin directory.
The absolute path can be obtained by querying resources on the classpath. Something like the following:
URL propertiesURL = Prop.class.getResource("/d1.properties");
if (propertiesURL == null) {
// uh-oh...
}
String absolutePath = propertiesURL.getPath();
// Now use absolutePath

Save information from Java application [duplicate]

This question already has answers here:
What is the proper way to store app's conf data in Java?
(6 answers)
Closed 9 years ago.
I'm making an application using databases in Java (compiled as JAR). In order to connect to the database, the user must enter the database's address. It would be a pain to remember/type the address every time you want to use the program.
Thus, I want to save the address to a text file somewhere...but where? I want this application to be accessible to anyone on any operating system, and I'd prefer not to have my JAR in a folder.
Is it possible, maybe, to write/read from a text file located within the JAR itself?
Like Sotirios Delimanolis said you can create and save a properties file.
It is very simple to do it please have a look at the example below (see the original the post)
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class WritePropertiesFile {
public static void main(String[] args) {
try {
Properties properties = new Properties();
properties.setProperty("favoriteAnimal", "marmot");
properties.setProperty("favoriteContinent", "Antarctica");
properties.setProperty("favoritePerson", "Nicole");
File file = new File("test2.properties");
FileOutputStream fileOut = new FileOutputStream(file);
properties.store(fileOut, "Favorite Things");
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I would not suggest you save the properties file into the jar file however it is possible to do so.
Please follow the stackoverflow answer at: how to write into a text file in Java
You can open a file anywhere in your jar using e.g. ClassLoader.getResourceAsStream()
Here's what worked for me. I simply used the path System.getProperty("user.home") as my file's location. This is operating system neutral.
Try the Java Preferences API to store user data like this.
Storing data in the application folder will be problematic (e.g., user might not have permission, application might be signed, etc). You can store a file in the user home directory, but most operating systems have a designated location to store user data (e.g., 'Application Support' on Mac, AppData on Windows, etc). Plus the user probably won't appreciate you cluttering up their home directory. You can create a properties file and handle storing it in the proper place yourself, but an easier solution would be to use the Preferences API which abstracts the pain of having to know where to write the file.
Here is an example:
import java.util.prefs.Preferences;
public class Test {
public static final String DB_PROP = "user.selected.db.address";
public static void main(String[] args) {
Preferences prefs = Preferences.userNodeForPackage(Test.class);
prefs.put(DB_PROP, "foo");
String dbAddress = prefs.get(DB_PROP, null);
System.out.println(dbAddress);
}
}

Categories

Resources