[编辑]
根据请求,我在以后的评论的情绪前面这个答案:如果你需要这个行为频繁,一个“更适当的”解决方案可能是将您的日志从文本文件到DBAppender(log4j 2的一部分)。然后你可以简单地查询最新的条目。
[/编辑]
我可能会接近这个略有不同的答案列出。
(1)创建Writer的子类,以相反的顺序写入每个字符的编码字节:
public class ReverseOutputStreamWriter extends Writer {
private OutputStream out;
private Charset encoding;
public ReverseOutputStreamWriter(OutputStream out, Charset encoding) {
this.out = out;
this.encoding = encoding;
}
public void write(int ch) throws IOException {
byte[] buffer = this.encoding.encode(String.valueOf(ch)).array();
// write the bytes in reverse order to this.out
}
// other overloaded methods
}
(2)创建一个log4j WriterAppender的子类,其createWriter方法将被重写以创建一个ReverseOutputStreamWriter实例。
(3)创建一个log4j Layout的子类,其格式方法以相反的字符顺序返回日志字符串:
public class ReversePatternLayout extends PatternLayout {
// constructors
public String format(LoggingEvent event) {
return new StringBuilder(super.format(event)).reverse().toString();
}
}
(4)修改我的日志配置文件,以将日志消息发送到“正常”日志文件和“反向”日志文件。 “反向”日志文件将包含与“正常”日志文件相同的日志消息,但每个消息将被向后写。 (请注意,“反向”日志文件的编码不一定符合UTF-8,甚至不符合任何字符编码。)
(5)创建一个InputStream的子类,它包装了RandomAccessFile的一个实例,以便以相反的顺序读取文件的字节:
public class ReverseFileInputStream extends InputStream {
private RandomAccessFile in;
private byte[] buffer;
// The index of the next byte to read.
private int bufferIndex;
public ReverseFileInputStream(File file) {
this.in = new RandomAccessFile(File, "r");
this.buffer = new byte[4096];
this.bufferIndex = this.buffer.length;
this.in.seek(file.length());
}
public void populateBuffer() throws IOException {
// record the old position
// seek to a new, previous position
// read from the new position to the old position into the buffer
// reverse the buffer
}
public int read() throws IOException {
if (this.bufferIndex == this.buffer.length) {
populateBuffer();
if (this.bufferIndex == this.buffer.length) {
return -1;
}
}
return this.buffer[this.bufferIndex++];
}
// other overridden methods
}
现在,如果我想以相反的顺序读取“正常”日志文件的条目,我只需要创建一个ReverseFileInputStream的实例,给它“revere”日志文件。