I have a piece of code that generates new data whenever there is new data available as InputStream . The same file is overwritten everytime. Sometimes the file becomes 0 kb before it gets written. A webservice reads these files at regular intervals. I need to avoid the case when the file is 0 bytes.
How do it do this? Will locks help in this case? If the browser comes in to read a file which is locked, will the browser continue to show old data from the cache until the lock is released and file is available to be read again.
try{
String outputFile = "output.html";
FileWriter fWriter = new FileWriter(outputFile);
//write the data ...
fWriter .flush();
outputFile = "anotheroutput.html";
fWriter = new FileWriter(outputFile);
//write the data ...
fWriter .flush();
fWriter.close();
}
catch(Exception e)
{
e.prinStackTrace();
}
Try writing to a temporary file (in the same file system) and once the file write is complete move it into place using File.renameTo(). If you underlying file system supports atomic move operations (most do) then you should get the behaviour that you require. If you are running on windows you will have to make sure you close the file after reading otherwise the file move will fail.
public class Data
{
private final File file;
protected Data(String fileName) {
this.file = new File(filename);
}
/* above is in some class somehwere
* then your code brings new info to the file
*/
//
public synchronized accessFile(String data) {
try {
// Create temporary file
String tempFilename = UUID.randomUUID().toString() + ".tmp";
File tempFile = new File(tempFilename);
//write the data ...
FileWriter fWriter = new FileWriter(tempFile);
fWriter.write(data);
fWriter.flush();
fWriter.close();
// Move the new file in place
if (!tempFile.renameTo(file)) {
// You may want to retry if move fails?
throw new IOException("Move Failed");
}
} catch(Exception e) {
// Do something sensible with the exception.
e.prinStackTrace();
}
}
}
FileWriter fWriter = new FileWriter(fileName,true);
try using above :-)
Your requirement is not very clear. Do you want to write a new name file every time or you want to append to the same file or you want to over write the same file? Anyway all three cases are easy and from the API you can manage it.
If the issue is that a web service is reading the file which is not yet complete i.e. is in writing phase. In your web service you should check if the file is read only, then only you read the file. In writing phase once writing is finished set the file to read only.
The 0Kb file happens because you are overwriting the same file again. Overwriting cleans up all the data and then start writing the new content.
public class Data
{
String fileName;
protected Data(String fileName)
{
this.fileName= fileName;
return; // return from constructor often not needed.
}
/* above is in some class somehwere
* then your code brings new info to the file
*/
//
public synchronized accessFile(String data)
{
try
{
// File name to be class member.
FileWriter fWriter = new FileWriter(fileName);
//write the data ...
fWriter.write(data);
fWriter .flush();
fWriter .close();
return;
}
catch(Exception e)
{
e.prinStackTrace();
}
this is not needed:
outputFile = "anotheroutput.html";
fWriter = new FileWriter(outputFile);
//write the data ...
fWriter .flush();
fWriter.close();
that's because work on the file is a method of class Data
Related
I want to append to the file and if its not empty; and want to write if its empty. Below is is my code. write function works, append is not. Can anyone guide here?
public class Filecreate {
public static void main(String args[]) throws IOException {
File file = new File("newFileCreated.txt");
System.out.println("file path "+file.getAbsolutePath() +" file length - "+file.length());
FileWriter myWriter = new FileWriter(file);
if((int)file.length() != 0){
myWriter.append("appended text\n");
}else{
myWriter.write("Files in Java might be tricky, but it is fun enough!");
}
myWriter.close();
System.out.println("file length after writing to file "+file.length());
}
}
You don't need to worry about whether or not the file contains anything. Just apply the argument of true to the append parameter in the FileWriter constructor then always use the Writer#append() method, for example:
String ls = System.lineSeparator();
String file = "MyFile.txt";
FileWriter myWriter = new FileWriter(file, true)
myWriter.append("appended text" + ls);
/* Immediately write the stream to file. Only really
required if the writes are in a loop of some kind
and you want to see the write results right away.
The close() method also flushes the stream to file
before the close takes place. */
myWriter.flush();
System.out.println("File length after writing to file " +
new File(file).length());
myWriter .close();
If the file doesn't already exist it will be automatically created
and the line appended to it.
If the file is created but is empty then the line is appended to it.
If the file does contain content then the line is merely appended to
that content.
The issue occurs because you measure file's size after you open it. Thus, you have to check file's size before you open it. Also, I won't recommend to cast long to int, because your solution won't work on big files. To conclude, following code will work for you:
public static void main(String[] args) throws IOException {
File file = new File("newFileCreated.txt");
long fileSize = file.length();
System.out.println("file path "+file.getAbsolutePath() +" file length - "+file.length());
FileWriter myWriter = new FileWriter(file);
if(fileSize > 0L){
myWriter.append("appended text\n");
}else{
myWriter.write("Files in Java might be tricky, but it is fun enough!");
}
myWriter.close();
System.out.println("file length after writing to file "+file.length());
}
My Code is:
String MyFile = "Riseone.dat";
String MyContent = "This is My file im writing\r\n";
File file;
FileOutputStream outputStream;
try {
file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS),MyFile);
outputStream = new FileOutputStream(file);
outputStream.write(MyContent.getBytes());
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
When I try this code MyFile creates in data/data/appfolder/files/Riseone.dat
but I want to create a file in DIRECTORY_DOWNLOADS.
also I want the file to write in append for next write action.
new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), MyFile); corresponds to the file inside the Downloads directory of external shared storage. You might have seen older file in internal storage. Check it carefully.
If you want to append the data for next write, use append mode to create FileOutputStream using another constructor public FileOutputStream(File file, boolean append)
outputStream = new FileOutputStream(file, true);
I am trying to write some coordinates to a file and later read it in as a string. So I need to have them written to file attached...without space or a new line, but my code writes only the first coordinate, that is pos_Let, but does not write pos_Num at all, not even with a space or on a new line.
So how can I get the code to write to file pos_LetposNum like that? Obviously I mean their references ;) ..thanks in advance
protected void writeCoordtoFile () throws IOException
{
File file = new File("FermiPresentCoord.txt");
boolean yes = file.createNewFile() ;
//boolean yes = exists();
if (yes == true)
{
// create a FileWriter Object
FileWriter writer = new FileWriter(file, true);
// Writes the content to the file
writer.write("");
writer.flush();
writer.write(pos_Let);
writer.flush();
writer.write(pos_Num);
writer.close();
}
else
{
// creates the file
file.createNewFile();
// creates a FileWriter Object
FileWriter out = new FileWriter(file);
// Writes the content to the file
out.write(pos_Let);
out.flush();
out.write(pos_Num);
out.flush();
out.close();
}
}
Quoting the method createNewFile():
Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist. The check for the existence of the file and the creation of the file if it does not exist are a single operation that is atomic with respect to all other filesystem activities that might affect the file.
Note: this method should not be used for file-locking, as the resulting protocol cannot be made to work reliably. The FileLock facility should be used instead.
Returns:
true if the named file does not exist and was successfully created; false if the named file already exists
in your case, you first create the file, and createNewFile() returns true, so you go to the if block, appending the line to the current file. Then, createNewFile() returns false, since, the file exists! So, you go to the else block, and create the file again from scratch...
So, basically, just inverse the if with else, and don't call createNewFile() twice... With the least possible changes (so that you do not get confused) here is my simple suggestion:
protected void writeCoordtoFile () throws IOException
{
File file = new File("FermiPresentCoord.txt");
boolean fileDoesNotExist = file.createNewFile() ;
//boolean fileDoesNotExist = file does **not** exist!
if (fileDoesNotExist)
{
// create a FileWriter Object
FileWriter writer = new FileWriter(file);
// Writes the content to the file
writer.write(pos_Let);
writer.write(pos_Num);
writer.close();
}
else
{
// creates a FileWriter Object
FileWriter out = new FileWriter(file,true);
// Writes the content to the file
out.write(""); //not sure why you need that...
out.write(pos_Let);
out.write(pos_Num);
out.close();
}
}
I can not find out why you are checking the existence of the output file. Because, when you are using FileWriter if the file specified in the path does not exist, it would create it and open a character output stream to it. Also if it exists in that path, only opens the output stream and it is ready to write into.
Try the following code and see whats happening when you run it more than one times:
float posLat = 156.23589965f;
float posLon = 12.987564f;
File file = new File("c:/FermiPresentCoord.txt");
FileWriter writer = new FileWriter(file, true);
writer.append(posLat+",");
writer.append(posLon+",");
writer.flush();
writer.close();
There is no need to invoke the file.createNewFile() and/or checking the for the existence of the file when you want to write into it.
The second argument for the FileWriter constructor is append flag. So every time you create an output stream to a file with FileWriter(file, true) constructor it automatically appends to the data of the file.
Good Luck.
I have a BufferedWriter which is being used to write to a file which has just been created in the given directory, however, for some reason it is not writing the text that it reads from another file, here is my code:
private static final String tempFileDir = System.getProperty("user.dir") + "/TempATM.txt";
File tempFile = new File(tempFileDir); //Create temporary file to write new info to
File toRenameTo = new File("VirtualATM.txt"); //filename to rename temp file to
if (!tempFile.exists() && !tempFile.isDirectory()) {
tempFile.createNewFile(); //Create temp file if it doesn't already exist.
}
FileOutputStream fos = new FileOutputStream(tempFile, true); //For writing new balance
Writer bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF8"));//For writing new balance
String newLineRead = null;
FileReader fileReader = new FileReader("VirtualATM.txt");//for reading from file
BufferedReader newBufferedReader = new BufferedReader(fileReader);//for reading from file
while((newLineRead = newBufferedReader.readLine()) != null){
if(!newLineRead.contains(cardNumberStr)){
bw.append(newLineRead); //If the line does not contain user entered card number, write line to new file.
((BufferedWriter) bw).newLine();
}else if(newLineRead.contains(cardNumberStr)){
bw.append(newAccountDetails); //Write updated account details if the line read contains users account number
((BufferedWriter) bw).newLine();
}
}
File toDeleteFile = new File("dirToWriteFile"); //File path to delete the file.
if(!toDeleteFile.delete()){
JOptionPane.showMessageDialog(null, "FATAL ERROR! Could not delete VirtualATM.txt", "Error", JOptionPane.ERROR_MESSAGE); // for if there is an error when deleting file
}
if(!file.renameTo(toRenameTo)){
JOptionPane.showMessageDialog(null, "FATAL ERROR! Could not rename the file to VirtualATM.txt", "Error", JOptionPane.ERROR_MESSAGE);//for if there is an error renaming file
}
Edit:
I am also having trouble deleting and renaming the text file, could any suggest what may be causing this problem, what SecurityExceptions etc. may be preventing Java from deleting and renaming a text file (.txt) on Windows 8.1?
You need to either flush the buffer post writing the data to buffer like
bw.flush();
or close the writer like
bw.close();//handle exception if you are not using AutoCloseable feature.
You must either flush the buffer to the disk after writing the data using:
bw.flush();
or / and if you have finished writing the data, you must always close the writer which will automatically flush the data to the disk before closing using:
bw.close();
Hope this helps. Good luck and have fun programming!
Cheers,
Lofty
I want to write data to a text file. But, in my application, i will want to keep on writing items to the text file (Which means, the text that i want to write, should be appended to the file - and not create a new file every time)
My code, is as follows; But how could i append text the next time i am writing something to the file ?
1.) The problem with the code below is, the first time writes to the file, but when i am trying to write for the 2nd time i get the following exception;
java.io.IOException: Stream closed
2.) I want to be able to write to the same file untill the application is closed. Therefore, how can i close the Stream when the application is closed ?
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class WriteToFileExample {
public void writeToFile(String stuff) {
try {
File file = new File("../somefile.txt");
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile(),true);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(stuff);
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
UPDATE 1
private File file;
public WriteToFileExample(){
file = new File("../somefile.txt");
}
public void writeToFile(String stuff) {
try {
if (!file.exists()) {
file.createNewFile();
}
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(stuff);
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
EXCEPTION
Exception in thread "main" java.lang.NullPointerException
at com.proj.example.Log.WriteToFile(WriteToFileExample.java:3)
Which points to if (!file.exists()) {.
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
Use the true argument for the FileWriter constructor.
You should create your FileWriter using the contructor that takes an extra boolean argument, that indicates that you want to append.
FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
You never close the FileWriter in your code. And from the documentation for the class:
Whether or not a file is available or may be created depends upon the
underlying platform. Some platforms, in particular, allow a file to be
opened for writing by only one FileWriter (or other file-writing
object) at a time. In such situations the constructors in this class
will fail if the file involved is already open.
Close the file writer before exiting your method, its good practice anyway. And yes, definitely do open the writer in append mode, if you don't want the files contents to be blown away every time you call your method.
Checking the api, says that the FileWriter constructor takes a boolean to flag whether to append or not. That answer your question?
Instead of doing this:
FileWriter fw = new FileWriter(file.getAbsoluteFile());
do as follow:
FileWriter fw = new FileWriter(file.getAbsoluteFile(),true);
As to append on a existing file FileWriter needs an extra argument as true here
FileWriter
public FileWriter(File file, boolean append) throws IOException
Constructs a FileWriter object given a File object. If the second argument is true, then bytes will be
written to the end of the file rather than the beginning.
Parameters:
file - a File object to write to
append - if true, then bytes will be
written to the end of the file rather than the beginning
Throws:
IOException - if the file exists but is a directory rather than a
regular file, does not exist but cannot be created, or cannot be
opened for any other reason
Since:
1.4