Why does introducing a FileWriter delete all the content in the file? - java

I have a text file with some text in it and i'm planning on replacing certain characters in the text file. So for this i have to read the file using a buffered reader which wraps a file reader.
File file = new File("new.txt");
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
But since i have to edit characters i have to introduce a file writer and add the code which has a string method called replace all. so the overall code will look as given below.
File file = new File("new.txt");
FileWriter fw = new FileWriter(file);
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
fw.write(br.readLine().replaceAll("t", "1") + "\n");
}
Problem is when i introduce a file writer to the code (By just having the initialization part and when i run the program it deletes the content in the file regardless of adding the following line)
fw.write(br.readLine().replaceAll("t", "1") + "\n");
Why is this occurring? am i following the correct approach to edit characters in a text file?
Or is there any other way of doing this?
Thank you.

public FileWriter(String fileName,
boolean append)
Parameters:
fileName - String The system-dependent filename.
append - boolean if true, then data will be written to the end of the
file rather than the beginning.
To append data use
new FileWriter(file, true);

The problem is that you're trying to write to the file while you're reading from it. A better solution would be to create a second file, put the transformed data into it, then replace the first file with it when you're done. Or if you don't want to do that, read all of the data out of the file first, then open it for writing and write the transformed data.
Also, have you considered using a text-processing language solution such as awk, sed or perl: https://unix.stackexchange.com/questions/112023/how-can-i-replace-a-string-in-a-files

You need to read the file first, and then, only after you read the entire file, you can write to it.
Or you open a different file for writing and then afterwards you replace the old file with the new one.
The reason is that once you start writing to a file, it is truncated (the data that was in the file is deleted).
The only way to avoid that is to open the file in "append" mode. With that mode, you start writing at the end of the file, so you don't delete its content. However, you won't be able to modify the existing content, you will only add content.

Maybe like this
public static void main(String[] args) throws IOException {
try {
File file = new File("/Users/alexanderkrum/IdeaProjects/printerTest/src/atmDep.txt");
Scanner myReader = new Scanner(file);
ArrayList<Integer> numbers = new ArrayList<>();
while (myReader.hasNextLine()) {
numbers.add(myReader.nextInt() + 1);
}
myReader.close();
FileWriter myWriter = new FileWriter(file);
for (Integer number :
numbers) {
myWriter.write(number.toString() + '\n');
}
myWriter.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}

Just add at last :
fw.close();
this will close it ,then it will not delete anything in the file.
:)

Related

Read UTF-8 properties file and save as UTF-8 txt file

I am currently trying to analyze all of my properties files and need my properties files in the form of a .txt file for one part. The problem is that german "Umlaute" like Ä,Ü,Ö etc. are not taken over correctly and therefore my program does not work. (If I convert the files manually into a txt there are no problems, but the whole thing should run dynamically)
Here is my code I am currently using:
private static void createTxt(String filePath, String savePath) throws IOException {
final File file = new File(filePath);
final BufferedReader bReader = new BufferedReader(new FileReader(file.getPath()));
final List<String> stringList= new ArrayList<>();
String line = bReader.readLine();
while (line != null) {
stringList.add(line);
line = bReader.readLine();
}
final Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(savePath), "UTF-8"));
try {
for (final String s : stringList) {
out.write(s + "\n");
}
}
finally {
out.close();
}
}
The encoding of the txt is also UTF-8 - I think the problem is due to the bufferedReader or caching into the ArrayList
Thank you for your time and help,
LG Pascal
When reading and writing files you should always set a charset. FileReader has a constructor that takes a Charset.
new FileReader(file, StandardCharsets.UTF_8)
If you just want to read all lines from a file just use Files.readAllLines(path, StandardCharsets.UTF_8);
To write you can use Files.write(path, listOfStrings, StandardCharsets.UTF_8);
And if you only want to copy the files, just use Files.copy(source, target);

How to get my delete function to delete an entire line that contains what I entered, as opposed to just what I entered?

