@Author Jacky Wang
轉(zhuǎn)載請注明出處,http://www.reibang.com/p/1c1b35d9be9b
碰到一個需求,在某個服務(wù)的日志文件達到指定大小之后,刪除該日志文件前面多少行,在后面追加新的日志用僧。以下,為此次使用隨機文件流操作文件內(nèi)容所記科阎。
/**
* @Title: removeFileLine
* @Description: TODO(該方法為從文件開頭刪除前n行)
* @param: @param file 文件
* @param: @param lineNum 刪除的行行數(shù)
* @param: @throws IOException
* @return: void
* @throws
*/
public void removeFileLine(File file, int lineNum) throws IOException {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(file, "rw");
// Initial write position.
// 寫文件的位置標記,從文件開頭開始,后續(xù)讀取文件內(nèi)容從該標記開始
long writePosition = raf.getFilePointer();
for (int i = 0; i < lineNum; i++) {
String line = raf.readLine();
if (line == null) {
break;
}
}
// Shift the next lines upwards.
// 讀文件的位置標記,寫完之后回到該標記繼續(xù)讀該行
long readPosition = raf.getFilePointer();
// 利用兩個標記,
byte[] buff = new byte[1024];
int n;
while (-1 != (n = raf.read(buff))) {
raf.seek(writePosition);
raf.write(buff, 0, n);
readPosition += n;
writePosition += n;
raf.seek(readPosition);
}
raf.setLength(writePosition);
} catch (IOException e) {
logger.error("readAndRemoveFirstLines error", e);
throw e;
} finally {
try {
if (raf != null) {
raf.close();
}
} catch (IOException e) {
logger.error("close RandomAccessFile error", e);
throw e;
}
}
}
/**
* @Title: appendContentToFile
* @Description: TODO(在文件末尾追加內(nèi)容)
* @param: @param file
* @param: @param content
* @param: @throws IOException
* @return: void
* @throws
*/
public static void appendContentToFile(File file, String content) throws IOException {
RandomAccessFile randomFile = null;
try {
// 打開一個隨機訪問文件流,按讀寫方式
randomFile = new RandomAccessFile(file, "rw");
// 文件長度,字節(jié)數(shù)
long fileLength = randomFile.length();
// 將寫文件指針移到文件尾根盒。
randomFile.seek(fileLength);
randomFile.writeBytes(content);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (randomFile != null) {
randomFile.close();
randomFile = null;
}
}
}
/**
* @Title: checkFileInSize
* @Description: TODO(檢查文件字節(jié)數(shù)是否超出限制)
* @param: @param file
* @param: @param limitSize
* @param: @return
* @return: boolean
* @throws
*/
private boolean checkFileInSize(File file, Long limitSize) {
return file.length() <= limitSize;
}
以上就是上述需求用到的方法了,下面將上面的方法整合完成需求纠拔。
@Component
@SuppressWarnings("restriction")
@PropertySource("classpath:/config/ivg.properties")
public class AppStartupListener implements ApplicationRunner {
@Value("${log.startup.path}")
private String logPath;// 日志保存路徑
@Value("${log.startup.output.statement}")
private String outputStatement;// 追加日志內(nèi)容模板
@Value("${log.startup.limit.size}")
private Long limitSize;// 文件大小限制,eg:50M:50*1024*1024 = 52428800
@Value("${log.startup.remove.line}")
private int removeLineNum;// 超過限制之后一次刪除多少行
private void initLog() {
logger.info("***程序啟動日志記錄開始***");
// 檢查文件是否存在
File file = null;
try {
file = new File(logPath);
if (!file.exists() || !file.isFile()) {
logger.info("file is not exist,creating " + logPath + " now...");
file.createNewFile();
}
StringBuilder sb = new StringBuilder(outputStatement);
SimpleDateFormat sdf = new SimpleDateFormat(" yyyy-MM-dd HH:mm:ss");
String date = sdf.format(new Date());
String outputLog = sb.append(date).append("\r\n").toString();
// 檢查文件大小
while (!checkFileInSize(file, limitSize)) {
// 先刪除前三行
removeFileLine(file, removeLineNum);
}
// 追加項目啓動log日志
appendContentToFile(file, outputLog);
} catch (FileNotFoundException e) {
logger.error("StartupLog Listener error,{}", e);
} catch (IOException e) {
logger.error("StartupLog Listener error,{}", e);
}
}
}
至此需求已完成。通過此次需求,學習了RandomAccessFile隨機文件流的一些簡單使用方式,記錄在此蜜氨。