Search code examples
javaasynchronousfile-move

moving a file to different location while it is still been accessed


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.


Solution

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