I have a function that adds, searches, and deletes lines from a text file. The Search works irrelevant of case and has a .contains which allows it to work on less than the whole line. The delete function only deletes the exact match. I'm accessing an outside .txt file which is saving the changes that are made.
I tried duplicating my search code, but was unable to produce the same result. I'd also like to completely remove the line so that my table remains clean looking if I don't delete that last entry, but that's less important.
System.out.println("What would you like to delete");
Scanner deleteScanner = new Scanner(System.in);
String deleteInput = deleteScanner.nextLine();
try{
File file = new File("contacts.txt");
File temp = File.createTempFile("file", ".txt",
file.getParentFile());
BufferedReader reader = new BufferedReader(new
InputStreamReader(new FileInputStream(file)));
PrintWriter writer = new PrintWriter(new
OutputStreamWriter(new FileOutputStream(temp)));
for (String line; (line = reader.readLine()) != null;) {
line = line.replace(deleteInput, "");
writer.println(line);
}
reader.close();
writer.close();
file.delete();
temp.renameTo(file);
} catch (IOException e){
e.printStackTrace();
}
I feel like .contains should work but I haven't been able to make it function as intended.
You could get all file lines easier by using:
List<String> lines = Files.readAllLines(Paths.get(path), Charset.defaultCharset());
After that you can simple iterate thru the lines List and delete the whole line if it contains deleteInput:
for (String line : lines) {
if (line.contains(deleteInput)) {
lines.remove(line);
}
}
If there is a need to find the occupies ignoring case you can use toLowerCase() before each check.

How can I get this buffered writer to write one line at a time? JAVA

