log4j 之 DailyRollingFileAppender 问题,为什么不是每天生产新的日志文件呢???

时间:2022-11-01 17:43:59
请问各位,如何是用DailyRollingFileAppender是每天生成单独的日志文件,而不是在日志有变化时才生成新的日志文件。

下面是我的配置,但是这个配置出现的问题就是,如果在第二天没有产生新日志,那么就不会生成新的日志文件。

例如 2009-6-25日日志文件为 debug.log,在2009-6-26时如果debug.log中的日志没有变化,则不会产生debug.log.2009-6-25;直到当有新的日志内容产生时才会生成debug.log.2009-6-25,这样的问题是,如果2009-6-26没有产生任何新日志,那么就得在2009-6-27或往后直到有新日志内容生成那天才会产生debug.log.2009-6-25文件。

我想让他一到新的一天就产生前一天的日志文件,不知怎么实现呢,谢谢!!!

log4j.appender.FILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.FILE.Threshold=DEBUG
log4j.appender.FILE.File=/tmp/debug.log
log4j.appender.file.DatePattern='.'yyyy-MM-dd
log4j.appender.FILE.Append=true
log4j.appender.FILE.Encoding=GBK
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n

10 个解决方案

#1


这个应该比较难,我想它应该是在写日志的时候才去检查是否需要产生新的文件,而不是有一个单独的线程或计时器跑在那里,每隔24小时便产生一个文件。
要么,干脆你修改一下自己的程序,确保每24小时内至少打一条log就是了,哪怕只是报一声平安,呵呵。

#2


呵呵,这也是个主意,谢谢。

那不知有没有更好的方案呢??

#3


我觉得你的需求也怪怪的,没有日志的那天干吗还要产生一个空文件啊?
我反倒觉得没有日志的就没有文件,这是优点,不是缺点。
:P

#4


我的意图是想如果前一天有日志内容,就生成前一天的日志文件如:debug.log.2009-6-25。
譬如说,到2009-6-26时,若debug.log中有日志内容,则生成debug.log.2009-6-25;到2009-6-26时,若debug.log中没有任何日志内容,就不必生成debug.log.2009-6-25。

#5


请各位指教。

#6


引用 4 楼 kld208 的回复:
我的意图是想如果前一天有日志内容,就生成前一天的日志文件如:debug.log.2009-6-25。 
譬如说,到2009-6-26时,若debug.log中有日志内容,则生成debug.log.2009-6-25;到2009-6-26时,若debug.log中没有任何日志内容,就不必生成debug.log.2009-6-25。

???什么意思?到到2009-6-26时,若debug.log中没有任何日志内容,肯定不会生成debug.log.2009-6-25呀。

#7


引用 6 楼 ouyangxiaokang6 的回复:
引用 4 楼 kld208 的回复:
我的意图是想如果前一天有日志内容,就生成前一天的日志文件如:debug.log.2009-6-25。 
譬如说,到2009-6-26时,若debug.log中有日志内容,则生成debug.log.2009-6-25;到2009-6-26时,若debug.log中没有任何日志内容,就不必生成debug.log.2009-6-25。 


???什么意思?到到2009-6-26时,若debug.log中没有任何日志内容,肯定不会生成debug.log.2009-6-25呀。 


这个是肯定的,但是,到2009-6-26时,如果没有新日志内容生成,即使debug.log中有日志,也不会生成debug.log.2009-6-25呀。
我的意思是想实现这么个功能:在2009-6-26到来时,如果debug.log中有25日的日志,即使26日没有新日志内容生成,也会生成debug.log.2009-6-25。

#8


??

#9


这你需要重写rollOver方法,实现自己的每天记录日志的工程,不会出现第二天没有日志不生成文件的问题
你可以惨遭我写的代码

public class CustomDailyRollingFileAppender extends DailyRollingFileAppender
{
    
    /**
     * file separator
     */
    public static final String FILE_SEPARATOR = System.getProperty("file.separator");
    
    /**
     * The default maximum file size is 10MB.
     */
    public static final int DEFAULT_MAXFILE_SIZE = 10;
    
    /**
     * 1024
     */
    public static final int NUMBER_1024 = 1024;
    
