【问题标题】:moving a file to different location while it is still been accessed将文件移动到不同的位置,而它仍然被访问
【发布时间】:2013-09-18 06:20:34
【问题描述】:

我开发了一个 java 程序,它使用 asynchronousFileChannel 将数据写入文件(临时文件)。
现在每次向文件写入条目时,都会调用第二个方法,该方法将检查其大小,如果其大小超过预阈值大小,例如 10000 字节,则应将所有文件内容移动到不同的文件(永久数据记录) .
我应该使用什么,以便在将数据从临时文件移动到永久文件时不会丢失任何数据,而临时文件仍被不同的线程访问。

【问题讨论】:

  • 使用另一个文件进行写入(例如:tempFileA、tempFileB)。移动第一个文件,同时继续写入第二个文件。
  • 大多数操作系统会在文件打开以进行写入时锁定文件,并且在解锁之前您无法将其移动到其他位置。完成写入文件后,您可以检查大小并相应地移动它。
  • 我可以通过检查字节来处理锁定,方法与我使用异步文件通道的方法相同,但无法找到移动文件的适当方法,同时删除临时文件的内容已移至永久文件。

标签: java asynchronous file-move


【解决方案1】:

10,000 字节不是很多,它只是

【讨论】:

    【解决方案2】:

    由于您使用的是 AsynchronousFileChannel,因此总是存在一个问题,即当您的一个方法尝试移动文件时,另一个线程可能正在尝试读取/写入它。

    您需要通过其他方式进行移动。

    如果您正在做的是记录,我认为您可能正在做 - 使用 FileHandler 来滚动文件。在此处查看示例 - http://kodejava.org/how-do-i-create-a-rolling-log-files/

    您还可以在此处查看有关滚动文件的一些讨论 - Rolling file implementation

    stackoverflow 上的另一个 - Rolling logs by both size and time

    还有一个 - How to write statistical data into rolling files in java

    希望这会有所帮助。祝你好运。

    【讨论】:

    • 我不是在做日志记录,只是在写入时使用异步FileChannel及其lock()方法写入文件,如果大小超过阈值,则无法找到将其移动到永久目录的方法跨度>
    • 如果您使用的是 AsynchronousFileChannel,在任何给定时间,都会发生多重访问,您将无法获得正确的 lock()。您是否尝试过其他链接。您可以使用一些示例代码来尝试这样做。
    • 如果您使用的是 AsynchronousFileChannel,在任何给定时间,都会发生多重访问,您将无法获得正确的 lock()。您可能必须先 tryLock() 以检查您是否甚至可以获得锁定。我觉得在文件达到大小后滚动文件是一个更好的选择。检查链接,看看这些解决方案是否适合您。发布您遇到问题的代码。也许我们可能会得到一个更好的主意,并可以为您提供解决方案。
    • 你能推荐一些链接,我可以从中获得滚动文件的想法。
    【解决方案3】:

    这是我为你写的代码...

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

    我像下面这样使用它

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

    【讨论】:

      【解决方案4】:

      只需关闭文件,重命名它,然后打开一个新文件。你想多了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-09
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 2016-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多