I am creating a little program that will amend driver letters saved in a program file. The method works in the sense that it locates the file correctly and amends the drive letter correctly.
However when I open the file after it has been changed all the Directory listings are all on one line but they need to be 1 directory per line. I've tried saving each individual line to an Array List then printing them out like that but that didn't seem to work for me so was wondering if anyone could help?
Much appreciated.
P.S. Been messing around trying to make it work and also now ran into another issue where it is now printing them all out into one line but with spaces in between e.g:
S:\ D A T A\ S A G E\
public class copy
{
private String newDriveLetter;
private String line;
private Path[]sageFolders;
private FileReader fileReader;
private BufferedReader bufferedReader;
private FileWriter fileWriter;
private BufferedWriter bufferedWriter;
private List<String> lines = new ArrayList<String>();
public void scanFiles() throws IOException{
try
{
System.out.println("Sage 2015 is Installed on this machine");
File companyFile = new File(sageFolders[8] + "\\COMPANY");
fileReader = new FileReader(companyFile);
bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null)
{
if(line.contains("F"))
{
line = line.replace("F:\\","S:\\");
lines.add(line);
}
}
//Close the Readers
fileReader.close();
bufferedReader.close();
fileWriter = new FileWriter(companyFile);
bufferedWriter = new BufferedWriter(fileWriter);
for(String s : lines)
{
bufferedWriter.write(s);
}
bufferedWriter.flush();
bufferedWriter.close();
}
catch(FileNotFoundException e)
{
System.out.println("File not Found: Moving onto next Version");
}
}
The problem is that readLine() reads a whole line, and then tosses away the line ending. From the documentation:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
So you have to add it back again, possibly using the preferred line ending for your platform:
bufferedWriter.write(String.format("%s%n", s);
here %s is the String and %n is the platform dependent line ending.
Alternatively, as Ransom Briggs indicates, you may use newline(). newLine() is easier to read and will perform slightly better:
bufferedWriter.write(s);
bufferedWriter.newLine();
I've left the String.format method in as it is a more general approach of adding newlines to strings.
Try PrintWriter - so new PrintWriter(bufferedWriter).println(s).
Add this after bufferedWriter.write(s);:
bufferedWriter.write(System.getProperty("line.separator", "\n"));
This will add the system specific line separator, or "\n" if the system property is not set.

Java - open txt file and clear all multiple spaces

I have a txt file and what I am trying to do is open it and delete all multiple spaces so they become only one. I use:
br = new BufferedReader(new FileReader("C:\\Users\\Chris\\Desktop\\file_two.txt"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\Chris\\Desktop\\file_two.txt"));
while ((current_line = br.readLine()) != null) {
//System.out.println("Here.");
current_line = current_line.replaceAll("\\s+", " ");
bw.write(current_line);
}
br.close();
bw.close();
However, as it seems correct according to me at least, nothing is written on the file. If I use a system.out.println command, it is not printed, meaning that execution is never in the while loop... What do I do wrong? Thanks
you are reading the file and at the same time writing contents on it..it is not allowed...
so better way to read the file first and store the processed text in another file and finally replace the original file with the new one..try this
br = new BufferedReader(new FileReader("C:\\Users\\Chris\\Desktop\\file_two.txt"));
bw = new BufferedWriter(new FileWriter("C:\\Users\\Chris\\Desktop\\file_two_copy.txt"));
String current_line;
while ((current_line = br.readLine()) != null) {
//System.out.println("Here.");
current_line = current_line.replaceAll("\\s+", " ");
bw.write(current_line);
bw.newLine();
}
br.close();
bw.close();
File copyFile = new File("C:\\Users\\Chris\\Desktop\\file_two_copy.txt");
File originalFile = new File("C:\\Users\\Chris\\Desktop\\file_two.txt");
originalFile.delete();
copyFile.renameTo(originalFile);
it may help...
There are few problems with your approach:
Main one is that you are trying to read and write to same file at the same time.
other is that new FileWriter(..) always creates new empty file which kind of prevents FileReader from reading anything from your file.
You should read content from file1 and write its modified version in file2. After that replace file1 with file2.
Your code can look more or less like
Path input = Paths.get("input.txt");
Path output = Paths.get("output.txt");
List<String> lines = Files.readAllLines(input);
lines.replaceAll(line -> line.replaceAll("\\s+", " "));
Files.write(output, lines);
Files.move(output, input, StandardCopyOption.REPLACE_EXISTING);
You must read first then write, you are not allowed to read and write to the same file at the same time, you would need to use RandomAccessFile to do that.
If you don't want to learn a new technique, you will need to either write to a separate file, or cache all lines to memory(IE an ArrayList) but you must close the BufferedReader before you Initialize your BufferedWriter, or it will get a file access error.
Edit:
In case you want to look into it, here is a RandomAccessFile use case example for your intended use. It is worth pointing out this will only work if the final line length is less than or equal to the original, because this technique is basically overwriting the existing text, but should be very fast with a small memory overhead and would work on extremely large files:
public static void readWrite(File file) throws IOException{
RandomAccessFile raf = new RandomAccessFile(file, "rw");
String newLine = System.getProperty("line.separator");
String line = null;
int write_pos = 0;
while((line = raf.readLine()) != null){
line = line.replaceAll("\\s+", " ") + newLine;
byte[] bytes = line.getBytes();
long read_pos = raf.getFilePointer();
raf.seek(write_pos);
raf.write(bytes, 0, bytes.length);
write_pos += bytes.length;
raf.seek(read_pos);
}
raf.setLength(write_pos);
raf.close();
}

Copying and merging two files

I am using java File Streams. I have two files. First file may or may not be empty. The second file contains strings and floats. If the first file is empty then I want to copy second file in it. else I want to merge the files.
Have tried RandomAccessFile but it's not working.
If you want to copy a file then use
public static Path copy(Path source,
Path target,
CopyOption... options)
throws IOException
File.copy()
If you want to merge them then open the file in write mode in which you want to append the data with appending mode.
BufferedWriter bw = new BufferedWritr(new FileWriter("file.txr",true));
and then write the data in bw which you have read from the source file.
My solution would look like this:
public void CopyFile(File one, File two) throws IOException {
// Declare the reader and the writer
BufferedReader in = new BufferedReader(new FileReader(one));
BufferedWriter out;
String contentOfFileOne = "";
// Read the content of the first file
while(in.ready()){
contentOfFileOne += in.readLine();
}
// Trim all whitespaces
contentOfFileOne.trim();
// If the first file is empty
if(contentOfFileOne.isEmpty()){
// Create a new Writer to the first file and a reader
// from the second file
in.close();
out = new BufferedWriter(new FileWriter(one));
in = new BufferedReader(new FileReader(two));
while(in.ready()){
String currentLine = in.readLine();
out.write(currentLine);
}
// Close them accordingly
in.close();
out.close();
} else {
// If the first file contains something
in.close();
out = new BufferedWriter(new FileWriter(one,true));
in = new BufferedReader(new FileReader(two));
// Copy the content of file two at the end of file one
while(in.ready()){
String currentLine = in.readLine();
out.write(currentLine);
}
in.close();
out.close();
}
}
The comments should explain the functionality.
I think this is supposed to be the most efficient option
FileChannel f1 = FileChannel.open(Paths.get("1"), StandardOpenOption.APPEND);
FileChannel f2 = FileChannel.open(Paths.get("2"));
f1.transferFrom(f2, f1.size(), Long.MAX_VALUE);

Categories