    /**
     * Content of scheduledFilename
     */
    private String scheduledFilename;
    
    /**
     * The date pattern. By default, the pattern is set to 
     *  "yyyy-MM-dd" meaning daily rollover.
     */
    private String datePattern = "yyyy-MM-dd";
    
    /**
     * The file suffix. By default, the suffix is ".txt".
     */
    private String suffix = ".txt";
    
    /**
     * The default maximum file size is 10MB.
     */
    private long maxFileSize = DEFAULT_MAXFILE_SIZE * NUMBER_1024 * NUMBER_1024;
    
    /**
     * There is one backup file by default.
     */
    private int maxBackupIndex = 1;
    
    /**
     * Content of note
     */
    private long nextRollover = 0;
    
    /**
     * Returns the value of the <b>MaxBackupIndex</b> option.
     * @return maxBackupIndex
     */
    public int getMaxBackupIndex()
    {
        return maxBackupIndex;
    }
    
    /**
     * Get the maximum size that the output file is allowed to reach before
     * being rolled over to backup files.
     * 
     * @since 1.1
     * @return maxFileSize
     */
    public long getMaximumFileSize()
    {
        return maxFileSize;
    }
    
    /** (non-Javadoc)
     * @see org.apache.log4j.FileAppender#setFile(java.lang.String)
     * @param file String
     */
    @Override
    public void setFile(String file)
    {
        // Trim spaces from both ends. The users probably does not want
        // trailing spaces in file names.
        String val = file.trim();
        sdf = new SimpleDateFormat(datePattern);
        String dateName = sdf.format(new Date());
        // directory name
        String dirName = val + dateName;
        File fdir = new File(dirName);
        
        if (!fdir.exists())
        {
            //创建目录
            boolean flag = fdir.mkdirs();
            
            if (!flag)
            {
                LogLog.error("CustomDailyRollingFileAppender.setFile mkdir[" + dirName + "] Error!");
            }
        }
        
        StringBuffer buf = new StringBuffer();
        buf.append(dirName).append(FILE_SEPARATOR).append(dateName).append(suffix);
        
        fileName = buf.toString();
    }
    
    /** (non-Javadoc)
     * @see org.apache.log4j.DailyRollingFileAppender#activateOptions()
     */
    @Override
    public void activateOptions()
    {
        super.activateOptions();
        if (datePattern != null && fileName != null)
        {
            now.setTime(System.currentTimeMillis());
            sdf = new SimpleDateFormat(datePattern);
            int type = computeCheckPeriod();
            printPeriodicity(type);
            rc.setType(type);
            // file = logs/2009-12-26/2009-12-26.txt
            File file = new File(fileName);
            
            // scheduledFilename = logs/2009-12-27
            scheduledFilename =
                new File(file.getParentFile().getParentFile(), sdf.format(new Date(file.lastModified()))).getPath();
            
        }
        else
        {
            LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
        }
    }
    
