How to load files on multiple platforms properly using Java? [duplicate] - java

This question already has answers here:
Platform independent paths in Java
(8 answers)
Closed 3 years ago.
I have a java swing database application which needs to be run on Windows and Linux. My database connection details are stored in a XML file and I load them.
This application can load this properties on Linux properly but it is not working on Windows.
How do I load files on multiple platforms properly using Java?
This is the code:
PropertyHandler propertyWriter = new PropertyHandler();
List keys = new ArrayList();
keys.add("ip");
keys.add("database");
Map localProps = propertyWriter.read(keys, "conf" + File.separatorChar + "properties.xml", true);//if false load from the local properties
//get properties from the xml in the internal package
List seKeys = new ArrayList();
seKeys.add("driver");
seKeys.add("username");
seKeys.add("password");
Map seProps = propertyWriter.read(seKeys, "conf" + File.separatorChar + "properties.xml", true);
String dsn = "jdbc:mysql://" + (String) localProps.get("ip") + ":3306/" + (String) localProps.get("database");
jDBCConnectionPool = new JDBCConnectionPool((String) seProps.get("driver"), dsn, (String) seProps.get("username"), (String) seProps.get("password"));
File reader method:
public Map read(List properties, String path, boolean isConfFromClassPath)
{
Properties prop = new Properties();
Map props = new HashMap();
try {
if (isConfFromClassPath) {
InputStream in = this.getClass().getClassLoader().getResourceAsStream(path);
prop.loadFromXML(in);
for (Iterator i = properties.iterator(); i.hasNext();) {
String key = (String) i.next();
props.put(key, prop.getProperty(key));
}
in.close();
} else {
FileInputStream in = new FileInputStream(path);
prop.loadFromXML(in);
for (Iterator i = properties.iterator(); i.hasNext();) {
String key = (String) i.next();
props.put(key, prop.getProperty(key));
}
in.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return props;
}

If the file is in a jar file and accessed by the classpath then you should always use /.
The JavaDocs for the ClassLoader.getResource say that "The name of a resource is a '/'-separated path name that identifies the resource."
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)

I'm not sure if there is the proper way, but one way is:
File confDir = new File("conf");
File propFile = new File(confDir, "properties.xml");
But in a scenario as simple as yours, I would just use /

If it's a resource located in classpath, we can load it with following snippet:
getClass().getClassLoader().getResourceAsStream(
"/META-INF/SqlQueryFile.sql")));

You can load all files on multiple platforms without any trouble.
Kindly use Matcher.quoteReplacement(File.separator) for replacing the slash.
It will works for every platform.
String fileLocation = "/src/service/files";
fileLocation = fileLocation.replaceAll("/",Matcher.quoteReplacement(File.separator));

assuming that your file is in conf/properties.xml on Linux and conf\properties.xml on Windows,
use File.pathSeparator instead of File.separator

Related

How to have different properties file for different machines?

So I am working in a team of people on a small school project, and we're developing java/jsp web app with apache.. I created simple properties.config file so I can store values and use them later and it looks something like this:
home_url = http://localhost:8080/to3/
to3_path = C:/Users/User2/Documents/workspace/TO-3
db_url = jdbc:mysql://localhost:3306/to3?useUnicode=true&characterEncoding=UTF-8
Problem I have is when I commit it and someone do a checkout they have to change values for url-s and paths so it fits their machine.. I heard I can make a custom properties file which will override these default values if it recognizes certain machine, but I don't know how to do it.
Thank you all in advance for your help.
Don't commit project settings. Put them in .gitignore and commit a copy of it (e.g. properties.config.sample). Make sure to keep it up to date with any new keys you add, but each developer should make their own untracked copy.
As Amadan point out you should not commit project properties. My suggestion is to create a file with .properties extension and place your properties inside. To use this file in java you can create a class like that
public class MyProperties{
private String homeUrl = "";
private String to3Path = "";
private String dbPath = "";
private final String configPath = System.getProperty("user.home") + File.separator + "my-props.properties";
public void loadProperties(){
try {
Properties prop = new Properties();
InputStream input = null;
File filePath = new File(configPath);
input = new FileInputStream(filePath);
// load a properties file
prop.load(input);
homeUrl = prop.getProperty("home_url");
to3Path = prop.getPropert("to3_path");
dbPath = prop.getProperty("db_url");
}catch (Exception e) {
e.printStackTrace();
}
}
// getters & setters
}
Then in your app you can do
MyProperties props = new MyProperties();
props.loadProperties();
String homeUrl = props.getHomeUrl();
System.getProperty("user.home") will give home path depending on the OS.
For example in windows this is path is C:\Users\yourName
This way all your co-workers can place their own properties in their personal pc inside their home path and you will be able to work without conflicts.

