以相反的顺序逐行读取文件 [英] Read a file line by line in reverse order

查看:219
本文介绍了以相反的顺序逐行读取文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个java ee应用程序,我使用servlet来打印使用log4j创建的日志文件。当读取日志文件时,通常会查找最后一个日志行,因此如果以相反的顺序打印日志文件,servlet将会更加有用。我的实际代码是:

  response.setContentType(text); 
PrintWriter out = response.getWriter();
try {
FileReader logReader = new FileReader(logfile.log);
try {
BufferedReader buffer = new BufferedReader(logReader);
for(String line = buffer.readLine(); line!= null; line = buffer.readLine()){
out.println(line);
}
} finally {
logReader.close();
}
} finally {
out.close();
}

我在互联网中发现的实现涉及使用StringBuffer并加载所有打印之前的文件是否没有代码光的方式来寻找文件的末尾并读取内容直到文件的开头?

解决方案



根据请求,我以后评论的意见提前给出答案:如果您经常需要这种行为,更合适的解决方案可能是使用DBAppender(log4j 2的一部分)将日志从文本文件移动到数据库表。然后你可以简单地查询最新的条目。



[/ EDIT]



我可能会略有不同比起列出的答案。



(1)创建一个 Writer 的子类,它将每个字符的编码字节写入反向顺序:

  public class ReverseOutputStreamWriter extends Writer {
private OutputStream out;
私人Charset编码;
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))。
//以相反的顺序写入字节到this.out
}
//其他重载方法
}

(2)创建一个log4j的子类 WriterAppender createWriter 方法将被覆盖以创建一个 ReverseOutputStreamWriter 的实例。



(3)创建一个log4j 布局格式方法以反向字符顺序返回日志字符串:

  public class ReversePatternLayout extends PatternLayout {
//构造函数
public String format(LoggingEvent event){
return new StringBuilder(super.format(event) 。).reverse()的toString();
}
}

(4)修改我的日志配置文件发送日志消息到 正常日志文件和反向日志文件。 反向日志文件将包含与正常日志文件相同的日志消息,但每个消息将向后写入。 (请注意,反向日志文件的编码不一定符合UTF-8,甚至是任何字符编码。)



(5)创建一个子类 InputStream 包装一个 RandomAccessFile 的实例,以便以相反的顺序读取文件的字节:

  public class ReverseFileInputStream扩展InputStream {
private RandomAccessFile in;
private byte [] buffer;
//要读取的下一个字节的索引。
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 {
//记录旧位置
//寻找新的前一个位置
//从新的位置到旧位置进入缓冲区
//反向缓冲区
}
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 ++];
}
//其他重写方法
}

我想以相反的顺序读取正常日志文件的条目,我只需要创建一个 ReverseFileInputStream 的实例,给它尊敬的日志文件。 / p>

I have a java ee application where I use a servlet to print a log file created with log4j. When reading log files you are usually looking for the last log line and therefore the servlet would be much more useful if it printed the log file in reverse order. My actual code is:

    response.setContentType("text");
    PrintWriter out = response.getWriter();
    try {
        FileReader logReader = new FileReader("logfile.log");
        try {
            BufferedReader buffer = new BufferedReader(logReader);
            for (String line = buffer.readLine(); line != null; line = buffer.readLine()) {
                out.println(line);
            }
        } finally {
            logReader.close();
        }
    } finally {
        out.close();
    }

The implementations I've found in the internet involve using a StringBuffer and loading all the file before printing, isn't there a code light way of seeking to the end of the file and reading the content till the start of the file?

解决方案

[EDIT]

By request, I am prepending this answer with the sentiment of a later comment: If you need this behavior frequently, a "more appropriate" solution is probably to move your logs from text files to database tables with DBAppender (part of log4j 2). Then you could simply query for latest entries.

[/EDIT]

I would probably approach this slightly differently than the answers listed.

(1) Create a subclass of Writer that writes the encoded bytes of each character in reverse order:

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) Create a subclass of log4j WriterAppender whose createWriter method would be overridden to create an instance of ReverseOutputStreamWriter.

(3) Create a subclass of log4j Layout whose format method returns the log string in reverse character order:

public class ReversePatternLayout extends PatternLayout {
    // constructors
    public String format(LoggingEvent event) {
        return new StringBuilder(super.format(event)).reverse().toString();
    }
}

(4) Modify my logging configuration file to send log messages to both the "normal" log file and a "reverse" log file. The "reverse" log file would contain the same log messages as the "normal" log file, but each message would be written backwards. (Note that the encoding of the "reverse" log file would not necessarily conform to UTF-8, or even any character encoding.)

(5) Create a subclass of InputStream that wraps an instance of RandomAccessFile in order to read the bytes of a file in reverse order:

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
}

Now if I want to read the entries of the "normal" log file in reverse order, I just need to create an instance of ReverseFileInputStream, giving it the "revere" log file.

这篇关于以相反的顺序逐行读取文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