以相反的顺序逐行读取文件 [英] Read a file line by line in reverse order
问题描述
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屋!