    /**
     * Rollover the current file to a new file.
     */
    @Override
    void rollOver()
        throws IOException
    {
        
        /* Compute filename, but only if datePattern is specified */
        if (datePattern == null)
        {
            errorHandler.error("Missing DatePattern option in rollOver().");
            return;
        }
        
        // file = logs/2009-12-26/
        File file = new File(fileName).getParentFile();
        
        String nowDate = sdf.format(now);
        // logs/[sysdate]/
        File nowFileDir = new File(file.getParentFile(), nowDate);
        
        String datedFilename = nowFileDir.getPath();
        
        // String datedFilename = fileName + sdf.format(now);
        // It is too early to roll over because we are still within the
        // bounds of the current interval. Rollover will occur once the
        // next interval is reached.
        if (scheduledFilename.equals(datedFilename))
        {
            return;
        }
        
        // close current file
        this.closeFile();
        
        try
        {
            
            // This will also close the file. This is OK since multiple
            // close operations are safe.
            // this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
            File currentF = new File(nowFileDir, nowDate + suffix);
            
            this.setFile(currentF.getPath(), false, this.bufferedIO, this.bufferSize);
        }
        catch (IOException e)
        {
            errorHandler.error("setFile(" + fileName + ", false) call failed.");
        }
        scheduledFilename = datedFilename;
    }

#10




public// synchronization not necessary since doAppend is alreasy synched
    void rollOverOfRolling()
    {
        File target;
        File file;
        
        if (qw != null)
        {
            long size = ((CountingQuietWriter)qw).getCount();
            LogLog.debug("rolling over count=" + size);
            // if operation fails, do not roll again until
            // maxFileSize more bytes are written
            nextRollover = size + maxFileSize;
        }
        LogLog.debug("maxBackupIndex=" + maxBackupIndex);
        
        boolean renameSucceeded = true;
        // If maxBackups <= 0, then there is no file renaming to be done.
        if (maxBackupIndex > 0)
        {
            // Delete the oldest file, to keep Windows happy.
            file = new File(fileName + '.' + maxBackupIndex);
            if (file.exists())
            {
                renameSucceeded = file.delete();
            }
                
            
            // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,
            // 2}
            for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--)
            {
                file = new File(fileName + "." + i);
                if (file.exists())
                {
                    target = new File(fileName + '.' + (i + 1));
                    LogLog.debug("Renaming file " + file + " to " + target);
                    renameSucceeded = file.renameTo(target);
                }
            }
            
            if (renameSucceeded)
            {
                // Rename fileName to fileName.1
                target = new File(fileName + "." + 1);
                
                this.closeFile(); // keep windows happy.
                
                file = new File(fileName);
                LogLog.debug("Renaming file " + file + " to " + target);
                renameSucceeded = file.renameTo(target);
                //
                // if file rename failed, reopen file with append = true
                //
                if (!renameSucceeded)
                {
                    try
                    {
                        this.setFile(fileName, true, bufferedIO, bufferSize);
                    }
                    catch (IOException e)
                    {
                        LogLog.error("setFile(" + fileName + ", true) call failed.", e);
                    }
                }
            }
        }
        
