Backend Development 8 min read

Simple Java Logging Utility (LogUtils) with Console and File Output

This article introduces a lightweight Java logging utility class named LogUtils that supports four log levels, formats messages, and can output logs to the console or a file, with configurable level, target, and file settings, accompanied by example usage code.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Simple Java Logging Utility (LogUtils) with Console and File Output

This article presents a self‑contained Java logging utility class called LogUtils . The class defines four log levels (debug, info, warn, error), formats log entries with timestamps, tags, and message length limits, and allows output to the console, a file, or both. Configuration methods let developers set the minimum log level, specify a log file, and choose output targets.

Implementation code:

package com.XXX.utiles;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 日志输出工具
 可以输出到控制台和指定的文件中
 分为4个级别,由低到高分别为: debug, info, warn, error
 输出级别:
 输出debug:debug, info, warn, error
 输出info:info, warn, error
 输出warn:warn, error
 输出error:error

 info Demo:{@code
 可选:设置日志输出级别默认为info级别    LogUtils.setLogOutLevel(LogUtils.Level.DEBUG);
 可选:设置日志输出文件追加到文件尾部     LogUtils.setLogOutFile(new File("MyLog.log"));
 可选:设置日志输出位置是否输出到控制台和是否输出到文件默认只输出到控制台不输出到文件     LogUtils.setLogOutTarget(true, true);
 输出日志
 *     LogUtils.debug("TAG", "The debug log.");
 *     LogUtils.info("TAG", "The info log.");
 *     LogUtils.warn("TAG", "The warn log.");
 *     LogUtils.error("TAG", "The error log.");
 */
public class LogUtils {
    private static final int TAG_MAX_LENGTH = 20;
    private static final int MESSAGE_MAX_LENGTH = 1024;
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd HH:mm:ss.SSS");
    private static Level logOutLevel = Level.INFO;
    private static boolean isOutToConsole = true;
    private static boolean isOutToFile = false;
    private static File logOutFile;
    private static RandomAccessFile logOutFileStream;

    public static void setLogOutLevel(Level currentLevel) {
        if (currentLevel == null) {
            currentLevel = Level.INFO;
        }
        LogUtils.logOutLevel = currentLevel;
    }

    public static synchronized void setLogOutFile(File logOutFile) throws IOException {
        LogUtils.logOutFile = logOutFile;
        if (logOutFileStream != null) {
            closeStream(logOutFileStream);
            logOutFileStream = null;
        }
        if (LogUtils.logOutFile != null) {
            try {
                logOutFileStream = new RandomAccessFile(LogUtils.logOutFile, "rw");
                logOutFileStream.seek(LogUtils.logOutFile.length());
                logOutFileStream.seek(LogUtils.logOutFile.length());
            } catch (IOException e) {
                closeStream(logOutFileStream);
                logOutFileStream = null;
                throw e;
            }
        }
    }

    public static void setLogOutTarget(boolean isOutToConsole, boolean isOutToFile) {
        LogUtils.isOutToConsole = isOutToConsole;
        LogUtils.isOutToFile = isOutToFile;
    }

    public static void debug(String tag, String message) {
        printLog(Level.DEBUG, tag, message, false);
    }

    public static void info(String tag, String message) {
        printLog(Level.INFO, tag, message, false);
    }

    public static void warn(String tag, String message) {
        printLog(Level.WARN, tag, message, false);
    }

    public static void error(String tag, String message) {
        printLog(Level.ERROR, tag, message, true);
    }

    public static void error(String tag, Exception e) {
        if (e == null) {
            error(tag, (String) null);
            return;
        }
        PrintStream printOut = null;
        try {
            ByteArrayOutputStream bytesBufOut = new ByteArrayOutputStream();
            printOut = new PrintStream(bytesBufOut);
            e.printStackTrace(printOut);
            printOut.flush();
            error(tag, new String(bytesBufOut.toByteArray(), "UTF-8"));
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            closeStream(printOut);
        }
    }

    private static void printLog(Level level, String tag, String message, boolean isOutToErr) {
        if (level.getLevelValue() >= logOutLevel.getLevelValue()) {
            String log = DATE_FORMAT.format(new Date()) +
                    " " +
                    level.getTag() +
                    "/" +
                    checkTextLengthLimit(tag, TAG_MAX_LENGTH) +
                    ": " +
                    checkTextLengthLimit(message, MESSAGE_MAX_LENGTH);
            if (isOutToConsole) {
                outLogToConsole(isOutToErr, log);
            }
            if (isOutToFile) {
                outLogToFile(log);
            }
        }
    }

    private static void outLogToConsole(boolean isOutToErr, String log) {
        if (isOutToErr) {
            System.err.println(log);
        } else {
            System.out.println(log);
        }
    }

    private static synchronized void outLogToFile(String log) {
        if (logOutFileStream != null) {
            try {
                logOutFileStream.write((log + "\n").getBytes("UTF-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static String checkTextLengthLimit(String text, int maxLength) {
        if ((text != null) && (text.length() > maxLength)) {
            text = text.substring(0, maxLength - 3) + "...";
        }
        return text;
    }

    private static void closeStream(Closeable stream) {
        if (stream != null) {
            try {
                stream.close();
            } catch (Exception e) {
            }
        }
    }

    public static enum Level {
        DEBUG("D", 1), INFO("I", 2), WARN("W", 3), ERROR("E", 4);
        private String tag;
        private int levelValue;

        private Level(String tag, int levelValue) {
            this.tag = tag;
            this.levelValue = levelValue;
        }

        public String getTag() {
            return tag;
        }

        public int getLevelValue() {
            return levelValue;
        }
    }
}

Example usage demonstrates configuring the logger to output all levels, write to a file named MyLog.log , and enable both console and file targets, then emitting a debug, info, warn, and error message.

package com.XXX.utiles;

import java.io.File;

public class Main {
    private static final String TAG = "Main";
    public static void main(String[] args) throws Exception {
        LogUtils.setLogOutLevel(LogUtils.Level.DEBUG);
        LogUtils.setLogOutFile(new File("MyLog.log"));
        LogUtils.setLogOutTarget(true, true);

        LogUtils.debug(TAG, "The debug log.");
        LogUtils.info(TAG, "The info log.");
        LogUtils.warn(TAG, "The warn log.");
        LogUtils.error(TAG, "The error log.");
    }
}
BackendJavaloggingUtilityFileIOconsole
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.