I developed a java program which is writing data into a file(temporary file) using asynchronousFileChannel.
Now each time it writes a entry to the file a second method will be called which will check for its size and if its size exceeds a pre thresold size say 10000 bytes,all the file contents should be moved to a different file(permanent Datarecord).
What should i use so that no data should be lost while moving data from temp file to permanent file while the temporary file is still been accessed by different threads.

- 1,568
- 15
- 30
-
use another file for writing (ex: tempFileA, tempFileB). move the first file while continuing to write in the second. – Lescai Ionel Sep 18 '13 at 06:29
-
Most OS will lock the file while it's open for writing and there's no way you can move it to a different location before the lock is released. After you FINISHED writing the file you can check the size and move it accordingly. – Nir Alfasi Sep 18 '13 at 06:40
-
i can handle the lock by checking the bytes in the same method i am using the asynchronousFileChannel ,but not able to a find appropriate way to move the file,while deleting the content of the temporary file which is already moved to the permanent file. – Charles Stevens Sep 18 '13 at 07:29
4 Answers
10,000 bytes is not very much, it is just <10kb. So I think you can buffer all this data in queue and when size exceeds you can clear(delete-create) temporary file and flush queue data to permanent storage file.

- 279
- 1
- 2
- 8
Since you are using AsynchronousFileChannel, there is always a problem that when one of your methods is trying to move the file, another thread might be trying to read/write to it.
You need to do the move by other means.
If what you are doing is logging, which I think you might be doing - use a FileHandler to roll the file. See an example here - http://kodejava.org/how-do-i-create-a-rolling-log-files/
You can also see some discussion about rolling files here - Rolling file implementation
Another one on stackoverflow - Rolling logs by both size and time
And another one - How to write statistical data into rolling files in java
Hope this helps. Good Luck.

- 1
- 1

- 2,068
- 1
- 16
- 17
-
I am not doing logging just simply writing a file using asynchronousFileChannel with its lock() method while writing,not able to find a method to move it if the size exceeds the threshold to a permanent directory – Charles Stevens Sep 18 '13 at 07:21
-
If you are using AsynchronousFileChannel, at any given time, multiple access will be happening and you will not get a proper lock() on it. Did you try the other links. There is some sample code you could use to try to do it. – Indu Devanath Sep 18 '13 at 10:36
-
If you are using AsynchronousFileChannel, at any given time, multiple access will be happening and you will not get a proper lock() on it. You might have to tryLock() first to check if you can even acquire a lock on it. I feel rolling a file after the file gets to the size is a better option. Check the links and see if any of those solutions work for you. Post the code you are having trouble with. May be we might get a better idea and can provide you with a solution. – Indu Devanath Sep 18 '13 at 10:44
-
could u suggest some links where i can get the idea for rolling a file. – Charles Stevens Sep 18 '13 at 11:49
Just close the file, rename it, and open a new one. You're overthinking this.

- 305,947
- 44
- 307
- 483
Here's the code I wrote for you...
public class RollMyFile {
private long FILE_MAX_SIZE;
private String fileName;
/**
* Constructor to take in the initial file name and the maxFileSize
* @param fileNameToStartWith
*/
public RollMyFile(String fileNameToStartWith, long maxFileSize) {
this.fileName = fileNameToStartWith;
this.FILE_MAX_SIZE = maxFileSize;
}
/**
* Synchronized to roll over to a new file
*
* @param fileChannel
* @return
* @throws IOException
*/
public synchronized AsynchronousFileChannel rollMeIfNeeded(AsynchronousFileChannel fileChannel) throws IOException {
if(fileChannel.size()>FILE_MAX_SIZE) {
this.fileName = getNewRolledFileName(this.fileName);
File file = new File(this.fileName);
file.createNewFile();
fileChannel = getAsyncChannel(this.fileName);
}
return fileChannel;
}
/**
* Change this to create a new name for the roll over file
* @param currentFileName
* @return
*/
public String getNewRolledFileName(String currentFileName) {
if (currentFileName.contains(".")) {
currentFileName = currentFileName.substring(0,
currentFileName.lastIndexOf('.'));
}
return currentFileName+ "." + Calendar.getInstance().getTimeInMillis();
}
/**
* This is where you request to write a whole bunch of stuff that
* you said you want to store
*
* @param stuffToWrite
* @throws IOException
*/
public void write(StringBuffer stuffToWrite) throws IOException {
AsynchronousFileChannel fileChannel = getAsyncChannel(this.fileName);
fileChannel = rollMeIfNeeded(fileChannel);
ByteBuffer byteBuffer = ByteBuffer.wrap(stuffToWrite.toString().getBytes());
fileChannel.write(byteBuffer, fileChannel.size());
}
/**
* Change this to how ever you 'open' the AsynchronousFileChannel
*
* @param givenFileName
* @return
* @throws IOException
*/
private AsynchronousFileChannel getAsyncChannel(String givenFileName) throws IOException {
return AsynchronousFileChannel.open(Paths.get(givenFileName), StandardOpenOption.WRITE);
}
}
And I used it like below
public class Tester {
public static void main(String[] args) {
RollMyFile rmf = new RollMyFile("my-current-file", 1000);
try {
for(int i=1; i<1000; i++) {
rmf.write(new StringBuffer(" lots of important stuff to store... "));
System.out.println(i);
}
System.out.println("end");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

- 2,068
- 1
- 16
- 17