Reading and Writing to file in resource folder Maven - java

I am writing code for reading and writing file which is present in src/main/resources folder of Maven project, but code is reading and writing to file present in "project/target/classes/config.properties", but what I need to read/write the file present in "project/src/main/resources/config.properties". Below is a piece of code, I written:
public class PropertyFileReader {
private static final Logger LOGGER = LoggerFactory
.getLogger(PropertyFileReader.class);
private static Properties prop;
static {
prop = new Properties();
}
public static void main(String[] args) {
String property = read("config.properties", "number");
System.out.println(property);
write("config.properties", "number", "6");
}
public static String read(final String fileName, final String propertyName) {
File file = getpropertyFile(fileName);
try (InputStream input = new FileInputStream(file)) {
prop.load(input);
} catch (IOException ex) {
LOGGER.error("Error occurred while reading property from file : ",
ex);
}
return prop.getProperty(propertyName);
}
public static void write(final String fileName, final String propertName,
String propertyValue) {
File file = getpropertyFile(fileName);
try (OutputStream output = new FileOutputStream(file)) {
prop.setProperty(propertName, propertyValue);
prop.store(output, null);
} catch (IOException io) {
LOGGER.error("Error occurred while writing property to file : ",
io);
}
}
private static File getpropertyFile(final String fileName) {
ClassLoader classLoader = PropertyFileReader.class.getClassLoader();
return new File(classLoader.getResource(fileName).getFile());
}
}
I also read various posts related to it, which suggest to make some changes in pom.xml with adding <RESOURCE_PATH>${project.basedir}/src/main/resources</RESOURCE_PATH>. But I am not understaning how should I do it.
Can you please guide me in implementing the same.
Thanks.

You can't edit files within a jar file. Instead you can create temporary files from files within a jar file.
static File stream2file(InputStream in) throws IOException {
File tempFile = File.createTempFile("stringOfYourChoice", ".tmp");
tempFile.deleteOnExit();
Files.copy(in, tempFile.toPath(), REPLACE_EXISTING)
return tempFile;
}

Related

read project directory to get properties file in java web application

Am trying to ready properties file which is presented in my project directory src/test/resources/properties/api/. But this way is not working and its give me file not found exception.
Please find my code below :
public Properties extractProperties() throws IOException {
InputStream configReader= null;
String env = getProperty("tuf.environment");
try {
configReader = new FileInputStream(new File("src/test/resources/properties/api/"+env+".properties")); // throwing exception
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
prop.load(configReader);
return prop;
}
I would do it the following way. Please note that the extractProperties() method will return an empty Properties object if the file was not found. Please also note the try-with-resources statement which will auto-close the InputStream.
public Properties extractProperties() throws IOException {
String env = getProperty("tuf.environment");
Properties prop = new Properties();
try (InputStream in = this.getClass().getResourceAsStream("/properties/api/" + env + ".properties")) {
prop.load(in);
} catch (Exception e) {
e.printStackTrace();
}
return prop;
}
Judging from your path you are using either Maven or Gradle as it looks like the default structure used by them. Which means src/test/resources points to the root of the classpath, so there is no src/test/resources. (The same applies to src/main/resources as well!).
So if you want to load it yuo would need to remove the src/test/resources part of the loading.
Next if this is run from a packaged application loading a File won't work as it isn't a File. The File needs to be a physical file on the filesystem and not inside an archive.
Taking all that into account you should be able to load the properties using the following
public Properties extractProperties() throws IOException {
String env = getProperty("tuf.environment");
String resource = "/properties/api/"+env+".properties";
try (InputStream in = getClass().getResourceAsStream(resource)) {
prop.load(in);
return prop;
}
}
Try something like below
public Properties extractProperties() throws IOException {
Properties prop=new Properties();
String env = getProperty("tuf.environment");
String mappingFileName = "/properties/api/" + env+ ".properties";
Resource resource = resourceLoader.getResource("classpath:" + mappingFileName);
try (InputStream inputStream = resource.getInputStream();
BufferedReader bufferedInputStream = new BufferedReader(new InputStreamReader(inputStream))) {
prop.load(bufferedInputStream);
} catch IOException ie) {
//handle exception
}
return prop;
}
Probably env is not what you think it is. Why not list all files in that directory?
You can print with https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/nio/file/Files.html#list(java.nio.file.Path)
With the relevant directory:
Path apiDir = Paths.get("src/test/resources/properties/api/");

How to load the correct language (set in config) instead of the language last in an array