        //
        // if all renames were successful, then
        //
        if (renameSucceeded)
        {
            try
            {
                // This will also close the file. This is OK since multiple
                // close operations are safe.
                this.setFile(fileName, false, bufferedIO, bufferSize);
                nextRollover = 0;
            }
            catch (IOException e)
            {
                LogLog.error("setFile(" + fileName + ", false) call failed.", e);
            }
        }
    }
    
    /** (non-Javadoc)
     * @see org.apache.log4j.FileAppender#setFile(java.lang.String, boolean, boolean, int)
     * @param fileName String
     * @param append boolean
     * @param bufferedIO boolean
     * @param bufferSize int
     * @throws IOException IOException
     */
    @Override
    public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
        throws IOException
    {
        // 父类FileAppender.setFile方法存在bug(log4j-1.2.6)。在log4j-1.2.15中修改为以下代码
        // super.setFile(fileName, append, bufferedIO, bufferSize)
        // -------------from log4j1.2.15---------------start
        LogLog.debug("setFile called: " + fileName + ", " + append);
        
        // It does not make sense to have immediate flush and bufferedIO.
        if (bufferedIO)
        {
            setImmediateFlush(false);
        }
        
        reset();
        FileOutputStream ostream = null;
        try
        {
            //
            // attempt to create file
            //
            ostream = new FileOutputStream(fileName, append);
        }
        catch (FileNotFoundException ex)
        {
            //
            // if parent directory does not exist then
            // attempt to create it and try to create file
            // see bug 9150
            //
            String parentName = new File(fileName).getParent();
            if (parentName != null)
            {
                File parentDir = new File(parentName);
                if (!parentDir.exists() && parentDir.mkdirs())
                {
                    ostream = new FileOutputStream(fileName, append);
                }
                else
                {
                    throw ex;
                }
            }
            else
            {
                throw ex;
            }
        }
        Writer fw = createWriter(ostream);
        if (bufferedIO)
        {
            fw = new BufferedWriter(fw, bufferSize);
        }
        this.setQWForFiles(fw);
        this.fileName = fileName;
        this.fileAppend = append;
        this.bufferedIO = bufferedIO;
        this.bufferSize = bufferSize;
        writeHeader();
        LogLog.debug("setFile ended");
        // -----------------------------------------end
        if (append)
        {
            File f = new File(fileName);
            ((CountingQuietWriter)qw).setCount(f.length());
        }
    }
    
    /**
     * Set the maximum number of backup files to keep around.
     * 
     * <p>
     * The <b>MaxBackupIndex</b> option determines how many backup files are
     * kept before the oldest is erased. This option takes a positive integer
     * value. If set to zero, then there will be no backup files and the log
     * file will be truncated when it reaches <code>MaxFileSize</code>.
     * @param maxBackups int
     */
    public void setMaxBackupIndex(int maxBackups)
    {
        this.maxBackupIndex = maxBackups;
    }
    
    /**
     * Set the maximum size that the output file is allowed to reach before
     * being rolled over to backup files.
     * 
     * <p>
     * This method is equivalent to {@link #setMaxFileSize} except that it is
     * required for differentiating the setter taking a <code>long</code>
     * argument from the setter taking a <code>String</code> argument by the
     * JavaBeans {@link java.beans.Introspector Introspector}.
     * 
     * @see #setMaxFileSize(String)
     * @param mFileSize Long
     */
    public void setMaximumFileSize(long mFileSize)
    {
        this.maxFileSize = mFileSize;
    }
    
    /**
     * Set the maximum size that the output file is allowed to reach before
     * being rolled over to backup files.
     * 
     * <p>
     * In configuration files, the <b>MaxFileSize</b> option takes an long
     * integer in the range 0 - 2^63. You can specify the value with the
     * suffixes "KB", "MB" or "GB" so that the integer is interpreted being
     * expressed respectively in kilobytes, megabytes or gigabytes. For example,
     * the value "10KB" will be interpreted as 10240.
     * @param value String
     */
    public void setMaxFileSize(String value)
    {
        maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
    }
    
    @Override
    protected void setQWForFiles(Writer writer)
    {
        this.qw = new CountingQuietWriter(writer, errorHandler);
    }
    
    /**
     * This method differentiates RollingFileAppender from its super class.
     * 
     * @since 0.9.0
     * @param event LoggingEvent
     */
    @Override
    protected void subAppend(LoggingEvent event)
    {
        //按日期方式备份
        super.subAppend(event);
        
        //文件大小方式备份
        if (fileName != null && qw != null)
        {
            long size = ((CountingQuietWriter)qw).getCount();
            if (size >= maxFileSize && size >= nextRollover)
            {
                rollOverOfRolling();
            }
        }
    }
    
    /**
     * get suffix
     * @return the suffix
     */
    public String getSuffix()
    {
        return suffix;
    }
    
    /**
     * set suffix
     * @param suffix the suffix to set
     */
    public void setSuffix(String suffix)
    {
        this.suffix = suffix;
    }
}


代码是分两次发的,写的太多了,这里还有好几个功能,你可以看一下

#1


这个应该比较难,我想它应该是在写日志的时候才去检查是否需要产生新的文件,而不是有一个单独的线程或计时器跑在那里,每隔24小时便产生一个文件。
要么,干脆你修改一下自己的程序,确保每24小时内至少打一条log就是了,哪怕只是报一声平安,呵呵。

#2


呵呵,这也是个主意,谢谢。

那不知有没有更好的方案呢??

#3


我觉得你的需求也怪怪的,没有日志的那天干吗还要产生一个空文件啊?
我反倒觉得没有日志的就没有文件,这是优点,不是缺点。
:P

#4


我的意图是想如果前一天有日志内容,就生成前一天的日志文件如:debug.log.2009-6-25。
譬如说,到2009-6-26时,若debug.log中有日志内容,则生成debug.log.2009-6-25;到2009-6-26时,若debug.log中没有任何日志内容,就不必生成debug.log.2009-6-25。

#5


请各位指教。

#6


引用 4 楼 kld208 的回复:
我的意图是想如果前一天有日志内容,就生成前一天的日志文件如:debug.log.2009-6-25。 
譬如说,到2009-6-26时,若debug.log中有日志内容,则生成debug.log.2009-6-25;到2009-6-26时,若debug.log中没有任何日志内容,就不必生成debug.log.2009-6-25。

???什么意思?到到2009-6-26时,若debug.log中没有任何日志内容,肯定不会生成debug.log.2009-6-25呀。

#7


