美文网首页
07_使用随机流RandomAccessFile删除文件指定内容

07_使用随机流RandomAccessFile删除文件指定内容

作者: 明天你好向前奔跑 | 来源:发表于2018-09-06 17:37 被阅读0次

    @Author Jacky Wang

    转载请注明出处,https://www.jianshu.com/p/1c1b35d9be9b

    碰到一个需求,在某个服务的日志文件达到指定大小之后,删除该日志文件前面多少行,在后面追加新的日志。以下,为此次使用随机文件流操作文件内容所记。

    /**   
     * @Title: removeFileLine   
     * @Description: TODO(该方法为从文件开头删除前n行)   
     * @param: @param file 文件
     * @param: @param lineNum 删除的行行数
     * @param: @throws IOException      
     * @return: void      
     * @throws   
     */ 
    public void removeFileLine(File file, int lineNum) throws IOException {
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(file, "rw");
            // Initial write position.
            // 写文件的位置标记,从文件开头开始,后续读取文件内容从该标记开始
            long writePosition = raf.getFilePointer();
            for (int i = 0; i < lineNum; i++) {
                String line = raf.readLine();
                if (line == null) {
                    break;
                }
            }
            // Shift the next lines upwards.
            // 读文件的位置标记,写完之后回到该标记继续读该行
            long readPosition = raf.getFilePointer();
    
            // 利用两个标记,
            byte[] buff = new byte[1024];
            int n;
            while (-1 != (n = raf.read(buff))) {
                raf.seek(writePosition);
                raf.write(buff, 0, n);
                readPosition += n;
                writePosition += n;
                raf.seek(readPosition);
            }
            raf.setLength(writePosition);
        } catch (IOException e) {
            logger.error("readAndRemoveFirstLines error", e);
            throw e;
        } finally {
            try {
                if (raf != null) {
                    raf.close();
                }
            } catch (IOException e) {
                logger.error("close RandomAccessFile error", e);
                throw e;
            }
        }
    }
    
    /**   
     * @Title: appendContentToFile   
     * @Description: TODO(在文件末尾追加内容)   
     * @param: @param file
     * @param: @param content
     * @param: @throws IOException      
     * @return: void      
     * @throws   
     */ 
    public static void appendContentToFile(File file, String content) throws IOException {
        RandomAccessFile randomFile = null;
        try {
            // 打开一个随机访问文件流,按读写方式
            randomFile = new RandomAccessFile(file, "rw");
            // 文件长度,字节数
            long fileLength = randomFile.length();
            // 将写文件指针移到文件尾。
            randomFile.seek(fileLength);
            randomFile.writeBytes(content);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (randomFile != null) {
                randomFile.close();
                randomFile = null;
            }
        }
    }
    
    /**   
     * @Title: checkFileInSize   
     * @Description: TODO(检查文件字节数是否超出限制)   
     * @param: @param file
     * @param: @param limitSize
     * @param: @return      
     * @return: boolean      
     * @throws   
     */ 
    private boolean checkFileInSize(File file, Long limitSize) {
        return file.length() <= limitSize;
    }
    

    以上就是上述需求用到的方法了,下面将上面的方法整合完成需求。

    @Component
    @SuppressWarnings("restriction")
    @PropertySource("classpath:/config/ivg.properties")
    public class AppStartupListener implements ApplicationRunner {
    
        @Value("${log.startup.path}")
        private String logPath;// 日志保存路径
        @Value("${log.startup.output.statement}")
        private String outputStatement;// 追加日志内容模板
        @Value("${log.startup.limit.size}")
        private Long limitSize;// 文件大小限制,eg:50M:50*1024*1024 = 52428800
        @Value("${log.startup.remove.line}")
        private int removeLineNum;// 超过限制之后一次删除多少行
    
        private void initLog() {
            logger.info("***程序启动日志记录开始***");
    
            // 检查文件是否存在
            File file = null;
            try {
                file = new File(logPath);
                if (!file.exists() || !file.isFile()) {
                    logger.info("file is not exist,creating " + logPath + " now...");
                    file.createNewFile();
                }
                StringBuilder sb = new StringBuilder(outputStatement);
                SimpleDateFormat sdf = new SimpleDateFormat(" yyyy-MM-dd HH:mm:ss");
                String date = sdf.format(new Date());
                String outputLog = sb.append(date).append("\r\n").toString();
    
                // 检查文件大小
                while (!checkFileInSize(file, limitSize)) {
                    // 先删除前三行
                    removeFileLine(file, removeLineNum);
                }
                // 追加項目啓動log日志
                appendContentToFile(file, outputLog);
            } catch (FileNotFoundException e) {
                logger.error("StartupLog Listener error,{}", e);
            } catch (IOException e) {
                logger.error("StartupLog Listener error,{}", e);
            }
        }
    }
    

    至此需求已完成。通过此次需求,学习了RandomAccessFile随机文件流的一些简单使用方式,记录在此。

    相关文章

      网友评论

          本文标题:07_使用随机流RandomAccessFile删除文件指定内容

          本文链接:https://www.haomeiwen.com/subject/ydaxgftx.html