Java 保留日志文件的2个以前版本

Java 保留日志文件的2个以前版本,java,java.util.logging,Java,Java.util.logging,我的Java应用程序CB从数据库获取数据,比如案例1。每次CB启动时都会创建一个日志文件: Logger logger = Logger.getLogger("CBLog"); fh = new FileHandler(CBDataPath + "\\CB.log"; logger.addHandler(fh); SimpleFormatter formatter = new SimpleFormatter(); fh.setFormatter(formatter); logger.

我的Java应用程序CB从数据库获取数据,比如案例1。每次CB启动时都会创建一个日志文件:

Logger logger = Logger.getLogger("CBLog");  
fh = new FileHandler(CBDataPath + "\\CB.log";
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();  
fh.setFormatter(formatter);  
logger.info("CB started");  
我想为一个特定的案例保留2个以前版本的日志文件。如何最容易做到这一点

我有一个想法。我可以在案例数据库中维护一个表示运行编号的整数。每次连续运行都将日志文件命名为CB_CaseA_n.log,其中n是上一次运行的编号加上1。每次在CaseA上运行CB时,都会在CasaA目录中搜索所有CB_CaseA_?.log文件,并且只保留最近保存的3个文件。即,CB_案例A_7的第10次运行将被删除。看起来不太优雅

有更好的方法吗?

来自:

计数指定要循环的输出文件数默认为1

%g用于区分旋转日志的生成编号

使用计数和生成模式创建文件处理程序:

new FileHandler("CBDataPath + "\\CB%g.log, Integer.MAX_VALUE, 2, false);

这是我的解决办法。解释如下:

updateLogHistory() maintains historical log files in the MyConcourses directory. It is called in the ConcoursGUI() constructor.

The intuition is a "stack" of log files with the current log, i.e., ConcoursBuilderLog_0.log,  on top. To make room for a new log file
 for the ConcoursBuilder session, any existing log files have to be "pushed down." However, the stack is allowed to hold only a prescribed
number, size, elements so if there are already size files in the stack the bottom one gets deleted, or rather, overwritten. When the function
 finishes the top TWO will be identical, so the top one can be overwritten in the caller.

It's important to note that "stack" is a metaphor here; there isn't a stack in the sense of a programed data structure. There can be only 
size log files in the MyConcourses folder. What actually happens in a so-called push is the CONTENTS of ConcoursBuilderLog_i.log 
复制到ConcoursBuilderLog_i+1.log中,保持ConcoursBuilderLog_i.log不变

// The algorithm below requires an initial ConcoursBuilder_0.log. Consequently, prior to calling updateLogHistory() 
// the directory is first checked and an empty one is created if absent. Typically, this happens only in the first 
// run after INSTALLATION of ConcoursBuilder. However, it must be checked because the user might accidently deleted it.
//
// Work from the bottom up to push all existing log files down, leaving the contents of the current ConcoursBuilderLog_0 in
// both ConcoursBuilderLog_0 and 1. the subsequent log file will overwrite both ConcoursBuilderLog_0.
//



Logger logger = Logger.getLogger("ConcoursBuilderLog"); 
File logFile = null;
try {
    String strFileFullPath = concoursBuilderDataPath + "\\ConcoursBuilderLog_" + 0 + ".log";
    logFile = new File(strFileFullPath);
    if(!logFile.exists()){
        try {
            logFile.createNewFile();
        } catch (IOException ex) {
            Logger.getLogger(ConcoursGUI.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {            
            Files.write(Paths.get(logFile.getPath()), "Empty log file".getBytes(), StandardOpenOption.WRITE);
        } catch (IOException ex) {
            Logger.getLogger(ConcoursGUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    // Maintain a "stack" of historical ConcoursBuilder log files.
    updateLogHistory(NUM_SAVED_LOGS,  logFile);  

} catch (SecurityException e) {  
    e.printStackTrace();  
} 
fhLogger = null;
try {
    fhLogger = new FileHandler(logFile.toString(), false);
} catch (IOException ex) {
    Logger.getLogger(ConcoursGUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
    Logger.getLogger(ConcoursGUI.class.getName()).log(Level.SEVERE, null, ex);
}
logger.addHandler(fhLogger);
logger.setLevel(Level.ALL);
SimpleFormatter formatter = new SimpleFormatter();
fhLogger.setFormatter(formatter);

// the updater
private static  void updateLogHistory(int size, File logFile0){
        String strTemp = logFile0.toString(); 
    String strPrefix = strTemp.substring(0, strTemp.indexOf("_")+1);
    for(int i =  size-1; i >=0; i--){
        String strFileFullPath = strPrefix + i + ".log";
        File logFile_i  = new File(strFileFullPath);
        if(logFile_i.exists() && !logFile_i.isDirectory()){
            Path path= Paths.get(strFileFullPath); // this is the the absolute path to the i file as a Path                
            if( i != size-1){
                // not at the end so there is a valid file name i+1.
                // Note that the file selected by iNext has already been pushed into iNext+1, or is the last. Either way,
                // it can properly be overwritten.
                int iPlus1 = i + 1;
                String strFileFullPathIPlus1 = strPrefix + iPlus1 + ".log";
                Path pathIPlus1 = Paths.get(strFileFullPathIPlus1); //  absolute path to the file as a Path                
                try {
                    Files.copy(path, pathIPlus1,   REPLACE_EXISTING);
                } catch (IOException ex) {
                    okDialog("IOException while updating log history in updateLogHistory()");
                    Logger.getLogger(ConcoursGUI.class.getName()).log(Level.SEVERE, null, ex);
                }
                continue; // (unnecessary) branch back to for() 
            } else{
                // Getting here means stack is full. IOW, the reference file the is last log file to be kept so we no longer need it's contents.
                // No action required since it will simply be overwritten in the next pass.
                //  things in the next pass.;
            }
        } 
    }

}     

谢谢可怕的是,我刚刚完成了我自己的攻击!不过我会试试你的建议。对于代码格式,或者更确切地说,缺乏格式,我很抱歉。我用4隔开,然后粘贴。。。我猜这没用。这似乎是个问题。除了创建CB0.log,它还创建CB0.log.lck。程序完成后,后者将被删除。我的理解是,这意味着日志文件已经存在于另一个进程中。我刚刚使用了您的新FileHandler行,并对其进行了轻微的修改。@EdS每个打开的文件处理程序都将有点“lck”文件。最后,那个“lck”文件被删除了。我想这毕竟不是我想要的。Javadoc表示,当当前文件的大小超过限制时,它开始写入下一个文件。我的愿望是为每个指定数量的应用程序会话保留单独的日志。