引用 6 楼 ouyangxiaokang6 的回复:
引用 4 楼 kld208 的回复:
我的意图是想如果前一天有日志内容,就生成前一天的日志文件如:debug.log.2009-6-25。 
譬如说,到2009-6-26时,若debug.log中有日志内容,则生成debug.log.2009-6-25;到2009-6-26时,若debug.log中没有任何日志内容,就不必生成debug.log.2009-6-25。 


???什么意思?到到2009-6-26时,若debug.log中没有任何日志内容,肯定不会生成debug.log.2009-6-25呀。 


这个是肯定的,但是,到2009-6-26时,如果没有新日志内容生成,即使debug.log中有日志,也不会生成debug.log.2009-6-25呀。
我的意思是想实现这么个功能:在2009-6-26到来时,如果debug.log中有25日的日志,即使26日没有新日志内容生成,也会生成debug.log.2009-6-25。

#8


??

#9


这你需要重写rollOver方法,实现自己的每天记录日志的工程,不会出现第二天没有日志不生成文件的问题
你可以惨遭我写的代码

public class CustomDailyRollingFileAppender extends DailyRollingFileAppender
{
    
    /**
     * file separator
     */
    public static final String FILE_SEPARATOR = System.getProperty("file.separator");
    
    /**
     * The default maximum file size is 10MB.
     */
    public static final int DEFAULT_MAXFILE_SIZE = 10;
    
    /**
     * 1024
     */
    public static final int NUMBER_1024 = 1024;
    
    /**
     * Content of scheduledFilename
     */
    private String scheduledFilename;
    
    /**
     * The date pattern. By default, the pattern is set to 
     *  "yyyy-MM-dd" meaning daily rollover.
     */
    private String datePattern = "yyyy-MM-dd";
    
    /**
     * The file suffix. By default, the suffix is ".txt".
     */
    private String suffix = ".txt";
    
    /**
     * The default maximum file size is 10MB.
     */
    private long maxFileSize = DEFAULT_MAXFILE_SIZE * NUMBER_1024 * NUMBER_1024;
    
    /**
     * There is one backup file by default.
     */
    private int maxBackupIndex = 1;
    
    /**
     * Content of note
     */
    private long nextRollover = 0;
    
    /**
     * Returns the value of the <b>MaxBackupIndex</b> option.
     * @return maxBackupIndex
     */
    public int getMaxBackupIndex()
    {
        return maxBackupIndex;
    }
    
    /**
     * Get the maximum size that the output file is allowed to reach before
     * being rolled over to backup files.
     * 
     * @since 1.1
     * @return maxFileSize
     */
    public long getMaximumFileSize()
    {
        return maxFileSize;
    }
    
    /** (non-Javadoc)
     * @see org.apache.log4j.FileAppender#setFile(java.lang.String)
     * @param file String
     */
    @Override
    public void setFile(String file)
    {
        // Trim spaces from both ends. The users probably does not want
        // trailing spaces in file names.
        String val = file.trim();
        sdf = new SimpleDateFormat(datePattern);
        String dateName = sdf.format(new Date());
        // directory name
        String dirName = val + dateName;
        File fdir = new File(dirName);
        
        if (!fdir.exists())
        {
            //创建目录
            boolean flag = fdir.mkdirs();
            
            if (!flag)
            {
                LogLog.error("CustomDailyRollingFileAppender.setFile mkdir[" + dirName + "] Error!");
            }
        }
        
        StringBuffer buf = new StringBuffer();
        buf.append(dirName).append(FILE_SEPARATOR).append(dateName).append(suffix);
        
        fileName = buf.toString();
    }
    
    /** (non-Javadoc)
     * @see org.apache.log4j.DailyRollingFileAppender#activateOptions()
     */
    @Override
    public void activateOptions()
    {
        super.activateOptions();
        if (datePattern != null && fileName != null)
        {
            now.setTime(System.currentTimeMillis());
            sdf = new SimpleDateFormat(datePattern);
            int type = computeCheckPeriod();
            printPeriodicity(type);
            rc.setType(type);
            // file = logs/2009-12-26/2009-12-26.txt
            File file = new File(fileName);
            
            // scheduledFilename = logs/2009-12-27
            scheduledFilename =
                new File(file.getParentFile().getParentFile(), sdf.format(new Date(file.lastModified()))).getPath();
            
        }
        else
        {
            LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
        }
    }
    
