I have a properties file 1, which after ordering it and eliminating duplicates, I save it in a new properties file 2. My problem is that when saving my properties, the store method is interpreting the text of my property and saves it interpreted, not as it is.
This is my method:
void saveProperties(Properties properties) {
File file = new File("C:\\Files\\new.properties");
FileOutputStream fileOutputStream = new FileOutputStream(file);
properties.store(fileOutputStream, "Properties");
}
This is my store method Override, so it doesn't add escape characters:
public void store(OutputStream out, Properties properties) throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
bw.write("#" + new Date().toString());
bw.newLine();
synchronized (this) {
for (Enumeration e = properties.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
String val = (String) properties.get(key);
// Commented out to stop '/' or ':' or '#' chars being replaced
// key = saveConvert(key, true, escUnicode);
// val = saveConvert(val, false, escUnicode);
bw.write(key + "=" + val);
bw.newLine();
}
}
bw.flush();
}
These are my two test properties.:
myPropertieTest1=Sure?\\nplease click \\'here\\' to see more info.
myPropertieTest2=Requirements\:<br/>\n" + "name, surname, address.
And this is the result saved in my new properties file:
mypropertietest1=Sure?\nplease click \'here\' to see more info.
mypropertietest2=Requirements:<br/>
" + "name, surname, address.
The escape characters disappear, even in Test2 the property is saved in two lines because the line breaks are interpreted.
I am not sure how you are loading the properties value, but when I tried it on local it works without this issue:
public class Demo{
public static void main(String[] args) throws IOException {
Demo demo = new Demo();
FileReader reader = new FileReader("old.properties");
Properties prop = new Properties();
prop.load(reader);
demo.saveProperties(prop);
}
void saveProperties(Properties properties) throws IOException {
File file = new File("new.properties");
FileOutputStream fileOutputStream = new FileOutputStream(file);
properties.store(fileOutputStream, "Properties");
}
}
Related
I have a set of words and an outside file.
I want to check if a word in the set is already present in the outside file. If the word is already in the file, then do nothing, if the word is not in the outside file already, then add it to the outside file.
This is the code I have written:
public static void toFile(Set<String> vocab, String filename)
{
try
{
for(String vocabWord : vocab)
{
File file = new File(filename);
Scanner sc2 = new Scanner(file);
while(sc2.hasNextLine())
{
String docWord = sc2.nextLine();
if (!(vocabWord.equals(docWord)))
{
FileWriter myWriter = new FileWriter(filename, true);
PrintWriter printWriter = new PrintWriter(myWriter);
printWriter.println(vocabWord);
printWriter.close();
}
else
break;
}
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
I am using three different text documents to test it, have the line "test file one", "test file two", and "test file three".
The output I was expecting was: "test file three" (it is connected with a stop list which one and two are part of, and has been working)
However, when I run it, either with only one of the files or all three consecutively, the file always comes out empty.
I tried changing up things in the method, but nothing has worked, I either get an infinite loop or nothing in the outside file.
I am not sure what I am missing... I would really appreciate any help.
I tried this and added some comments for explanation. I have tested on local machine and it works
public static void toFile(Set<String> vocab, String filename) {
try {
for(String vocabWord : vocab) {
//task for each String in our Set
File file = new File(filename);
Scanner sc2 = new Scanner(file);
boolean exists = false;//lets say it doesn't exist
while(sc2.hasNextLine()) {
//task for each line in the text
//search the whole file first for the word
String docWord = sc2.nextLine();
if (docWord.equals(vocabWord)){
exists = true;
break;
}
}
if (!exists) {
//add the vocabWord only if it doesnt exists
FileWriter myWriter = new FileWriter(filename, true);
PrintWriter printWriter = new PrintWriter(myWriter);
printWriter.println(vocabWord);
printWriter.close();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
To append the missing vocabulary in order of vocab, you can reduce the file operations
as such:
public static void toFile(Set<String> vocab, String filename) {
try {
Charset charset = Charset.defaultCharset();
Path path = Paths.get(filename);
Set<String> existing = Files.lines(path, charset)
.collect(Collectors.toSet());
if (!existing.isEmpty()) {
try (BufferedWriter bw = Files.newBufferedWriter(path, charset,
StandardOpenOption.APPEND);
PrintWriter printWriter = new PrintWriter(bw)) {
vocab.stream()
.filter(word -> !existing.contains(word))
.forEach(word -> printWriter.println(word));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
I am using JUnit Test for testing purposes, but I am facing a problem of AssertionFailedError.
I am using command line arguments to pass Test cases to the main class.
Below is my Main.java code
public class Main {
public static void main(String[] args) throws IOException {
//Storing all the commands, words, files
ArrayList<String> commands = new ArrayList<>();
ArrayList<String> words = new ArrayList<>();
ArrayList<String> files = new ArrayList<>();
for(String arg: args){
if(arg.contains("."))
files.add(arg);
else if(arg.contains("-") && !arg.contains("--"))
commands.add(arg);
else{
if(!arg.contains("--"))
words.add(arg);
}
}
for(String file : files ){
File originalFile = new File(file);
//CHECK IF textFile exists
if(originalFile.exists()){
if(words.size() == 2){
String from = words.get(0), to=words.get(1);
BufferedWriter bw;
//If file exists then check command
for(String command : commands){
if(command.trim().contains("-f")){
File temp = new File("Temp.txt");
temp.createNewFile();
//If Temp.exists
if(temp.exists()){
bw = new BufferedWriter(new FileWriter(temp));
//Fetch all the lines from Orginal File
List<String> lines = Files.readAllLines(Paths.get(originalFile.getName()));
//Add to treemap
TreeMap<Integer,String> tm = new TreeMap<>();
for(int i=0;i<lines.size();i++){
tm.put(i,lines.get(i));
}
//To check first occurence of word in hashmap
for(int i=0;i<tm.size();i++){
String lastLine = tm.get(i);
tm.remove(i);
tm.put(i,lastLine.replaceFirst(from,to));
if(!lastLine.equals(tm.get(i)))
break;
}
//Write treemap to the text file
for(String line: tm.values())
bw.write(line.trim() + "\n");
System.out.println("First Occurence " + originalFile.getName()+ " changed");
bw.close();
originalFile.delete();
temp.renameTo(originalFile);
}else
System.out.println("Error in creating Temp.txt file");
}
}
}
Everything is working fine, the file is created. I dont think there is error in the code. Below is the MainTest.java
public class MainTest {
// Some utilities
private File createInputFile1() throws Exception {
File file1 = new File("Test.txt");
try (FileWriter fileWriter = new FileWriter(file1)) {
fileWriter.write("Dog is an animal");
}
return file1;
}
private String getFileContent(String filename) {
String content = null;
try {
content = new String(Files.readAllBytes(Paths.get(filename)));
} catch (IOException e) {
e.printStackTrace();
}
return content;
}
// Actual test cases
#Test
public void mainTest2() throws Exception {
File inputFile1 = createInputFile1();
String args[] = {"-f", "Dog", "Cat", "--", "Test.txt"};
Main.main(args);
String expected1 = "Cat is an animal".trim();
String actual1 = getFileContent("Test.txt");
assertEquals("The files differ!", expected1, actual1);
assertTrue(Files.exists(Paths.get(inputFile1.getPath() + ".bck")));
}
}
Everything works fine, file Test.txt is created and it has the text in it.
But I am facing this error of AssertionFailedError: The files differ! expected: Cat is an animal[] but was: Cat is an animal[ ]
Why does it differ [] and [ ] ?
Try this, shall help :
String expected1 = "Cat is an animal".trim();
String actual1 = getFileContent("Test.txt").trim();
assertEquals("The files differ!", expected1, actual1);
Since what trim does is
* #return A string whose value is this string, with any leading and trailing white
* space removed, or this string if it has no leading or
* trailing white space.
hence you see a diff of space [ ] and [] with your solution and its resolved using trim in both.
I want to write in properties file without removing earlier written values in file.
for Eg there is value in properties file
token = tokengenerated
Now when I again set new value like
token1 = tokensnew
Then the properties file should show
token = tokengenerated
token1 = tokensnew
Pass true as a second argument to FileWriter to turn on "append" mode.
fout = new FileWriter("filename.txt", true);
FileWriter usage reference
You should read file and update it through properties and streams.
below is the code snippet is help you.
public class ReadAndWriteProperties {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
String propertiesFileName = "config.properties";
File f = new File(propertiesFileName);
InputStream input = new FileInputStream(f);
if (input != null) {
props.load(input);
props.setProperty("token2", "tokensnew");
OutputStream out = new FileOutputStream(f);
props.store(out, "save");
}
}
}
You must read the file (var1), then add your content to the var1 and then write the var1 to the file.
I am currently making a game in java with random world gen, at the beginning of the game I want it to store the tile ID, the X position, and the Y position so that when I re-load the game it will be able to generate it again.
When I write my file it all works but I have one issue, the output to the file is a weird combination of characters.
Code:
import java.io.*;
public class FileWrite {
public static FileWriter writeFile;
public static BufferedWriter write;
public static void recordItem(int blockID, int blockX, int blockY, String filePath, String fileName) throws Exception {
writeFile = new FileWriter("res/save/" + filePath+ fileName, true);
write = new BufferedWriter(writeFile);
write.write(blockID);
write.write(blockX);
write.write(blockY);
write.newLine();
write.flush();
}
}
Output in file:
#
`
?
?
?
?
?
?
?
?
?
How do I encode my FileWriter to UTF-8 so it displays numbers? Thanks for the help. :)
Just a suggestion, if you would like to make a little more robust form of your persistent info, you might consider object serialization. It's easier than it sounds. Just have a static inner class that implements Serializable, something like this:
static class JunkRec implements Serializable
{
private static final long serialVersionUID = 1L;
final int _blockID, _blockX, _blockY;
final String _filePath, _fileName;
public JunkRec(int blockID, int blockX, int blockY,
String filePath, String fileName)
{
_blockID = blockID;
_blockX = blockX;
_blockY = blockY;
_filePath = filePath;
_fileName = fileName;
}
#Override
public String toString() {
return String.format("id=%08d x=%04d y=%04d fp=%s fn=%s",
_blockID, _blockX, _blockY, _filePath, _fileName);
}
}
Now, one method to store a JunkRec...
public static void storeJunk(JunkRec jr)
{
try (
FileOutputStream fos = new FileOutputStream(
jr._filePath + jr._fileName + ".ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);) {
oos.writeObject(jr);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
Another method to restore a JunkRec, given the filename.
public static JunkRec retrieveJunk(String filePath, String fileName)
{
try (
FileInputStream fis = new FileInputStream(
filePath + fileName + ".ser");
ObjectInputStream ois = new ObjectInputStream(fis);) {
return (JunkRec) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
And finally a little test driver in main()...
public static void main(String[] args)
{
// generate and restore 10 records
Random r = new Random();
List<String> names = new ArrayList<>();
/* do a few in two ways */
for (int i = 0; i < 5; ++i) {
int blk = r.nextInt(10000);
String fname = String.format("BLKID_%02d", i);
if (names.add(fname)) {
JunkRec jr = new JunkRec(
r.nextInt(10000),
r.nextInt(50),
r.nextInt(50),
"/tmp/",
fname);
storeJunk(jr);
System.out.println("Wrote: "+jr);
}
}
/* read them all back */
for (String fname : names) {
JunkRec jr = retrieveJunk("/tmp/", fname);
System.out.println("Retrieved: " + jr + " from " + fname);
}
/* clean up */
for (String fname : names) {
((File) new File("/tmp/" + fname + ".ser")).delete();
}
}
This is not production-quality code, but it shows how easy serialization can be. There are a gotchas, but in general Serialization is a solid solution for file-based persistence.
Just a suggestion. Have fun!
The write method writes a single character, so you're writing characters with the Unicode codepoint of blockID, blockX, blockY which is not what you want.
Whether your Writer is encoded as UTF-8 is not so relevant here, although it is always good to be explicit about encoding if you want your files to be portable across machines, so try new OutputStreamWriter(new FileOutputStream("res/save/" + filePath+ fileName, true), "UTF-8"); instead of creating a FileWriter directly. Creating it directly doesn't allow you to specify the encoding.
Instead do something like this:
writer.write(String.format("%d %d %d\n", blockID, blockX, blockY));
This will format your three numbers as one string on one line before sending it to the file.
Note that you shouldn't create a new Writer/BufferedWriter every time that you want to write a line. You should keep them in a class field and re-use the same writer. You also need to close the file after you are done with it, since the operating system has a limit to the number of files that you have open at the same time, and you will run out of that number quickly with your current code.
I'm trying to read a file from a filepath read from properties, but I keep getting FileNotFoundException (the file exists).
test.properties:
test.value = "src/main/resources/File.csv"
LoadProperties.java:
public class LoadProperties {
public static void main(String[] args) throws FileNotFoundException, IOException {
Properties aProp = new Properties();
aProp.load(new FileInputStream("src/main/resources/test.properties")); // works
String filepath = aProp.getProperty("test.value");
System.out.println(filepath); // outputs: "src/main/resources/File.csv"
FileReader aReader = new FileReader("src/main/resources/File.csv"); // works
FileReader aReader2 = new FileReader(filepath); // java.io.FileNotFoundException
}
}
Why is this exception being thrown while the line above it works just fine?
How should I read a file from a path provided with properties?
You are not supposed to put " in your property file. Here Java sees it as :
String file = "\"src/main/resources/File.csv\"";
test.value =src/main/resources/File.csv
You don't need double quotes in properties file to represent a continuous string.
you can write own logic to read properties file, it does not matter whether single quotes or double quotes are there in the file path
String propertyFileLocation = "C:\a\b\c\abc.properties";
try
{
fileInputStream = new FileInputStream(propertyFileLocation);
bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
properties = new Properties();
String currentLine = null;
String[] keyValueArray = null;
while ((currentLine = bufferedReader.readLine()) != null) {
if (!currentLine.trim().startsWith("#")) {
keyValueArray = currentLine.split("=");
if (keyValueArray.length > 1) {
properties.put(keyValueArray[0].trim(), keyValueArray[1].trim().replace("\\\\","\\"));
}
}
}
}
catch (Exception e)
{
return null;
}