I'm creating a little java app and I'm trying to load the yml files based on config.yml lang set (en/it) but I can't find a way to load them, only the last one in an array is loaded which is "it" for me.
I know that my method is probably the worst solution for a language file, I'm open to every method that will help me with the problem. But I prefer an external lang_en/it file instead of internal ones (Or is it better internal?)
After I set the language, the app will self-update every text in every class.
static final Properties props = new Properties();
static WelcomeMessage main = new WelcomeMessage();
static File file = null;
static File folder = null;
static boolean os = main.os.startsWith("Windows");
public static void create() {
String[] lang = {"en", "it"};
for (String s : lang) {
file = new File(WelcomeMessage.user + "/AppData/Roaming/MyApp/lang_" + s + ".yml");
folder = new File(file.getParent());
SetLanguages(s);
}
if (!file.exists()) {
try {
if (os) {
folder.mkdir();
file.createNewFile();
} else {
file = new File(main.user + "/Library/Application Support/MyApp/config.yml");
folder.mkdir();
file.createNewFile();
}
} catch (Exception e) {
System.out.println(e + " " + file);
}
}
}
public static void SetLanguages(String lang) {
if (lang.equals("en")) {
store("Settings.Save", "Save");
store("Settings.ConfigPath", "Config Path");
store("Settings.Language", "Language");
store("Settings.Title", "Settings");
} else if (lang.equals("it")) {
store("Settings.Save", "Salva");
store("Settings.ConfigPath", "Percorso config");
store("Settings.Language", "Lingua");
store("Settings.Title", "Impostazioni");
}
}
public static String get(String value) {
String key = null;
try {
FileInputStream in = new FileInputStream(file);
props.load(in);
key = props.getProperty(value);
in.close();
} catch (Exception fnf) {
System.out.println(fnf);
}
return key;
}
public static void store(String value, String key) {
try {
FileOutputStream out = new FileOutputStream(file);
props.setProperty(value, key);
props.store(out, null);
out.close();
} catch (Exception fnf) {
System.out.println(fnf);
}
}
This is how I get a text from yml:
path.setText(Language.get("Settings.ConfigPath"));
language.setText(Language.get("Settings.Language"));
f.setTitle(Language.get("Settings.Title"));
save.setText(Language.get("Settings.Save"));
And this my Language.get(key)
public static String get(String value) {
String key = null;
try {
FileInputStream in = new FileInputStream(file);
props.load(in);
key = props.getProperty(value);
in.close();
} catch (Exception fnf) {
System.out.println(fnf);
}
return key;
}
I suggest the following changes:
Create a Settings class to hold the properties save, configPath, language and title. Even better if this class uses an immutable builder pattern, because once set, the properties will never change.
Create a SettingsFactory class with method getSettings(language). This class shall also have a field Map<String, Settings>. In the constructor (or a static block), first check if a file exists on the disk, and if yes, load it into the map. If not, populate the map, one entry for each language, and persist to the disk.
getSettings would simply return the value from the map corresponding to the given language.
The format of the file written to the disk is a different matter. You say YAML, but I'm not seeing any YAML specific code in your snippet. If you don't know how to write a map to YAML, open a different question.

Java File.renamTo not working

