How to separate key value pairs with comma in Java properties file - java

Currently, my property file output looks like this
Name=Frank
Email=frank#mail.com
based on the following codes
File prop = new File(".properties");
if (!prop.exists()) {
prop.createNewFile();
}
try {
FileReader reader = new FileReader(prop);
Properties properties = new Properties();
properties.load(reader);
reader.close();
properties.setProperty("Name", name);
properties.setProperty("Email", email);
FileWriter writer = new FileWriter(prop);
properties.store(writer, "Settings");
writer.close();
} catch (IOException ex) {
Logger.getLogger(PropertiesTest.class.getName()).log(Level.SEVERE, null, ex);
}
I want it to be written in one line, with each key value pair separated by a comma. So it will look like this
Name=Frank, Email=frank#mail.com
How can I achieve this? Or is there a way to group each Name and Email key value pairs with a unique identifier?
Basically, I want to have multiple Name and Email entries in one property file and to be able to get each of the entry.

The properties file is not designed to do this. You should instead use CSV, JSON, YAML, XML (but probably XML is too complicated for this use case) or a database.

Related

Android studio, File.properties deleted after reopening the app

I saved a File.properties in this.getFilesDir() + "Data.propertie".
In the app, I save the data that the user wrote, but when i open the app, all the data (or the file) that I saves from the previous time has been deleted.
Example:
// Store
for (Map.Entry<String,String> entry : MainActivity.Notes.entrySet()) { // Put all data from Notes in properties to store later
properties.put(entry.getKey(), entry.getValue());
}
try { properties.store(new FileOutputStream(this.getFilesDir() + "data.properties"), null); } // Store the data
catch (IOException e) { e.printStackTrace(); } // Error exception
// Load the map
Properties properties = new Properties(); // Crate properties object to store the data
try {
properties.load(new FileInputStream(this.getFilesDir() + "data.proprties")); } // Try to load the map from the file
catch (IOException e) { e.printStackTrace(); } // Error exception
for (String key : properties.stringPropertyNames()) {
Notes.put(key, properties.get(key).toString()); // Put all data from properties in the Notes map
}
// Can load the data
You can see that i saved the data in the file, and I can load it, but when I open the app, the data has been deleted
There is a way to write in the file and save the data that i write to the next time I open the app?
First off Context.getFilesDir returns a File object. This File represents the private data directory of your app.
Then you do getFilesDir() + "foo" which will implicitly call toString() on the File instance. File.toString() is equivalent to File.getPath which does not necessarily return a trailing slash.
This means, if getFilesDir() returns a File at /data/app, your properties file will become /data/appdata.properties which is not in your data Folder and cannot be written to.
Instead, to get a File within a directory you can create a new File instance with that directory. e.g:
File propertiesFile = new File(this.getFilesDir(), "data.properties");
// use propertiesFile for FileOutputStream/FileInputStream etc.
This ensures that your properties file is within that directory and prevents any issues from file separators

CSVPrinter datas appears not separated in columns

I'm trying to use this library commons-csv (1.5) for generating the csv file, i've make a simple program for seeing the result :
String SAMPLE_CSV_FILE = "./sample.csv";
try (
BufferedWriter writer = Files.newBufferedWriter(Paths.get(SAMPLE_CSV_FILE));
CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.EXCEL
.withHeader("ID", "Name", "Designation", "Company"));
) {
csvPrinter.printRecord("1", "Name1 ", "CEO", "Google");
csvPrinter.printRecord("2", "Name2", "CEO", "Microsoft");
csvPrinter.flush();
}
My CSV is well generated but the header and the data isnt separated in each column, When I open the CSV file, I see all the data and header in the first column
I dont found yet the good CSVFormat, how to separate them ?
The selected answer does not really show how you can make sure that comma is set as the delimiter.
To tell excel that comma should be used as a delimiter, Print printer.printRecord("SEP=,"); as the first record in your file. its a command that excel understands and it will not show in your file output.
try (CSVPrinter printer = new CSVPrinter(new FileWriter("file.csv"),CSVFormat.EXCEL)) {
printer.printRecord("SEP=,"); //this line does the margic.
printer.printRecord("Column A","Column B","Column C");
} catch (IOException ex) {
}
When I run your program, I get all the columns separated by comma's as expected. If you're using Excel to open the file, make sure you have selected the comma as the delimiter instead of the tab.

how to write a string which starts with - into csv file?

