【问题标题】:how to store log files in directory (directory name having current date) every day如何每天将日志文件存储在目录(具有当前日期的目录名称)中
【发布时间】:2018-12-01 13:13:17
【问题描述】:

以下代码创建一个目录,名称为当前日期,并将日志文件存储在该目录中。但是接下来的第二天保持的日志文件也存储在同一目录中。我想每天创建一个与当前日期同名的新目录并在其中存储新的日志文件。

private static Date dir1 = new java.util.Date(System.currentTimeMillis());
private static Date dir = new java.util.Date(System.currentTimeMillis());
private static String baseDir1 = "/home/gaurav/flinklogs/";
private static String newDir1 = createDateBasedDirectory(baseDir1, dir1);

private static FileHandler fh1;

static {
    try {
        fh1 = new FileHandler(newDir1 + "/data.log", 0, 1, true);
    } catch (IOException | SecurityException e) {

    }
}

public static void main(String args[]) throws Exception {
    Logger logger = Logger.getLogger("MyLog");
    // This block configure the logger with handler and formatter
    logger.addHandler(fh);

    SimpleFormatter formatter = new SimpleFormatter();
    fh.setFormatter(formatter);

    // the following statement is used to log any messages
    logger.info(e.getMessage());
}

public static String createDateBasedDirectory(String baseDirectory, Date argDate) {
    String newDir = null;
    if (baseDirectory != null && argDate != null) {
        try {
            String format = "yyyy-MM-dd";
            DateFormat dateFormatter = new SimpleDateFormat(format);
            String date = dateFormatter.format(argDate);

            // check if the directory exists:
            String todaysLogDir = baseDirectory + "\\" + date;

            Path todaysDirectoryPath = Paths.get(todaysLogDir);
            // and check if this Path exists
            if (Files.exists(todaysDirectoryPath)) {
                // if present, just return it in order to write (into) a log file there
                return todaysDirectoryPath.toUri().toString();
            } else {
                newDir = baseDirectory + date;
                new File(newDir).mkdir();
                return newDir.toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return newDir;
}

【问题讨论】:

  • 你应该看看 log4j 或 logback。可以轻松配置这些框架以实现您所描述的日志轮换
  • @Rea Sand 谢谢,但我已经尝试过了...... log4j.properpties 文件和其他东西有很多问题......我只想这样做......任何解决方案??
  • 试试 Logback 一个现代日志框架,由最初制作 log4j 的人开发。 Logback 项目直接实现了slf4j façade API。

标签: java date logging directory logfile


【解决方案1】:

这里的问题是您已将所有变量声明为静态并在静态块中执行文件处理程序分配。

static {

        try {

            fh1 = new FileHandler(newDir1 + "/data.log", 0, 1, true);

        } catch (IOException | SecurityException e) {

        }
    }

因此,一旦您的程序启动,它就会初始化所有内容,然后第二天就不会重新初始化,因为程序已经从前一天开始运行。 您需要根据日期的变化重新分配文件处理程序。

另外,我建议您看看 log4j,因为您可以根据需要轻松配置它。

【讨论】:

  • 谢谢,我如何重新分配文件处理程序以更改日期
  • 尝试每天午夜运行的 cron 作业并重新分配新的处理程序。
  • 抱歉请详细说明...如何使用 cron 作业
  • 如果您不确定 cron 作业是如何工作的,我强烈建议您不要编写自己的日志框架。请尝试按照其他人的建议重用现有框架,这些框架已经为您完成这项工作。
  • 我使用过 log4j,但问题在于当我在服务器上运行我的 jar 文件时,它无法找到 log4j.properties 文件,这就是我使用它的原因....
【解决方案2】:

您的日期时间处理可能需要一些帮助。

首先,您正在使用麻烦的旧日期时间类(DateSimpleDateFormat),这些类在几年前已被 java.time 类取代。而且您忽略了时区的关键问题(在下面进一步讨论)。

  • java.util.Date 替换为 java.time.Instant
  • SimpleDateFormat 替换为 java.time.format.DateTimeFormatter

您所需的 YYYY-MM-DD 格式由 ISO 8601 标准定义。 java.time 类在生成/解析字符串时默认使用标准格式。所以不需要指定格式模式。

Instant

新的 java.util.Date(System.currentTimeMillis())

你的代码是多余的。简单地调用new Date() 具有相同的效果,捕获自 1970 UTC 第一时刻的纪元参考以来的毫秒数,1970-01-01T00:00:00Z。

现代代码将Date 替换为InstantInstant 类代表UTC 时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

但我们真的不需要Instant 来回答您的问题。请改用LocalDate

LocalDate

LocalDate 类表示没有时间和时区的仅日期值。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜过后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。

如果没有指定时区,JVM 会隐式应用其当前的默认时区。该默认值可能在运行时(!)期间change at any moment,因此您的结果可能会有所不同。最好将您的 [期望/预期时区][2] 明确指定为参数。

continent/region 的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

如果你想使用 JVM 当前的默认时区,请求它并作为参数传递。如果省略,则隐式应用 JVM 的当前默认值。最好是明确的,因为默认值可能会在任何时候在运行时被 JVM 中任何应用程序的任何线程中的任何代码更改。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

或者您可能会选择始终使用 UTC,就像人们运行 Stack Overflow 一样。请注意您的每日声望点如何累积,例如,如果在美国西海岸时间下午 4 点左右。

LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;

字符串

要生成标准 ISO 8601 格式的String,只需调用LocalDate::toString

String output = today.toString() ; 

日志框架

正如其他人所建议的那样,您不应该每天花费宝贵的时间重新发明日志框架来翻转文件夹。任何体面的日志框架都可以为您做到这一点。

特别是,我建议您首先考虑使用slf4j façade API。在您想要将信息发送到日志的代码中,调用 slf4jslf4j 背后是许多不同的日志框架。您可以稍后将一个日志框架切换为另一个,而无需更改应用程序的代码。

如果尚未使用日志框架,请采用LogbackLogback 项目是 slf4j API 的直接实现。所以不需要适配器。

slf4jLogback 都是由发明 log4j 的同一个人编写的。所以他在这个领域有很多经验。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-04
    • 2019-11-25
    • 2014-11-04
    • 1970-01-01
    • 2020-04-22
    • 2015-04-21
    • 2019-03-28
    • 1970-01-01
    相关资源
    最近更新 更多