I have made the code which renames all the jpg files in a directory from 1 to n (number of files)..
if there were let say 50 jpg files that after running the program all the files are renamed to 1.jpg ,2.jpg and so on till 50.jpg
But i am facing the problem if I manually rename the file let say 50.jpg to aaa.jpg then again running the program doesn't rename that file
I have wasted one day to resove that issue
Kindly help me
Code:
public class Renaming {
private static String path; // string for storing the path
public static void main(String[] args) {
FileReader fileReader = null; // filereader for opening the file
BufferedReader bufferedReader = null; // buffered reader for buffering the data of file
try{
fileReader = new FileReader("input.txt"); // making the filereader object and paasing the file name
bufferedReader = new BufferedReader(fileReader); //making the buffered Reader object
path=bufferedReader.readLine();
fileReader.close();
bufferedReader.close();
}
catch (FileNotFoundException e) { // Exception when file is not found
e.printStackTrace();
}
catch (IOException e) { // IOException
e.printStackTrace();
}
finally {
File directory=new File(path);
File[] files= directory.listFiles(); // Storing the all the files in Array
int file_counter=1;
for(int file_no=0;file_no<files.length;file_no++){
String Extension=getFileExtension(files[file_no]); //getting the filw extension
if (files[file_no].isFile() && (Extension .equals("jpg")|| Extension.equals("JPG"))){ // checking that if file is of jpg type then apply renaming // checking thaat if it is file
File new_file = new File(path+"\\"+files[file_no].getName()); //making the new file
new_file.renameTo(new File(path+"\\"+String.valueOf(file_no+1)+".jpg")); //Renaming the file
System.out.println(new_file.toString());
file_counter++; // incrementing the file counter
}
}
}
}
private static String getFileExtension(File file) { //utility function for getting the file extension
String name = file.getName();
try {
return name.substring(name.lastIndexOf(".") + 1); // gettingf the extension name after .
} catch (Exception e) {
return "";
}
}`
first of all, you should use the path separator / . It's work on Windows, Linux and Mac OS.
This is my version of your problem to rename all files into a folder provide. Hope this will help you. I use last JDK version to speed up and reduce the code.
public class App {
private String path = null;
public static int index = 1;
public App(String path){
if (Files.isDirectory(Paths.get( path ))) {
this.path = path;
}
}
public void rename() throws IOException{
if ( this.path != null){
Files.list(Paths.get( this.path ))
.forEach( f ->
{
String fileName = f.getFileName().toString();
String extension = fileName.replaceAll("^.*\\.([^.]+)$", "$1");
try {
Files.move( f ,Paths.get( this.path + "/" + App.index + "." + extension));
App.index++;
} catch (IOException e) {
e.printStackTrace();
}
}
);
}
}
public static void main(String[] args) throws IOException {
App app = new App("c:/Temp/");
app.rename();
}
}

Can't copy internal file to user's computer

I have a program that requires that an internal file (DICTIONARY) be copied to the user's computer into the folder defined like so:
private static final String DIC_NAME = "WordHelp.dic";
private static final String DIC_FOLDER = System.getProperty("user.home");
private static final String PATH_SEP = System.getProperty("file.separator");
public static final String DICTIONARY = DIC_FOLDER + PATH_SEP + DIC_NAME;
Here's what works on MY computer, where all the Java stuff is:
public static void createDictionaryIfNecessary() throws IOException{
Path out_path = FileSystems.getDefault().getPath(DICTIONARY);
boolean dic_exists = Files.exists(out_path,
new LinkOption[]{LinkOption.NOFOLLOW_LINKS});
if(dic_exists)
return;
File file = new File("src/dictionary"); // here's problem for user ************
Path in_path = file.toPath();
try {
Files.copy(in_path, out_path,
REPLACE_EXISTING, COPY_ATTRIBUTES, NOFOLLOW_LINKS);
} catch (IOException e) { JOptionPane.showMessageDialog(null, e); }
}
But user gets this error:
java.nio.file.NoSuchFileException: src\dictionary
SOURCE file (internal to .jar file) can't be found.
If I look at in_path while debugging, the value is:
(sun.nio.fs.Windowspath) src/dictionary
And below is a bunch of info about in_path:
This all works on MY computer and I could have sworn that it ONCE worked on a user's computer...
How should I define file (see line with ********** to enable copying internal file (src/dictionary) onto a user's computer?
Here's Netbeans project view:
I worked around it by using a Scanner to read individual strings from the internal file instead of using Files.copy. Here's the code. (It's not quite as fast using Scanner, but it works.)
public static void write(FileOutputStream outfile, String s) {
try {
for(int i = 0; i < s.length(); i++)
outfile.write(s.charAt(i));
outfile.write(13); outfile.write(10);
} catch (IOException ex) {JOptionPane.showMessageDialog(null, ex);}
}
public static Scanner openDic(){
InputStream myStream = null;
try { myStream = Class.forName("masterwords.Masterwords").getClassLoader()
.getResourceAsStream("dictionary");
}catch (ClassNotFoundException ex) {/* ... */}
return new Scanner(myStream).useDelimiter("\r");
}
public static void createDictionaryIfNecessary(){
Path out_path = FileSystems.getDefault().getPath(DICTIONARY);
if(Files.exists(out_path, new LinkOption[]{LinkOption.NOFOLLOW_LINKS})) return;
FileOutputStream outStream = null;
try {outStream = new FileOutputStream(out_path.toFile());}
catch (FileNotFoundException ex) {JOptionPane.showMessageDialog(null,ex);}
Scanner scInternalDic = IO.openDic();
while(scInternalDic.hasNext()){
Utilities.write(outStream,scInternalDic.next());
}
try {outStream.close();}
catch (IOException ex) {JOptionPane.showMessageDialog(null,ex);}
scInternalDic.close();
}

Load java properties inside static initializer block

I have a static util class that does some string manipulation on a bit sensitive data.
Prior to use of this class I need to initialize certain static variables with values, such as usernames/password, that I prefer to store in a .properties file.
I am not very familiar with how loading of .properties file work in Java, especially outside of *Spring DI *container.
Anyone can give me a hand/insight on how this can be done?
Thank you!
Addition: .properties file precise location is unknown, but it will be on the classpath. Sorta like classpath:/my/folder/name/myproperties.propeties
First, obtain an InputStream from which the properties are to be loaded. This can come from a number of locations, including some of the most likely:
A FileInputStream, created with a file name that is hard-coded or specified via a system property. The name could be relative (to the current working directory of the Java process) or absolute.
A resource file (a file on the classpath), obtained through a call to getResourceAsStream on the Class (relative to the class file) or ClassLoader (relative to the root of the class path). Note that these methods return null if the resource is missing, instead of raising an exception.
A URL, which, like a file name, could be hard-coded or specified via a system property.
Then create a new Properties object, and pass the InputStream to its load() method. Be sure to close the stream, regardless of any exceptions.
In a class initializer, checked exceptions like IOException must be handled. An unchecked exception can be thrown, which will prevent the class from being initialized. That, in turn, will usually prevent your application from running at all. In many applications, it might be desirable to use default properties instead, or fallback to another source of configuration, such as prompting a use in an interactive context.
Altogether, it might look something like this:
private static final String NAME = "my.properties";
private static final Properties config;
static {
Properties fallback = new Properties();
fallback.put("key", "default");
config = new Properties(fallback);
URL res = MyClass.getResource(NAME);
if (res == null) throw new UncheckedIOException(new FileNotFoundException(NAME));
URI uri;
try { uri = res.toURI(); }
catch (URISyntaxException ex) { throw new IllegalArgumentException(ex); }
try (InputStream is = Files.newInputStream(Paths.get(uri))) { config.load(is); }
catch (IOException ex) { throw new UncheckedIOException("Failed to load resource", ex); }
}
Check out java.util.Properties.
You can use a static initializer. So on the top of the class you can do:
static {
Properties props = new Properties();
InputStream steam = ...; // open the file
props.load(stream);
// process properties content
String username = props.getProperty("username");
}
Use either:
CurrentClassName.class.getResourceAsStream
new FileInputStream(File)
to get the input stream depending on if the class is in or out of the classpath. Then use
Properties.load
to load the properties.
It's been a while, but if I remember correctly you just do something like this:
Properties prop = new Properties();
prop.load(new FileInputStream(filename));
//For each property you need.
blah = prop.getProperty(propertyname);
Well with static Properties it would make sense to initialize them as a Singleton which will be loaded once in a class. Here's an example:
class Example
{
public final static String PROPSFILE = "test.properties";
private static Properties props;
protected static Properties getProperties()
{
if(props == null)
{
props = new Properties();
props.load(new FileInputStream(new File(PROPSFILE));
}
return props;
}
public static User getUser()
{
String username = getProperties().getProperty("username");
return new User(username);
}
}
If you use relative Pathnames you should make sure, that your classpath is setup righ.
for me MyClass.class.getClassLoader().getResourceAsStream(..) did the trick:
private static final Properties properties;
static {
Properties fallback = new Properties();
fallback.put(PROP_KEY, FALLBACK_VALUE);
properties = new Properties(fallback);
try {
try (InputStream stream = MyClass.class.getClassLoader().getResourceAsStream("myProperties.properties")) {
properties.load(stream);
}
} catch (IOException ex) {
// handle error
}
}
I agree with #Daff, maybe better to use singleton class...this what i have on my project for similar requirement, maybe it may help:
clients of the class can use it like this:
ConfigsLoader configsLoader = ConfigsLoader.getInstance("etc/configs.xml");
System.out.format("source dir %s %n", configsLoader.getSourceDir());
and then the class:
public class ConfigsLoader {
private String sourceDir;
private String destination;
private String activeMqUrl;
private static Logger log = Logger.getLogger(ConfigsLoader.class.getName());
private static ConfigsLoader instance = null;
private ConfigsLoader(String configFileName) {
log.info("loading configs");
Properties configs = new Properties();
try {
configs.loadFromXML(new FileInputStream(configFileName));
sourceDir = configs.getProperty("source.dir");
destination = configs.getProperty("destination");
activeMqUrl = configs.getProperty("activemqconnectionurl");
configs.setProperty("lastLoaded", new SimpleDateFormat("yyyy-M-d HH:mm").format(new Date()));
configs.storeToXML(new FileOutputStream(configFileName), "saving last modified dates");
} catch (InvalidPropertiesFormatException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (IOException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
}
}
public static ConfigsLoader getInstance(String configFileName) {
if(instance ==null) {
instance = new ConfigsLoader(configFileName);
}
return instance;
}
public String getSourceDir() {
return sourceDir;
}
public void setSourceDir(String sourceDir) {
this.sourceDir = sourceDir;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getActiveMqUrl() {
return activeMqUrl;
}
public void setActiveMqUrl(String activeMqUrl) {
this.activeMqUrl = activeMqUrl;
}
}
I did this finally using getResourceAsStream() fuction associated with the class in which the static code block is being written.
//associate Property and ImputStream imports
public class A {
static Properties p;
static {
p = new Properties();
try {
InputStream in = A.class.getResourceAsStream("filename.properties");
p.load(in);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException");
e.printStackTrace();
}
}
.
.
.
}

Categories

Resources