    /**
     * Rollover the current file to a new file.
     */
    @Override
    void rollOver()
        throws IOException
    {
        
        /* Compute filename, but only if datePattern is specified */
        if (datePattern == null)
        {
            errorHandler.error("Missing DatePattern option in rollOver().");
            return;
        }
        
        // file = logs/2009-12-26/
        File file = new File(fileName).getParentFile();
        
        String nowDate = sdf.format(now);
        // logs/[sysdate]/
        File nowFileDir = new File(file.getParentFile(), nowDate);
        
        String datedFilename = nowFileDir.getPath();
        
        // String datedFilename = fileName + sdf.format(now);
        // It is too early to roll over because we are still within the
        // bounds of the current interval. Rollover will occur once the
        // next interval is reached.
        if (scheduledFilename.equals(datedFilename))
        {
            return;
        }
        
        // close current file
        this.closeFile();
        
        try
        {
            
            // This will also close the file. This is OK since multiple
            // close operations are safe.
            // this.setFile(fileName, false, this.bufferedIO, this.bufferSize);
            File currentF = new File(nowFileDir, nowDate + suffix);
            
            this.setFile(currentF.getPath(), false, this.bufferedIO, this.bufferSize);
        }
        catch (IOException e)
        {
            errorHandler.error("setFile(" + fileName + ", false) call failed.");
        }
        scheduledFilename = datedFilename;
    }

#10




public// synchronization not necessary since doAppend is alreasy synched
    void rollOverOfRolling()
    {
        File target;
        File file;
        
        if (qw != null)
        {
            long size = ((CountingQuietWriter)qw).getCount();
            LogLog.debug("rolling over count=" + size);
            // if operation fails, do not roll again until
            // maxFileSize more bytes are written
            nextRollover = size + maxFileSize;
        }
        LogLog.debug("maxBackupIndex=" + maxBackupIndex);
        
        boolean renameSucceeded = true;
        // If maxBackups <= 0, then there is no file renaming to be done.
        if (maxBackupIndex > 0)
        {
            // Delete the oldest file, to keep Windows happy.
            file = new File(fileName + '.' + maxBackupIndex);
            if (file.exists())
            {
                renameSucceeded = file.delete();
            }
                
            
            // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3,
            // 2}
            for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--)
            {
                file = new File(fileName + "." + i);
                if (file.exists())
                {
                    target = new File(fileName + '.' + (i + 1));
                    LogLog.debug("Renaming file " + file + " to " + target);
                    renameSucceeded = file.renameTo(target);
                }
            }
            
            if (renameSucceeded)
            {
                // Rename fileName to fileName.1
                target = new File(fileName + "." + 1);
                
                this.closeFile(); // keep windows happy.
                
                file = new File(fileName);
                LogLog.debug("Renaming file " + file + " to " + target);
                renameSucceeded = file.renameTo(target);
                //
                // if file rename failed, reopen file with append = true
                //
                if (!renameSucceeded)
                {
                    try
                    {
                        this.setFile(fileName, true, bufferedIO, bufferSize);
                    }
                    catch (IOException e)
                    {
                        LogLog.error("setFile(" + fileName + ", true) call failed.", e);
                    }
                }
            }
        }
        