Create instance of file using value of a property in properties file

I'm trying to create an instance of a file to parse html records from a property value. the problem is in the url of the file that I must put in the file properties, here is my example :
the correspondance code for reading file :
public void extraxtElementWithoutId() {
Map<String,List<List<Element>>> uniciteIds = new HashMap<String,List<List<Element>>>();
FileReader fileReader = null;
Document doc = null;
try {
fileReader = new FileReader(new ClassPathResource(FILEPROPERTYNAME).getFile());
Properties prop = new Properties();
prop.load(fileReader);
Enumeration<?> enumeration = prop.propertyNames();
List<List<Element>> fiinalReturn = null;
while (enumeration.hasMoreElements()) {
String path = (String) enumeration.nextElement();
System.out.println("Fichier en question : " + prop.getProperty(path));
URL url = getClass().getResource(prop.getProperty(path));
System.out.println(url.getPath());
File inputFile = new File(url.getPath());
doc = Jsoup.parse(inputFile, "UTF-8");
//fiinalReturn = getListofElements(doc);
//System.out.println(fiinalReturn);
fiinalReturn = uniciteIds.put("Duplicat Id", getUnicityIds(doc));
System.out.println(fiinalReturn);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try{
fileReader.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
Thank you in advance,
Best Regards.
You are making a very common mistake for line -
URL url = getClass().getResource(prop.getProperty(path));
Try with property value as ( by removing src ) - /testHtmlFile/test.html and so on. Don't change code.
UrlEnterer1=/testHtmlFile/test.html instead of preceding it with src.
prop.getProperty(path) should be as per your build path location for the file. Check your build directory as how these files are stored. These are not stored under src but directly under build directory.
This answer explains a little bit about path value for file reading from class path.
Also, as a side note ( not related to question ) , try not doing prop.getProperty(path) but directly injecting property value in your class using org.springframework.beans.factory.annotation.Value annotation.

System.getProperty("mode") returns "null"

We recently had to set up one of the tomcat servers from scratch. Tomcat version is 8.0.20. Deploying a war file, now System.getProperty("mode") returns "null" where it should return PREPROD.
It should read this "mode" from a mode.properties file which is located in the webapps directory. The two lines commented out show another part of code that does not work anymore on the new tomcat server. I replaced it with code that should work.
//String pathOfWebInf = sce.getServletContext().getRealPath("WEB-INF");
//String pathOfLocalhostFile = pathOfWebInf + File.separator + "classes"
// + File.separator;
String pathOfLocalhostFile = this.getClass().getResource("/").getPath();
String mode = System.getProperty("mode");
String fileName = "localhost-oracle.properties." + mode;
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("xxx");
Properties dbProps = new EncryptableProperties(encryptor);
try
{
InputStream is = new FileInputStream(pathOfLocalhostFile + fileName);
dbProps.load(is);
} catch (Exception e)
{
throw new IOException("Could not read properties file " + pathOfLocalhostFile + fileName);
}
System.properties is related to all properties in the Computer where the JVM is running... there is no mode key defined there, that is why you get null as value....
check out all the properties in the pc by doing:
final Properties props = System.getProperties();
props.list(System.out);
and verify yourself, there is no mode key in that map...
You have to load mode.properties first, like this way
private Properties mode=null;
mode = new Properties();
mode.load(new FileInputStream(pathtoMODE));
String mode = mode.getProperty("mode");

Java: How do I access my properties file?

So I have a property file in my project. I need to access it.
Here's the tree structure:
+ Project Name
|--+ folder1
|--+ propertyfolder
|--+ file.properties
Or: Project/propertyfolder/file.properties
Here's what I've tried so far (one at a time, not all at once):
// error: java.io.File.<init>(Unknown Source)
File file = new File(System.getProperty("file.properties"));
File file = new File(System.getProperty("propertyfolder/file.properties"));
File file = new File(System.getProperty("propertyfolder\\file.properties"));
File file = new File(System.getProperty("../../propertyfolder/file.properties"));
And:
InputStream inputStream = getClass().getResourceAsStream("file.properties");
InputStream inputStream = getClass().getResourceAsStream("../../propertyfolder/file.properties");
InputStream inputStream = getClass().getResourceAsStream("propertyfolder/file.properties");
InputStream inputStream = getClass().getResourceAsStream("propertyfolder\\file.properties");
And all variations within getClass(), such as getClass().getClassLoader(), etc.
The error I'm getting is a NullReferenceException. It's not finding the file. How do I find it correctly?
(taken from comment to answer as OP suggested)
Just use File file = new File("propertyfolder/file.properties") but you do need to know where is java process working directory, if you cannot control it try an absolute path /c:/myapp/propertyfolder/file.properties.
You may also use /myapp/propertyfolder/file.properties path without C: disk letter to avoid windows-only mapping. You may use / path separator in Java apps works in Win,Linux,MacOSX. Watch out for text file encoding, use InputStreamReader to given an encoding parameter.
File file = new File("propertyfolder/file.properties");
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
BufferedReader reader = new BufferedReader(isr);
..read...
reader.close(); // this will close underlaying fileinputstream
Inorder to use getClass().resourceAsStream("file.properties") you need to make sure the file is there in the classpath.
That is if your Test.java file is compiled into bin/Test.class then make sure to have file.properties in the bin/ folder along with the Test.class
Otherwise you can use the Absolute Path, which is not advisable.
Did you set System properties to load file.properties from
1) Command line using -Dpropertyname=value OR
2) System.setProperty() API OR
3) System.load(fileName) API?
If you have n't done any one of them, do not use System.getProperty() to load file.properties file.
Assuming that you have not done above three, the best way to create file InputStream is
InputStream inputStream = getClass().getResourceAsStream("<file.properties path from classpath without />");
Properties extends Hashtable so, Each key and its corresponding value in the property list is a string.
Properties props = new Properties();
// File - Reads from Project Folder.
InputStream fileStream = new FileInputStream("applicationPATH.properties");
props.load(fileStream);
// Class Loader - Reades Form src Folder (Stand Alone application)
ClassLoader AppClassLoader = ReadPropertyFile.class.getClassLoader();
props.load(AppClassLoader.getResourceAsStream("classPATH.properties"));
for(String key : props.stringPropertyNames()) {
System.out.format("%s : %s \n", key, props.getProperty(key));
}
// Reads from src folder.
ResourceBundle rb = ResourceBundle.getBundle("resourcePATH");// resourcePATH.properties
Enumeration<String> keys = rb.getKeys();
while(keys.hasMoreElements()){
String key = keys.nextElement();
System.out.format(" %s = %s \n", key, rb.getString(key));
}
// Class Loader - WebApplication : src folder (or) /WEB-INF/classes/
ClassLoader WebappClassLoader = Thread.currentThread().getContextClassLoader();
props.load(WebappClassLoader.getResourceAsStream("webprops.properties"));
To read properties from specific folder. Construct path form ProjectName
InputStream fileStream = new FileInputStream("propertyfolder/file.properties");
If Key:value pairs specified in .txt file then,
public static void readTxtFile_KeyValues() throws IOException{
props.load(new FileReader("keyValue.txt") );
// Display all the values in the form of key value
for (String key : props.stringPropertyNames()) {
String value = props.getProperty(key);
System.out.println("Key = " + key + " \t Value = " + value);
}
props.clear();
}

How do I create a zip file one folder up from the present working directory with NIO?

I'm having trouble using the URI class.
I can create a zip file in c:\ with code like this:
// Properties for archive file we're creating
Map<String, String> archiveProperties = new HashMap<>();
archiveProperties.put("create", "true");
archiveProperties.put("encoding", "UTF-8");
URI archiveLocation = URI.create("jar:file:/" + "my.zip");
// Create archive
FileSystem archive = FileSystems.newFileSystem(archiveLocation, archiveProperties);
But I really want the zip file to be created one directory up, if you will, from the present working directory. I've tried a lot of things, including:
// Properties for archive file we're creating
Map<String, String> archiveProperties = new HashMap<>();
archiveProperties.put("create", "true");
archiveProperties.put("encoding", "UTF-8");
URI archiveLocation = URI.create("jar:file:../" + "my.zip");
// Create archive
FileSystem archive = FileSystems.newFileSystem(archiveLocation, archiveProperties);
But I either get an exception, URI is not hierarchical in this case, or it continues to be created in c:\
I finally came up with a solution, albeit not very pretty:
// Properties for archive file we're creating
Map<String, String> archiveProperties = new HashMap<>();
archiveProperties.put("create", "true");
archiveProperties.put("encoding", "UTF-8");
String filePathName = System.getProperty("user.dir") + FILE_SEPARATOR + ".." + FILE_SEPARATOR + "myfile.zip";
filePathName = filePathName.replace('\\','/');
filePathName = filePathName.replaceAll(" ", "%20");
URI archiveLocation = URI.create("jar:file:///" + filePathName);
// Create archive
FileSystem archive = FileSystems.newFileSystem(archiveLocation, archiveProperties);
Note FILE_SEPARATOR came from System.getProperty(file.separator)
A quick fix will be to use this
URI archiveLocation = URI.create("jar:file:///"+new File(".").getAbsolutePath()+"/../my.zip");

Categories

Resources