java讀取用戶登入退出日志信息上傳服務(wù)端
本文實(shí)例為大家分享了讀取用戶登入出日志并上傳服務(wù)端的具體實(shí)現(xiàn)代碼,供大家參考,具體內(nèi)容如下
該客戶端運(yùn)行在給用戶提供unix服務(wù)的服務(wù)器上。用來(lái)讀取并收集該服務(wù)器上用戶的上下線信息,并進(jìn)行配對(duì)整理后發(fā)送給服務(wù)端匯總。
具體實(shí)現(xiàn)代碼:
1. DMSServer.java
package com.dms;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* DMS服務(wù)端,用來(lái)接收每個(gè)客戶端發(fā)送過(guò)來(lái)的
* 配對(duì)日志并保存在本地文件中
* @author Administrator
*
*/
public class DMSServer {
//屬性定義
//用來(lái)接收客戶端連接的服務(wù)端的ServerSocket
private ServerSocket server;
//用來(lái)管理處理客戶端請(qǐng)求的線程的線程池
private ExecutorService threadPool;
//保存所有客戶端發(fā)送過(guò)來(lái)配對(duì)日志的文件
private File serverLogFile;
//消息隊(duì)列
private BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
public DMSServer() throws Exception{
try {
System.out.println("服務(wù)端正在初始化...");
//1 解析配置文件server-config.xml
Map<String,String> config = loadConfig();
//2 根據(jù)配置文件內(nèi)容初始化屬性
init(config);
System.out.println("服務(wù)端初始化完畢...");
} catch (Exception e) {
System.out.println("初始化服務(wù)端失敗!");
throw e;
}
}
/**
* 構(gòu)造方法初始化第一步,解析配置文件
* @return 返回的Map中保存的是配置文件中的
* 每一條內(nèi)容,其中key:標(biāo)簽的名字,
* value為標(biāo)簽中間的文本
* @throws Exception
*/
private Map<String,String> loadConfig() throws Exception{
try {
SAXReader reader = new SAXReader();
Document doc
= reader.read(new File("server-config.xml"));
Element root = doc.getRootElement();
Map<String,String> config
= new HashMap<String,String>();
/*
* 獲取<config>標(biāo)簽中的所有子標(biāo)簽
* 并將每一個(gè)子標(biāo)簽的名字作為key,中間的
* 文本作為value存入Map集合
*/
List<Element> list = root.elements();
for(Element e : list){
String key = e.getName();
String value = e.getTextTrim();
config.put(key, value);
}
return config;
} catch (Exception e) {
System.out.println("解析配置文件異常!");
e.printStackTrace();
throw e;
}
}
/**
* 構(gòu)造方法初始化第二步,根據(jù)配置項(xiàng)初始化屬性
* @param config
* @throws Exception
*/
private void init(Map<String,String> config) throws Exception{
/*
* 用配置文件中的<logrecfile>初始化屬性:serverLogFile
* 用配置文件中的<threadsum>初始化屬性:threadPool,這里創(chuàng)建固定大小線程池。該值作為線程池線程數(shù)量
* 用配置文件中的<serverport>初始化屬性:server,這里這個(gè)值為ServerSocket的服務(wù)端口
*/
this.server = new ServerSocket(
Integer.parseInt(config.get("serverport"))
);
this.serverLogFile = new File(
config.get("logrecfile")
);
this.threadPool = Executors.newFixedThreadPool(
Integer.parseInt(config.get("threadsum"))
);
}
/**
* 服務(wù)端開(kāi)始工作的方法
* @throws Exception
*/
public void start() throws Exception{
/*
* 實(shí)現(xiàn)要求:
* 首先單獨(dú)啟動(dòng)一個(gè)線程,用來(lái)運(yùn)行SaveLogHandler
* 這個(gè)任務(wù),目的是保存所有配對(duì)日志
* 然后開(kāi)始循環(huán)監(jiān)聽(tīng)服務(wù)端端口,一旦一個(gè)客戶端連接了,
* 就實(shí)例化一個(gè)ClientHander,然后將該任務(wù)交給線程池
* 使其分配線程來(lái)處理與該客戶端的交互。
*
*/
try {
System.out.println("服務(wù)端開(kāi)始工作...");
SaveLogHandler slh=new SaveLogHandler();
new Thread(slh).start();
while(true){
Socket socket=server.accept();
threadPool.execute(new ClientHandler(socket));
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
public static void main(String[] args) {
try {
DMSServer server = new DMSServer();
server.start();
} catch (Exception e) {
System.out.println("啟動(dòng)服務(wù)端失敗!");
}
}
/**
* 該線程負(fù)責(zé)從消息隊(duì)列中取出每一條配對(duì)日志,
* 并存入到serverLogFile文件
* @author Administrator
*
*/
private class SaveLogHandler implements Runnable{
public void run(){
PrintWriter pw = null;
try {
pw = new PrintWriter(
new FileOutputStream(
serverLogFile,true
)
);
while(true){
if(messageQueue.size()>0){
pw.println(messageQueue.poll());
}else{
pw.flush();
Thread.sleep(500);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally{
if(pw != null){
pw.close();
}
}
}
}
/**
* 處理一個(gè)指定客戶端請(qǐng)求
* @author Administrator
*
*/
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket = socket;
}
public void run(){
/*
* 思路:
* 首先接收客戶端發(fā)送過(guò)來(lái)的所有配對(duì)日志,
* 直到讀取到"OVER"為止,然后將這些配對(duì)
* 日志保存到本地的文件中,并回復(fù)客戶端
* "OK"
* 執(zhí)行步驟:
* 1:通過(guò)Socket創(chuàng)建輸出流,用來(lái)給客戶端
* 發(fā)送響應(yīng)
* 2:通過(guò)Socket創(chuàng)建輸入流,讀取客戶端發(fā)送
* 過(guò)來(lái)的日志
* 3:循環(huán)讀取客戶端發(fā)送過(guò)來(lái)的每一行字符串,并
* 先判斷是否為字符串"OVER",若不是,則是
* 一條配對(duì)日志,那么保存到本地文件,若是,
* 則停止讀取。
* 4:成功讀取所有日志后回復(fù)客戶端"OK"
*/
PrintWriter pw = null;
try {
//1
pw = new PrintWriter(
new OutputStreamWriter(
socket.getOutputStream(),"UTF-8"
)
);
//2
BufferedReader br = new BufferedReader(
new InputStreamReader(
socket.getInputStream(),"UTF-8"
)
);
//3
String message = null;
while((message = br.readLine())!=null){
if("OVER".equals(message)){
break;
}
//將該日志寫(xiě)入文件保存
messageQueue.offer(message);
}
//4
pw.println("OK");
pw.flush();
} catch (Exception e) {
e.printStackTrace();
pw.println("ERROR");
pw.flush();
} finally{
try {
//與客戶端斷開(kāi)連接釋放資源
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2. DMSClient.java
package com.dms;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.dms.bo.LogData;
import com.dms.bo.LogRec;
/**
* 該客戶端運(yùn)行在給用戶提供unix服務(wù)的服務(wù)器上。
* 用來(lái)讀取并收集該服務(wù)器上用戶的上下線信息,并
* 進(jìn)行配對(duì)整理后發(fā)送給服務(wù)端匯總。
* @author Administrator
*
*/
public class DMSClient {
//屬性定義
//第一步:解析日志所需屬性
//unix系統(tǒng)日志文件
private File logFile;
//保存解析后日志的文件
private File textLogFile;
//書(shū)簽文件
private File lastPositionFile;
//每次解析日志的條目數(shù)
private int batch;
//第二步:配對(duì)日志所需要屬性
//保存配對(duì)日志的文件
private File logRecFile;
//保存未配對(duì)日志的文件
private File loginLogFile;
//第三步:發(fā)送日志所需要屬性
//服務(wù)端地址
private String serverHost;
//服務(wù)端端口
private int serverPort;
/**
* 構(gòu)造方法,用來(lái)初始化客戶端
* @throws Exception
*/
public DMSClient() throws Exception{
try {
//1 解析配置文件config.xml
Map<String,String> config = loadConfig();
//打樁
System.out.println(config);
//2 根據(jù)配置文件內(nèi)容初始化屬性
init(config);
} catch (Exception e) {
System.out.println("初始化失敗!");
throw e;
}
}
/**
* 構(gòu)造方法初始化第二步,根據(jù)配置項(xiàng)初始化屬性
* @param config
* @throws Exception
*/
private void init(Map<String,String> config) throws Exception{
try {
logFile = new File(
config.get("logfile")
);
textLogFile = new File(
config.get("textlogfile")
);
lastPositionFile = new File(
config.get("lastpositionfile")
);
batch = Integer.parseInt(
config.get("batch")
);
logRecFile = new File(
config.get("logrecfile")
);
loginLogFile = new File(
config.get("loginlogfile")
);
serverHost = config.get("serverhost");
serverPort = Integer.parseInt(
config.get("serverport")
);
} catch (Exception e) {
System.out.println("初始化屬性失敗!");
e.printStackTrace();
throw e;
}
}
/**
* 構(gòu)造方法初始化第一步,解析配置文件
* @return 返回的Map中保存的是配置文件中的
* 每一條內(nèi)容,其中key:標(biāo)簽的名字,
* value為標(biāo)簽中間的文本
* @throws Exception
*/
private Map<String,String> loadConfig() throws Exception{
try {
SAXReader reader = new SAXReader();
Document doc
= reader.read(new File("config.xml"));
Element root = doc.getRootElement();
Map<String,String> config
= new HashMap<String,String>();
/*
* 獲取<config>標(biāo)簽中的所有子標(biāo)簽
* 并將每一個(gè)子標(biāo)簽的名字作為key,中間的
* 文本作為value存入Map集合
*/
List<Element> list = root.elements();
for(Element e : list){
String key = e.getName();
String value = e.getTextTrim();
config.put(key, value);
}
return config;
} catch (Exception e) {
System.out.println("解析配置文件異常!");
e.printStackTrace();
throw e;
}
}
/**
* 客戶端開(kāi)始工作的方法
* 循環(huán)執(zhí)行三步:
* 1:解析日志
* 2:配對(duì)日志
* 3:發(fā)送日志
*/
public void start(){
parseLogs();
matchLogs();
sendLogs();
// while(true){
// //解析日志
// if(!parseLogs()){
// continue;
// }
// //配對(duì)日志
// if(!matchLogs()){
// continue;
// }
// //發(fā)送日志
// sendLogs();
// }
}
/**
* 第三步:發(fā)送日志
* @return true:發(fā)送成功
* false:發(fā)送失敗
*/
private boolean sendLogs(){
/*
* 實(shí)現(xiàn)思路:
* 將logRecFile文件中的所有配對(duì)日志讀取
* 出來(lái)然后連接上服務(wù)端并發(fā)送過(guò)去,若服務(wù)端
* 全部接收,就可以將該文件刪除,表示發(fā)送
* 完畢了。
* 實(shí)現(xiàn)步驟:
* 1:logRecFile文件必須存在
* 2:將所有配對(duì)日志讀取出來(lái)并存入一個(gè)集合
* 等待發(fā)送
* 3:通過(guò)Socket連接服務(wù)端
* 4:創(chuàng)建輸出流
* 5:順序?qū)⑺信鋵?duì)日志按行發(fā)送給服務(wù)端
* 6:單獨(dú)發(fā)送一個(gè)字符串"OVER"表示所有日志
* 均已發(fā)送完畢
* 7:創(chuàng)建輸入流
* 8:讀取服務(wù)端發(fā)送回來(lái)的響應(yīng)字符串
* 9:若響應(yīng)的字符串為"OK",表示服務(wù)端正常
* 接收了所有日志,這時(shí)就可以將logRecFile
* 文件刪除并返回true表示發(fā)送完畢。
*
*/
Socket socket = null;
try {
//1
if(!logRecFile.exists()){
System.out.println(logRecFile+"不存在!");
return false;
}
//2
List<String> matches
= IOUtil.loadLogRec(logRecFile);
//3
socket = new Socket(serverHost,serverPort);
//4
PrintWriter pw = new PrintWriter(
new OutputStreamWriter(
socket.getOutputStream(),"UTF-8"
)
);
//5
for(String log : matches){
pw.println(log);
}
//6
pw.println("OVER");
pw.flush();
//7
BufferedReader br = new BufferedReader(
new InputStreamReader(
socket.getInputStream(),"UTF-8"
)
);
//8
String response = br.readLine();
//9
if("OK".equals(response)){
logRecFile.delete();
return true;
}else{
System.out.println("發(fā)送日志失敗!");
return false;
}
} catch (Exception e) {
System.out.println("發(fā)送日志失敗!");
e.printStackTrace();
} finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 第二步:配對(duì)日志
* @return true:配對(duì)成功
* false:配對(duì)失敗
*/
private boolean matchLogs(){
/*
* 實(shí)現(xiàn)思路:
* 將第一步解析的新日志,與上次為配對(duì)成功
* 的登入日志全部讀取出來(lái),然后再按照user,
* pid相同,type一個(gè)是7,一個(gè)是8進(jìn)行配對(duì)。
* 只要能找到類(lèi)型為8的,一定可以找到一個(gè)
* 能與之配對(duì)的登入日志。
*
* 實(shí)現(xiàn)步驟:
* 1:必要的判斷
* 1.1:logRecFile是否存在,存在則不再
* 進(jìn)行新的配對(duì)工作,避免覆蓋。
* 1.2:textLogFile文件必須存在。
* 2:讀取textLogFile將日志讀取出來(lái),并
* 存入到集合中。(若干LogData實(shí)例)
* 3:若loginLogFile文件若存在,則說(shuō)明
* 有上次未配對(duì)成功的日志,也將其讀取
* 出來(lái)存入集合等待一起配對(duì)
* 4:配對(duì)工作
* 4.1:創(chuàng)建一個(gè)集合,用于保存所有配對(duì)日志
* 4.2:創(chuàng)建兩個(gè)Map分別保存登入日志與登出日志
* 4.3:遍歷所有待配對(duì)的日志,按照登入與登出
* 分別存入兩個(gè)Map中,
* 其中key:user,pid
* value:LogData實(shí)例
* 4.4:遍歷登出Map,并根據(jù)每條登出日志的key
* 去登入Map中找到對(duì)應(yīng)的登入日志,并
* 以一個(gè)LogRec實(shí)例保存該配對(duì)日志,然后
* 存入配對(duì)日志的集合中。并將該配對(duì)日志
* 中的登入日志從登入Map中刪除。這樣一來(lái)
* 登入Map中應(yīng)當(dāng)只剩下沒(méi)有配對(duì)的了。
* 5:將配對(duì)日志寫(xiě)入到logRecFile中
* 6:將所有未配對(duì)日志寫(xiě)入到loginLogFile中
* 7:將textLogFile文件刪除
* 8:返回true,表示配對(duì)完畢
*
*/
try {
//1
//1.1
if(logRecFile.exists()){
return true;
}
//1.2
if(!textLogFile.exists()){
System.out.println(textLogFile+"不存在!");
return false;
}
//2
List<LogData> list
= IOUtil.loadLogData(textLogFile);
//3
if(loginLogFile.exists()){
list.addAll(
IOUtil.loadLogData(loginLogFile)
);
}
//4
//4.1
List<LogRec> matches
= new ArrayList<LogRec>();
//4.2
Map<String,LogData> loginMap
= new HashMap<String,LogData>();
Map<String,LogData> logoutMap
= new HashMap<String,LogData>();
//4.3
for(LogData logData : list){
String key = logData.getUser()+","+
logData.getPid();
if(logData.getType()==LogData.TYPE_LOGIN){
loginMap.put(key, logData);
}else if(logData.getType()==LogData.TYPE_LOGOUT){
logoutMap.put(key, logData);
}
}
//4.4
Set<Entry<String,LogData>> entrySet
= logoutMap.entrySet();
for(Entry<String,LogData> e : entrySet){
LogData logout = e.getValue();
LogData login = loginMap.remove(e.getKey());
LogRec logRec = new LogRec(login,logout);
matches.add(logRec);
}
//5
IOUtil.saveCollection(matches, logRecFile);
//6
IOUtil.saveCollection(
loginMap.values(),loginLogFile
);
//7
textLogFile.delete();
//8
return true;
} catch (Exception e) {
System.out.println("配對(duì)日志失敗!");
e.printStackTrace();
}
return false;
}
/**
* 第一步:解析日志
* @return true:解析成功
* false:解析失敗
*/
private boolean parseLogs(){
/*
* 實(shí)現(xiàn)思路:
* 循環(huán)讀取batch條日志,然后將每條日志中的
* 5個(gè)信息解析出來(lái),最終組成一個(gè)字符串,以
* 行為單位,寫(xiě)入到textLogFile文件中
*
* 實(shí)現(xiàn)步驟:
* 1:必要的判斷工作
* 1.1:為了避免解析的日志還沒(méi)有被使用,而
* 第一步又重復(fù)執(zhí)行導(dǎo)致之前日志被覆蓋
* 的問(wèn)題,這里需要判斷,若保存解析后
* 的日志文件存在,則第一步不再執(zhí)行。
* 該日志文件會(huì)在第二步配對(duì)完畢后刪除。
* 1.2:logFile文件必須存在(wtmpx文件)
* 1.3:是否還有日志可以解析
* 2:創(chuàng)建RandomAccessFile來(lái)讀取logFile
* 3:將指針移動(dòng)到上次最后讀取的位置,準(zhǔn)備
* 開(kāi)始新的解析工作
* 4:解析工作
* 4.1:創(chuàng)建一個(gè)List集合,用于保存解析后
* 的每一條日志(LogData實(shí)例)
* 4.2:循環(huán)batch次,解析每條日志中的
* 5項(xiàng)內(nèi)容(user,pid,type,time,host)
* 并用一個(gè)LogData實(shí)例保存,然后將
* 該LogData實(shí)例存入集合
* 5:將集合中的所有的日志以行為單位保存到
* textLogFile中
* 6:保存書(shū)簽信息
* 7:返回true,表示工作完畢
*
*/
RandomAccessFile raf = null;
try {
//1
//1.1
if(textLogFile.exists()){
return true;
}
//1.2
if(!logFile.exists()){
System.out.println(logFile+"不存在!");
return false;
}
//1.3
long lastPosition = hasLogs();
//打樁
// System.out.println(
// "lastPosition:"+lastPosition
// );
if(lastPosition<0){
System.out.println("沒(méi)有日志可以解析了!");
return false;
}
//2
raf = new RandomAccessFile(logFile,"r");
//3
raf.seek(lastPosition);
//4
List<LogData> list
= new ArrayList<LogData>();
for(int i=0;i<batch;i++){
//每次解析前都判斷是否還有日志可以解析
if(logFile.length()-lastPosition
<LogData.LOG_LENGTH
){
break;
}
//解析user
raf.seek(lastPosition+LogData.USER_OFFSET);
String user
= IOUtil.readString(
raf, LogData.USER_LENGTH
).trim();
//解析PID
raf.seek(lastPosition+LogData.PID_OFFSET);
int pid = raf.readInt();
//解析TYPE
raf.seek(lastPosition+LogData.TYPE_OFFSET);
short type = raf.readShort();
//解析TIME
raf.seek(lastPosition+LogData.TIME_OFFSET);
int time = raf.readInt();
//解析HOST
raf.seek(lastPosition+LogData.HOST_OFFSET);
String host
= IOUtil.readString(
raf, LogData.HOST_LENGTH
).trim();
LogData log = new LogData(user, pid, type, time, host);
list.add(log);
//打樁
// System.out.println(log);
//當(dāng)解析完一條日志后,更新lastPosition
lastPosition = raf.getFilePointer();
}
//5
IOUtil.saveCollection(list, textLogFile);
//6 保存書(shū)簽文件
IOUtil.saveLong(
lastPosition, lastPositionFile);
//7
return true;
} catch (Exception e) {
System.out.println("解析日志失敗!");
e.printStackTrace();
} finally{
if(raf != null){
try {
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 第一步解析日志中的一個(gè)環(huán)節(jié),
* 根據(jù)書(shū)簽文件記錄的位置判斷是否還有
* 日志可以解析,若有,則將上次最后的位置
* 返回,若沒(méi)有則返回-1。
* @return
*/
private long hasLogs(){
try {
/*
* 若lastPositionFile不存在,則說(shuō)明
* 從來(lái)沒(méi)有解析過(guò),那么從頭開(kāi)始解析即可
*/
if(!lastPositionFile.exists()){
return 0;
}
long lastPosition
= IOUtil.readLong(lastPositionFile);
if(logFile.length()-lastPosition
>=LogData.LOG_LENGTH){
return lastPosition;
}
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
public static void main(String[] args) {
try {
DMSClient client = new DMSClient();
client.start();
} catch (Exception e) {
System.out.println("客戶端運(yùn)行失敗!");
}
}
}
3. IOUtil.java
package com.dms;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.dms.bo.LogData;
/**
* 該類(lèi)是一個(gè)工具類(lèi),負(fù)責(zé)客戶端的IO操作
* @author Administrator
*
*/
public class IOUtil {
/**
* 從給定的文件中讀取每一行字符串(配對(duì)日志)
* 并存入一個(gè)集合后返回
* @param file
* @return
* @throws Exception
*/
public static List<String> loadLogRec(File file) throws Exception{
BufferedReader br = null;
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(
file
)
)
);
List<String> list
= new ArrayList<String>();
String line = null;
while((line = br.readLine())!=null){
list.add(line);
}
return list;
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally{
if(br != null){
br.close();
}
}
}
/**
* 從給定的文件中讀取每一條配對(duì)日志,并存入
* 一個(gè)集合中然后返回。
* @param file
* @return
* @throws Exception
*/
public static List<LogData> loadLogData(File file) throws Exception{
BufferedReader br = null;
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(
file
)
)
);
List<LogData> list = new ArrayList<LogData>();
String line = null;
while((line = br.readLine())!=null){
LogData logData = new LogData(line);
list.add(logData);
}
return list;
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally{
if(br!=null){
br.close();
}
}
}
/**
* 將指定的long值以字符串的形式寫(xiě)入到
* 給定文件的第一行
* @param l
* @param file
* @throws Exception
*/
public static void saveLong(
long lon,File file) throws Exception{
PrintWriter pw = null;
try {
pw = new PrintWriter(file);
pw.println(lon);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally{
if(pw != null){
pw.close();
}
}
}
/**
* 將集合中每個(gè)元素的toString方法返回的字符串
* 以行為單位寫(xiě)入到指定文件中。
* @param c
* @param file
* @throws Exception
*/
public static void saveCollection(
Collection c,File file) throws Exception{
PrintWriter pw = null;
try {
pw = new PrintWriter(file);
for(Object o : c){
pw.println(o);
}
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally{
if(pw != null){
pw.close();
}
}
}
/**
* 從給定的RandomAccessFile當(dāng)前位置開(kāi)始連續(xù)
* 讀取length個(gè)字節(jié),并轉(zhuǎn)換為字符串后返回
* @param raf
* @param length
* @return
* @throws Exception
*/
public static String readString(
RandomAccessFile raf,int length) throws Exception{
try {
byte[] data = new byte[length];
raf.read(data);
return new String(data,"ISO8859-1");
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* 從給定文件中讀取第一行字符串,然后將其
* 轉(zhuǎn)換為一個(gè)long值后返回
* @param file
* @return
* @throws Exception
*/
public static long readLong(File file) throws Exception{
BufferedReader br = null;
try {
br = new BufferedReader(
new InputStreamReader(
new FileInputStream(
file
)
)
);
String line = br.readLine();
return Long.parseLong(line);
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally{
if(br != null){
br.close();
}
}
}
}
4. config.xml
<?xml version="1.0" encoding="UTF-8"?> <config> <!-- unix系統(tǒng)日志文件名 --> <logfile>wtmpx</logfile> <!-- 保存解析后日志的文件名 --> <textlogfile>log.txt</textlogfile> <!-- 書(shū)簽文件名 --> <lastpositionfile>last-position.txt</lastpositionfile> <!-- 每次解析日志的條目數(shù) --> <batch>10</batch> <!-- 配對(duì)日志文件名 --> <logrecfile>logrec.txt</logrecfile> <!-- 未配對(duì)日志文件名 --> <loginlogfile>login.txt</loginlogfile> <!-- 服務(wù)端地址 --> <serverhost>localhost</serverhost> <!-- 服務(wù)端端口 --> <serverport>8088</serverport> </config>
5. server-config.xml
<?xml version="1.0" encoding="UTF-8"?> <config> <!-- 服務(wù)端保存配對(duì)日志文件的文件名 --> <logrecfile>server-logs.txt</logrecfile> <!-- 線程池線程數(shù)量 --> <threadsum>30</threadsum> <!-- 服務(wù)端端口 --> <serverport>8088</serverport> </config>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。
相關(guān)文章
SpringCloud集成Eureka并實(shí)現(xiàn)負(fù)載均衡的過(guò)程詳解
這篇文章主要給大家詳細(xì)介紹了SpringCloud集成Eureka并實(shí)現(xiàn)負(fù)載均衡的過(guò)程,文章通過(guò)代碼示例和圖文講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下2023-11-11
Java讀取properties文件之中文亂碼問(wèn)題及解決
這篇文章主要介紹了Java讀取properties文件之中文亂碼問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Java實(shí)現(xiàn)經(jīng)典游戲泡泡堂的示例代碼
這篇文章將利用Java制作經(jīng)典游戲——泡泡堂,游戲設(shè)計(jì)為雙人pk積分賽模式,在這個(gè)模式里面,玩家只要率先達(dá)到一定分?jǐn)?shù)既可以贏得比賽。感興趣的可以了解一下2022-04-04
SpringMVC攔截器創(chuàng)建配置及執(zhí)行順序
這篇文章主要為大家介紹了SpringMVC攔截器創(chuàng)建配置及執(zhí)行順序,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Spring Boot thymeleaf模板引擎的使用詳解
這篇文章主要介紹了Spring Boot thymeleaf模板引擎的使用詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

