Strange behavior in writing to file - java

I was trying some basic Java I/O operations, I try to run the below code :
public static void main(String[] args) {
File file = new File("fileWrite2.txt"); // create a File object
try {
FileWriter fr = new FileWriter(file);
PrintWriter pw = new PrintWriter(file); // create a PrintWriter that will send its output to a Writer
BufferedWriter br = new BufferedWriter(fr);
br.write("sdsadasdsa");br.flush();br.append("fffff");br.flush();
pw.println("howdy"); // write the data
pw.println("folks");
pw.flush();
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
When I run the above I get the following output in the file created :
howdy
folks
f
Can anyone explain why the 'f' is coming in the last line ?

The f comes from the left over string of br.append("fffff"); which was written in the file by the BufferedWriter.
Since both BufferedWriter and PrintWriter write to the same file, the contents written by the PrintWriter overwrite the contents written by the BufferedWriter.
But seems the no. of bytes written by PrintWriter fall short by 1 to completely overwrite the data written by BufferedWriter and thus you get the f.
If you change this br.append("fffff"); to br.append("ffffg");, you can see that the g is now left over. Alternatively, changing pw.println("folks"); to pw.println("folks1"); will show that the previously written data is now completely overwritten by the PrintWriter.
All this confusion is because of having 2 different writers for the same file object which is the cause of the problem. As #Boris pointed out, have just 1 writer for a file object.
Note: Another interesting thing to test out would be to move the second br.flush(); after the pw.flush();.
// br.flush(); // moved from here
pw.println("howdy"); // write the data
pw.println("folks");
pw.flush();
br.flush(); // to here

You are writing 15 characters on the bufferedwriter by doing this
`
br.write("sdsadasdsa");
br.flush();
br.append("fffff");`
But when you are writng on printWriter, it overwrites the content of the file
this time you are writing
pw.println("howdy"); // write the data
pw.println("folks");
which is 10 characters only with two new line \n which takes 2 bytes since we use println because \n in windows will transform to \r\n . So total of 14.
so 1 character remains there which is f

In your code the following steps are executed.
1 When
br.write("sdsadasdsa");br.flush();br.append("fffff");br.flush();
is executed.
The file content will be
sdsadasdsafffff
2 when
pw.println("howdy"); is calling.
String howdy override the first 5 character sdsad and a new line terminates the line. In txt, 2 characters are needed \r\n, this will over write another 2 character .Then the file content will be as follows:
howdy
dsafffff
3 when
pw.println("folks");
is executed.
Since it is not called flush() method in step#2. String folks will over write the second line content in file. and a new line to over write another 2 characters.
Then the following content will be stored in file:
howdy
folks
f

Related

Insert line before last line in a large size .DAT file in java [duplicate]

I have to modify a text file in java.
eg this is the file before modify
line
line
line
line
line
line
and after it should look like:
line
line
this is another
line
line
line
line
So don't write over anything, only add a line between the 2. and 3. line, and the original 3. line will be the new 4. line.
A way is to make a temp file, write every line in it, and where I want to modify I do the modification. Than delet the original, and rename the temp file. Or read the temp file and write it to te original file.
But is there any way to read and modify a file like I want using the same class in java?
thx!
You can read and modify to and from a file in Java at the same time. The problem you have though is that you need to insert data here, in order to do that everything after the new line needs to be shuffled down and then the length of the file extended.
Depending on exactly what and why you are trying to do there are a number of ways to do this, the easiest is probably to scan the file copying it to a new location and inserting the new values as you go. If you need to edit in place though then it's more complicated but essentially you do the same thing: Read X characters to a buffer, overwrite the X characters in the file with the new data, read next X characters. Overwrite the just-read characters from the first buffer. Repeat until EOF.
Think of files on disk as arrays - if you want to insert some items into the middle of an array, you need to shift all of them to make room.
The only safe way is to create a new temp file, copy the old file line by line and then rename it, just as you suggested. By updating the same file directly on the disk you risk losing the data if anything goes wrong and you would use a lot of memory.
Try this:
public void writeAfterNthLine(String filename, String text, int lineno) throws IOException{
File file = new File(filename);
File temp = File.createTempFile("temp-file-name", ".tmp");
BufferedReader br = new BufferedReader(new FileReader( file ));
PrintWriter pw = new PrintWriter(new FileWriter( temp ));
String line;
int lineCount = 0;
while ((line = br.readLine()) != null) {
pw.println(line);
if(lineCount==lineno){
pw.println(text);
}
lineCount++;
}
br.close();
pw.close();
file.delete();
temp.renameTo(file);
}
The code is not tested, but it should work, you can improve the code with several validations and exception handling

Why does this Java code not write to file?

There are so many Input/Output Classes in Java.
It is really a mess. You do not know which to use.
Which functions does operating system offer ? There will be one
to read one byte of a file or many bytes of a file I guess.
So for example if I use this.
String path = "C:\\Users\\myName\\test.txt";
FileOutputStream fos = new FileOutputStream(path);
fos.write(333);
If I open it with a text editor it shows me letter "G" . Already I do not understand this.
And this code does not write anything, the file is empty weirdly.
String path = "C:\\Users\\myName\\test.txt";
FileOutputStream fos = new FileOutputStream(path);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
out.write("something");
All these I/O classes just confuse me. What does buffered mean. It reads 1000 Bytes at once. So
there is operating function to straight away read 1000 Bytes of a file I guess.
You need to close the instances of BufferedWriter out and FileOutputStream fos, after invoking the out.write("something"), then only the file gets created successfully with the contents you are trying to write.
public static void main(String[] args) throws IOException {
String path = "C:\\Users\\myName\\test.txt";
FileOutputStream fos = new FileOutputStream(path);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
out.write("something");
out.close(); // Closes the stream, flushing it first.
fos.close(); // Closes this file output stream and releases any system resources associated with this stream.
}
Closing the instances of BufferedWriter and FileOutputStream will solve the issue.
fos.write(333) => The number has been written to the file and when you open the file it opens in ASCII format. You can use below code.
public static void main(String[] args) throws IOException {
FileWriter fw=new FileWriter("D:\\test.txt");
fw.write("Hello! This is a sample text");
System.out.println("Writing successful");
fw.close();
/* your code
String path = "D:\\test1.txt";
FileOutputStream fos = new FileOutputStream(path);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
out.write("Hello! This is a sample text");
out.close();
fos.close();
*/
}
There are so many Input/Output Classes in Java. It is really a mess. You do not know which to use.
The Files class is by far the easiest to use. For instance,
Files.writeString(Paths.get("test.txt"), "hello world!");
creates a text file named "test.txt" containing the text "hello world!".
The other classes are only needed if you want to do something fancy (for instance, deal with files too big to fit in main memory). For instance, suppose you wanted to read a huge log file (hundreds of gigabytes long) and wanted to write each line containing a particular word to another file. If you were to open the file with
Files.readAllLines(Paths.get("huge.log"));
you'd receive an OutOfMemoryError because the file doesn't fit in main memory. To work around that, we must read the file piece-wise, and that is what all those Reader and Writer classes (or InputStream and OutputStream, if you're dealing with binary files) are good for:
try (
var reader = Files.newBufferedReader(Paths.get("huge.log"));
var writer = Files.newBufferedWriter(Paths.get("interesting.log"));
) {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains(searchWord)) {
writer.write(line);
writer.write('\n');
}
}
}
As you can see, their use is quite a bit more complicated. For one, we must close the Reader and Writer once we are done with them, which is easiest accomplished with the try with resources statement shown above.
Closing is necessary because most operating systems limit the number of files that can be open at once. Closing also gives any Buffered* classes the opportunity to empty their buffers, ensuring that any data still in buffers is passed on to the file system.
If we fail to close, as you did in your example code, the file remains open until our program exits, upon which time any data in the buffers is lost, resulting in the incomplete file you found.

How to use a regular expression to parse a text file and write the result on another file in Java

I used a regular expression to parse a text file to use the resulted group one and two as follows:
write group two in another file
make its name to be group one
Unfortunately, No data is written on the file!
I did not figure out where is the problem, here is my code:
package javaapplication5;
import java.io.*;
import java.util.regex.*;
public class JavaApplication5 {
public static void main(String[] args) {
// TODO code application logic here
try {
FileInputStream fstream = new FileInputStream("C:/Users/Welcome/Desktop/End-End-Delay.txt");
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
File newFile1= new File("C:/Users/Welcome/Desktop/AUV1.txt");
FileOutputStream fos1= new FileOutputStream(newFile1);
BufferedWriter bw1= new BufferedWriter(new OutputStreamWriter(fos1));
String strLine;
while ((strLine = br.readLine()) != null) {
Pattern p = Pattern.compile("sender\\sid:\\s(\\d+).*?End-End\\sDelay:(\\d+(?:\\.\\d+)?)");
Matcher m = p.matcher(strLine);
while (m.find()) {
String b = m.group(1);
String c = m.group(2);
int i = Integer.valueOf(b);
if(i==0){
System.out.println(b);
bw1.write(c);
bw1.newLine();
}
System.out.println(b);
// System.out.println(c);
}
}
}
catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
Can anyone here help me to solve this problem and Identify it?
You are using BufferedWriter, and never flush (flushing writer pushes the contents on disk) your writer or even close it at the end of your program.
Due to which, before your content gets written in actual file on disk from BufferedWriter, the program exits and the contents get lost.
To avoid this, either you can call flush just after writing contents in bw1,
bw1.write(c);
bw1.newLine();
bw1.flush();
OR
Before your program ends, you should call,
bw1.close(); // this ensures all content in buffered writer gets push to disk before jvm exists
Calling flush every time you write the data is not really recommended, as it defeats the purpose of buffered writing.
So best is to close the buffered writer object. You can do it in two ways,
Try-with-resources
Manually close the buffered writer object in the end, likely in the finally block so as to ensure it gets called.
Besides all this, you need to ensure that your regex matches and your condition,
if(i==0){
gets executed else code that is writing data in file won't get executed and of course in that case no write will happen in file.
Also, it is strongly recommended to close any of the resources you open like file resources, database (Connection, Statements, ResultSets) resources etc.
Hope that helps.

Need help using java to read a file, insert trim command, edit the strings, and then save the file as an output

I have two different ways to read the file but I am not sure how to proceed to converting the text to a string and then an if then statement like...
if string contains ":"
true string = "string"
false string = ,,"string"
package test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class ReadStringFromFileLineByLine {
public static void main(String[] args) {
try {
File file = new File("foo.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
String line;
String trim;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line);
stringBuffer.append("\n");
}
fileReader.close();
System.out.println("Contents of file:");
System.out.println(stringBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
But I don't believe I am using the trim command appropriately
Your question doesn't really communicate clearly the intent of the program. What exactly are you trying to do? If your file is text-based, there is no "conversion to String" needed. Also "save the file as an output" isn't clear either. Do you want to save a new file, overwrite the existing file, or append the existing file. All of these scenarios are handled differently. Taking this by parts:
First point: Your Scantest class works. Given a file foo.txt in the project folder, the class will print out the contents of the file.
Second point: Your class ReadStringFromFileLineByLine works with my own foo.txt just like the first class. So, there might be something wrong with your test.txt file. This is probably the most important thing when testing (making all conditions equal). If the conditions for testing are not equal, the tests will most likely be inconclusive (which is why I suspect happened in your case).
Third point: None of your classes attempted to make any modifications to the obtained strings or made modifications to the file. If you were to write to a file, you have to consider the following: Append vs. Overwrite. All it takes is the use of a simple boolean value:
FileWriter fw = new FileWriter(file.getAbsoluteFile()); // overwrites contents of file
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true); // appends to file
The FileWriter single argument contructor calls the two-argument constructor passing false to it. Therefore, the FileWriter overwrites instead of appends. This is important because if you handle the file line by line, it is possible that at the end, your file will contain only the last line you "modified." If you choose to append, the new String will be added to the end of the line. So this is not good either. If you want to process a file line by line, made modifications to any given line, AND save the line to the same file, your best option is to use RandomAccessFile. This class allows you to write 'X' number of characters starting on a given offset. In this case, this "offset" is the "address" of the current line; putting it simply: the offset is equal to the number of characters already processed. So, for the first line, the offset is 0, for line 2 is the number of characters in line 1, and so forth.
I can add this as an update if you need it, but I did not see anything in your code that attempted to change the file in any way. I was just going by your title.

How to add new line in the middle of txt file in java

I have to modify a text file in java.
eg this is the file before modify
line
line
line
line
line
line
and after it should look like:
line
line
this is another
line
line
line
line
So don't write over anything, only add a line between the 2. and 3. line, and the original 3. line will be the new 4. line.
A way is to make a temp file, write every line in it, and where I want to modify I do the modification. Than delet the original, and rename the temp file. Or read the temp file and write it to te original file.
But is there any way to read and modify a file like I want using the same class in java?
thx!
You can read and modify to and from a file in Java at the same time. The problem you have though is that you need to insert data here, in order to do that everything after the new line needs to be shuffled down and then the length of the file extended.
Depending on exactly what and why you are trying to do there are a number of ways to do this, the easiest is probably to scan the file copying it to a new location and inserting the new values as you go. If you need to edit in place though then it's more complicated but essentially you do the same thing: Read X characters to a buffer, overwrite the X characters in the file with the new data, read next X characters. Overwrite the just-read characters from the first buffer. Repeat until EOF.
Think of files on disk as arrays - if you want to insert some items into the middle of an array, you need to shift all of them to make room.
The only safe way is to create a new temp file, copy the old file line by line and then rename it, just as you suggested. By updating the same file directly on the disk you risk losing the data if anything goes wrong and you would use a lot of memory.
Try this:
public void writeAfterNthLine(String filename, String text, int lineno) throws IOException{
File file = new File(filename);
File temp = File.createTempFile("temp-file-name", ".tmp");
BufferedReader br = new BufferedReader(new FileReader( file ));
PrintWriter pw = new PrintWriter(new FileWriter( temp ));
String line;
int lineCount = 0;
while ((line = br.readLine()) != null) {
pw.println(line);
if(lineCount==lineno){
pw.println(text);
}
lineCount++;
}
br.close();
pw.close();
file.delete();
temp.renameTo(file);
}
The code is not tested, but it should work, you can improve the code with several validations and exception handling

Categories

Resources