I am trying to write data to CSV file.
The string value which starts with - is getting converted to #NAME? automatically when i open csv file after writing. e.g. If i write test it displays correctly but when i write -test the value would be #NAME? when i open csv file. It is not a code issue but csv file automatically changes the value which starts with - to error(#NAME?). How can i correct this programmatically. below is the code,
public class FileWriterTest {
public static void main(String[] args) {
BufferedWriter bufferedWriter = null;
File file = new File("test.csv");
try {
bufferedWriter = new BufferedWriter(new FileWriter(file));
List<String> records = getRecords();
for (String record : records) {
bufferedWriter.write(record);
bufferedWriter.newLine();
}
bufferedWriter.flush();
System.out.println("Completed writing data to a file.");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedWriter != null)
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static List<String> getRecords() {
List<String> al = new ArrayList<String>();
String s1 = "test";
String s2 = "-test";
al.add(s1);
al.add(s2);
return al;
}
}
Could you please assist?
It's a problem with excel. When you open a CSV file in excel it tries to determine cell type automatically which usually fails. The CSV file is alright the editor is not ;)
You can either right click on the field, select Format Cell and there make it a text file (and you might need to remove the automatically inserted '=' sign). Or you can open the CSV file by going into Data - From Text/CSV and in the wizard select the proper column types.
In the formal CSV standard, you can do this by using quotes (") around the field value. They're a text delimiter (as opposed to other kinds of values, like numeric ones).
It sounds like you're using Excel. You may need to enable " as a text delimiter/indicator.
Update: If you double-click the .csv to open it in Excel, even this doesn't work. You have to open a workbook and then import the CSV data into it. (Pathetic, really...)
I got a relatively old version of Excel (2007), and the following works perfectly:
Put the text between double quotes and preceed it with an equal sign.
I.e., -test becomes ="-test".
You file will therefore look like this:
test1,test2,test3
test4,="-test5",test6
UPDATE
Works in Excel-2010 as well.
As Veselin Davidov mentioned, this will break the csv standard but I don't know whether that's a problem.

Unwanted backslash added to file saved by java method

In my spring project, one of my service classes has this method to save a file named database.properties in disk:
public void create_properties(String maquina, String usuario, String senha) {
System.out.println("create_properties");
Properties props = new Properties();
props.setProperty("jdbc.Classname", "org.postgresql.Driver");
props.setProperty("jdbc.url", "jdbc:postgresql://"+maquina+"/horario" );
props.setProperty("jdbc.user", usuario );
props.setProperty("jdbc.pass", senha );
props.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
props.setProperty("hibernate.show_sql", "false");
props.setProperty("hibernate.hbm2ddl.auto", "validate");
FileOutputStream fos;
try {
fos = new FileOutputStream( "database.properties" );
props.store( fos, "propriedades" );
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
My problem is that the property jdbc:url should be something like that:
jdbc:postgresql://localhost:5432/horario
But what is being saved is this:
jdbc\:postgresql\://localhost\:5432/horario
Anyone can tell me how to avoid this backslashes to be included?
It's doing exactly the right thing - you're saving a properties file, which escapes things like colons using backslashes. From the documentation for Properties.store:
Then every entry in this Properties table is written out, one per line. For each entry the key string is written, then an ASCII =, then the associated element string. For the key, all space characters are written with a preceding \ character. For the element, leading space characters, but not embedded or trailing space characters, are written with a preceding \ character. The key and element characters #, !, =, and : are written with a preceding backslash to ensure that they are properly loaded.
If you load the properties file in using Properties.load, you'll get the original string back in the Properties object.
If you don't want to store the value in a properties file, use a Writer and just write the string directly.

How to replace the contents of a file after processing

Let's say that I have a TreeMap and I want to take all values for a key, make a file with these, pass the file to another process loop and do this for every map key, so I always have to use the same file but its content must be replaced every time for each key.
What I do is:
PrintWriter writeRatings = new PrintWriter("ratings.txt", "UTF-8");
TreeMap<Integer, ArrayList<Rating>> ratings = new TreeMap<Integer, ArrayList<Rating>>();
-->
for(Integer clID:ratings.keySet()){
ArrayList<Rating> ratingGroup = ratings.get(clID);
for(Rating r:ratingGroup){
witer.println(r.toString());
}
}
writer.flush();
writer.close();
With this, I get a file with all the data for each map key. Can you suggest how can I get only the data from the current key each time in the file?
If you want to use the same file and just append lines to it, use a FileWriter and set the append mode to true
PrintWriter writer = new PrintWriter(new FileWriter("filename", true));
This will append lines to the file, instead of over writing the file. This way, different processes can use the same file and keep on adding new data to the file
So what worked for me was to include this line into the for loop in the position of the arrow in the main question post:
PrintWriter writer = new PrintWriter(new FileWriter("filename"));

Categories

Resources