        //
        // if all renames were successful, then
        //
        if (renameSucceeded)
        {
            try
            {
                // This will also close the file. This is OK since multiple
                // close operations are safe.
                this.setFile(fileName, false, bufferedIO, bufferSize);
                nextRollover = 0;
            }
            catch (IOException e)
            {
                LogLog.error("setFile(" + fileName + ", false) call failed.", e);
            }
        }
    }
    
    /** (non-Javadoc)
     * @see org.apache.log4j.FileAppender#setFile(java.lang.String, boolean, boolean, int)
     * @param fileName String
     * @param append boolean
     * @param bufferedIO boolean
     * @param bufferSize int
     * @throws IOException IOException
     */
    @Override
    public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
        throws IOException
    {
        // 父类FileAppender.setFile方法存在bug(log4j-1.2.6)。在log4j-1.2.15中修改为以下代码
        // super.setFile(fileName, append, bufferedIO, bufferSize)
        // -------------from log4j1.2.15---------------start
        LogLog.debug("setFile called: " + fileName + ", " + append);
        
        // It does not make sense to have immediate flush and bufferedIO.
        if (bufferedIO)
        {
            setImmediateFlush(false);
        }
        
        reset();
        FileOutputStream ostream = null;
        try
        {
            //
            // attempt to create file
            //
            ostream = new FileOutputStream(fileName, append);
        }
        catch (FileNotFoundException ex)
        {
            //
            // if parent directory does not exist then
            // attempt to create it and try to create file
            // see bug 9150
            //
            String parentName = new File(fileName).getParent();
            if (parentName != null)
            {
                File parentDir = new File(parentName);
                if (!parentDir.exists() && parentDir.mkdirs())
                {
                    ostream = new FileOutputStream(fileName, append);
                }
                else
                {
                    throw ex;
                }
            }
            else
            {
                throw ex;
            }
        }
        Writer fw = createWriter(ostream);
        if (bufferedIO)
        {
            fw = new BufferedWriter(fw, bufferSize);
        }
        this.setQWForFiles(fw);
        this.fileName = fileName;
        this.fileAppend = append;
        this.bufferedIO = bufferedIO;
        this.bufferSize = bufferSize;
        writeHeader();
        LogLog.debug("setFile ended");
        // -----------------------------------------end
        if (append)
        {
            File f = new File(fileName);
            ((CountingQuietWriter)qw).setCount(f.length());
        }
    }
    
    /**
     * Set the maximum number of backup files to keep around.
     * 
     * <p>
     * The <b>MaxBackupIndex</b> option determines how many backup files are
     * kept before the oldest is erased. This option takes a positive integer
     * value. If set to zero, then there will be no backup files and the log
     * file will be truncated when it reaches <code>MaxFileSize</code>.
     * @param maxBackups int
     */
    public void setMaxBackupIndex(int maxBackups)
    {
        this.maxBackupIndex = maxBackups;
    }
    
    /**
     * Set the maximum size that the output file is allowed to reach before
     * being rolled over to backup files.
     * 
     * <p>
     * This method is equivalent to {@link #setMaxFileSize} except that it is
     * required for differentiating the setter taking a <code>long</code>
     * argument from the setter taking a <code>String</code> argument by the
     * JavaBeans {@link java.beans.Introspector Introspector}.
     * 
     * @see #setMaxFileSize(String)
     * @param mFileSize Long
     */
    public void setMaximumFileSize(long mFileSize)
    {
        this.maxFileSize = mFileSize;
    }
    
    /**
     * Set the maximum size that the output file is allowed to reach before
     * being rolled over to backup files.
     * 
     * <p>
     * In configuration files, the <b>MaxFileSize</b> option takes an long
     * integer in the range 0 - 2^63. You can specify the value with the
     * suffixes "KB", "MB" or "GB" so that the integer is interpreted being
     * expressed respectively in kilobytes, megabytes or gigabytes. For example,
     * the value "10KB" will be interpreted as 10240.
     * @param value String
     */
    public void setMaxFileSize(String value)
    {
        maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1);
    }
    
    @Override
    protected void setQWForFiles(Writer writer)
    {
        this.qw = new CountingQuietWriter(writer, errorHandler);
    }
    
    /**
     * This method differentiates RollingFileAppender from its super class.
     * 
     * @since 0.9.0
     * @param event LoggingEvent
     */
    @Override
    protected void subAppend(LoggingEvent event)
    {
        //按日期方式备份
        super.subAppend(event);
        
        //文件大小方式备份
        if (fileName != null && qw != null)
        {
            long size = ((CountingQuietWriter)qw).getCount();
            if (size >= maxFileSize && size >= nextRollover)
            {
                rollOverOfRolling();
            }
        }
    }
    
    /**
     * get suffix
     * @return the suffix
     */
    public String getSuffix()
    {
        return suffix;
    }
    
    /**
     * set suffix
     * @param suffix the suffix to set
     */
    public void setSuffix(String suffix)
    {
        this.suffix = suffix;
    }
}


代码是分两次发的,写的太多了,这里还有好几个功能,你可以看一下