2

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.

4

4 回答 4

2

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.

于 2013-09-18T06:32:29.717 回答
2

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.

于 2013-09-18T07:11:26.537 回答
1

Just close the file, rename it, and open a new one. You're overthinking this.

于 2013-09-18T06:48:55.277 回答
1

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();
        }

    }

}
于 2013-09-19T07:22:09.413 回答