java讀取用戶登入加入日記信息上傳辦事端。本站提示廣大學習愛好者:(java讀取用戶登入加入日記信息上傳辦事端)文章只能為提供參考,不一定能成為您想要的結果。以下是java讀取用戶登入加入日記信息上傳辦事端正文
本文實例為年夜家分享了讀取用戶登入出日記並上傳辦事真個詳細完成代碼,供年夜家參考,詳細內容以下
該客戶端運轉在給用戶供給unix辦事的辦事器上。用來讀取並搜集該辦事器上用戶的高低線信息,並停止配對整頓後發送給辦事端匯總。
詳細完成代碼:
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辦事端,用來吸收每一個客戶端發送過去的
* 配對日記並保留在當地文件中
* @author Administrator
*
*/
public class DMSServer {
//屬性界說
//用來吸收客戶端銜接的辦事真個ServerSocket
private ServerSocket server;
//用來治理處置客戶端要求的線程的線程池
private ExecutorService threadPool;
//保留一切客戶端發送過去配對日記的文件
private File serverLogFile;
//新聞隊列
private BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
public DMSServer() throws Exception{
try {
System.out.println("辦事正直在初始化...");
//1 解析設置裝備擺設文件server-config.xml
Map<String,String> config = loadConfig();
//2 依據設置裝備擺設文件內容初始化屬性
init(config);
System.out.println("辦事端初始化終了...");
} catch (Exception e) {
System.out.println("初始化辦事端掉敗!");
throw e;
}
}
/**
* 結構辦法初始化第一步,解析設置裝備擺設文件
* @return 前往的Map中保留的是設置裝備擺設文件中的
* 每條內容,個中key:標簽的名字,
* value為標簽中央的文本
* @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>標簽中的一切子標簽
* 並將每個子標簽的名字作為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;
}
}
/**
* 結構辦法初始化第二步,依據設置裝備擺設項初始化屬性
* @param config
* @throws Exception
*/
private void init(Map<String,String> config) throws Exception{
/*
* 用設置裝備擺設文件中的<logrecfile>初始化屬性:serverLogFile
* 用設置裝備擺設文件中的<threadsum>初始化屬性:threadPool,這裡創立固定年夜小線程池。該值作為線程池線程數目
* 用設置裝備擺設文件中的<serverport>初始化屬性:server,這裡這個值為ServerSocket的辦事端口
*/
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"))
);
}
/**
* 辦事端開端任務的辦法
* @throws Exception
*/
public void start() throws Exception{
/*
* 完成請求:
* 起首零丁啟動一個線程,用來運轉SaveLogHandler
* 這個義務,目標是保留一切配對日記
* 然後開端輪回監聽辦事端端口,一旦一個客戶端銜接了,
* 就實例化一個ClientHander,然後將該義務交給線程池
* 使其分派線程來處置與該客戶真個交互。
*
*/
try {
System.out.println("辦事端開端任務...");
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("啟動辦事端掉敗!");
}
}
/**
* 該線程擔任從新聞隊列中掏出每條配對日記,
* 並存入到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();
}
}
}
}
/**
* 處置一個指定客戶端要求
* @author Administrator
*
*/
private class ClientHandler implements Runnable{
private Socket socket;
public ClientHandler(Socket socket){
this.socket = socket;
}
public void run(){
/*
* 思緒:
* 起首吸收客戶端發送過去的一切配對日記,
* 直到讀取到"OVER"為止,然後將這些配對
* 日記保留到當地的文件中,並答復客戶端
* "OK"
* 履行步調:
* 1:經由過程Socket創立輸入流,用來給客戶端
* 發送呼應
* 2:經由過程Socket創立輸出流,讀取客戶端發送
* 過去的日記
* 3:輪回讀取客戶端發送過去的每行字符串,並
* 先斷定能否為字符串"OVER",若不是,則是
* 一條配對日記,那末保留到當地文件,若是,
* 則停滯讀取。
* 4:勝利讀取一切日記後答復客戶端"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;
}
//將該日記寫入文件保留
messageQueue.offer(message);
}
//4
pw.println("OK");
pw.flush();
} catch (Exception e) {
e.printStackTrace();
pw.println("ERROR");
pw.flush();
} finally{
try {
//與客戶端斷開銜接釋放資本
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;
/**
* 該客戶端運轉在給用戶供給unix辦事的辦事器上。
* 用來讀取並搜集該辦事器上用戶的高低線信息,並
* 停止配對整頓後發送給辦事端匯總。
* @author Administrator
*
*/
public class DMSClient {
//屬性界說
//第一步:解析日記所需屬性
//unix體系日記文件
private File logFile;
//保留解析後日記的文件
private File textLogFile;
//書簽文件
private File lastPositionFile;
//每次解析日記的條目數
private int batch;
//第二步:配對日記所須要屬性
//保留配對日記的文件
private File logRecFile;
//保留未配對日記的文件
private File loginLogFile;
//第三步:發送日記所須要屬性
//辦事端地址
private String serverHost;
//辦事端端口
private int serverPort;
/**
* 結構辦法,用來初始化客戶端
* @throws Exception
*/
public DMSClient() throws Exception{
try {
//1 解析設置裝備擺設文件config.xml
Map<String,String> config = loadConfig();
//打樁
System.out.println(config);
//2 依據設置裝備擺設文件內容初始化屬性
init(config);
} catch (Exception e) {
System.out.println("初始化掉敗!");
throw e;
}
}
/**
* 結構辦法初始化第二步,依據設置裝備擺設項初始化屬性
* @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;
}
}
/**
* 結構辦法初始化第一步,解析設置裝備擺設文件
* @return 前往的Map中保留的是設置裝備擺設文件中的
* 每條內容,個中key:標簽的名字,
* value為標簽中央的文本
* @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>標簽中的一切子標簽
* 並將每個子標簽的名字作為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;
}
}
/**
* 客戶端開端任務的辦法
* 輪回履行三步:
* 1:解析日記
* 2:配對日記
* 3:發送日記
*/
public void start(){
parseLogs();
matchLogs();
sendLogs();
// while(true){
// //解析日記
// if(!parseLogs()){
// continue;
// }
// //配對日記
// if(!matchLogs()){
// continue;
// }
// //發送日記
// sendLogs();
// }
}
/**
* 第三步:發送日記
* @return true:發送勝利
* false:發送掉敗
*/
private boolean sendLogs(){
/*
* 完成思緒:
* 將logRecFile文件中的一切配對日記讀取
* 出來然後銜接上辦事端並發送曩昔,若辦事端
* 全體吸收,便可以將該文件刪除,表現發送
* 終了了。
* 完成步調:
* 1:logRecFile文件必需存在
* 2:將一切配對日記讀掏出來並存入一個聚集
* 期待發送
* 3:經由過程Socket銜接辦事端
* 4:創立輸入流
* 5:次序將一切配對日記按行發送給辦事端
* 6:零丁發送一個字符串"OVER"表現一切日記
* 均已發送終了
* 7:創立輸出流
* 8:讀取辦事端發送回來的呼應字符串
* 9:若呼應的字符串為"OK",表現辦事正直常
* 吸收了一切日記,這時候便可以將logRecFile
* 文件刪除並前往true表現發送終了。
*
*/
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("發送日記掉敗!");
return false;
}
} catch (Exception e) {
System.out.println("發送日記掉敗!");
e.printStackTrace();
} finally{
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 第二步:配對日記
* @return true:配對勝利
* false:配對掉敗
*/
private boolean matchLogs(){
/*
* 完成思緒:
* 將第一步解析的新日記,與前次為配對勝利
* 的登入日記全體讀掏出來,然後再依照user,
* pid雷同,type一個是7,一個是8停止配對。
* 只需能找到類型為8的,必定可以找到一個
* 能與之配對的登入日記。
*
* 完成步調:
* 1:需要的斷定
* 1.1:logRecFile能否存在,存在則不再
* 停止新的配對任務,防止籠罩。
* 1.2:textLogFile文件必需存在。
* 2:讀取textLogFile將日記讀掏出來,並
* 存入到聚集中。(若干LogData實例)
* 3:若loginLogFile文件若存在,則解釋
* 有前次未配對勝利的日記,也將其讀取
* 出來存入聚集期待一路配對
* 4:配對任務
* 4.1:創立一個聚集,用於保留一切配對日記
* 4.2:創立兩個Map分離保留登入日記與登出日記
* 4.3:遍歷一切待配對的日記,依照登入與登出
* 分離存入兩個Map中,
* 個中key:user,pid
* value:LogData實例
* 4.4:遍歷登出Map,並依據每條登出日記的key
* 去登入Map中找到對應的登入日記,並
* 以一個LogRec實例保留該配對日記,然後
* 存入配對日記的聚集中。並將該配對日記
* 中的登入日記從登入Map中刪除。如許一來
* 登入Map中應該只剩下沒有配對的了。
* 5:將配對日記寫入到logRecFile中
* 6:將一切未配對日記寫入到loginLogFile中
* 7:將textLogFile文件刪除
* 8:前往true,表現配對終了
*
*/
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("配對日記掉敗!");
e.printStackTrace();
}
return false;
}
/**
* 第一步:解析日記
* @return true:解析勝利
* false:解析掉敗
*/
private boolean parseLogs(){
/*
* 完成思緒:
* 輪回讀取batch條日記,然後將每條日記中的
* 5個信息解析出來,終究構成一個字符串,以
* 行動單元,寫入到textLogFile文件中
*
* 完成步調:
* 1:需要的斷定任務
* 1.1:為了不解析的日記還沒有被應用,而
* 第一步又反復履行招致之前日記被籠罩
* 的成績,這裡須要斷定,若保留解析後
* 的日記文件存在,則第一步不再履行。
* 該日記文件會在第二步配對終了後刪除。
* 1.2:logFile文件必需存在(wtmpx文件)
* 1.3:能否還有日記可以解析
* 2:創立RandomAccessFile來讀取logFile
* 3:將指針挪動到前次最初讀取的地位,預備
* 開端新的解析任務
* 4:解析任務
* 4.1:創立一個List聚集,用於保留解析後
* 的每條日記(LogData實例)
* 4.2:輪回batch次,解析每條日記中的
* 5項內容(user,pid,type,time,host)
* 並用一個LogData實例保留,然後將
* 該LogData實例存入聚集
* 5:將聚集中的一切的日記以行動單元保留到
* textLogFile中
* 6:保留書簽信息
* 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("沒有日記可以解析了!");
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);
//當解析完一條日記後,更新lastPosition
lastPosition = raf.getFilePointer();
}
//5
IOUtil.saveCollection(list, textLogFile);
//6 保留書簽文件
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;
}
/**
* 第一步解析日記中的一個環節,
* 依據書簽文件記載的地位斷定能否還有
* 日記可以解析,如有,則將前次最初的地位
* 前往,若沒有則前往-1。
* @return
*/
private long hasLogs(){
try {
/*
* 若lastPositionFile不存在,則解釋
* 歷來沒有解析過,那末從頭開端解析便可
*/
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("客戶端運轉掉敗!");
}
}
}
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;
/**
* 該類是一個對象類,擔任客戶真個IO操作
* @author Administrator
*
*/
public class IOUtil {
/**
* 從給定的文件中讀取每行字符串(配對日記)
* 並存入一個聚集後前往
* @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();
}
}
}
/**
* 從給定的文件中讀取每條配對日記,並存入
* 一個聚集中然後前往。
* @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值以字符串的情勢寫入到
* 給定文件的第一行
* @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();
}
}
}
/**
* 將聚集中每一個元素的toString辦法前往的字符串
* 以行動單元寫入到指定文件中。
* @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以後地位開端持續
* 讀取length個字節,並轉換為字符串後前往
* @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;
}
}
/**
* 從給定文件中讀取第一行字符串,然後將其
* 轉換為一個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體系日記文件名 --> <logfile>wtmpx</logfile> <!-- 保留解析後日記的文件名 --> <textlogfile>log.txt</textlogfile> <!-- 書簽文件名 --> <lastpositionfile>last-position.txt</lastpositionfile> <!-- 每次解析日記的條目數 --> <batch>10</batch> <!-- 配對日記文件名 --> <logrecfile>logrec.txt</logrecfile> <!-- 未配對日記文件名 --> <loginlogfile>login.txt</loginlogfile> <!-- 辦事端地址 --> <serverhost>localhost</serverhost> <!-- 辦事端端口 --> <serverport>8088</serverport> </config>
5. server-config.xml
<?xml version="1.0" encoding="UTF-8"?> <config> <!-- 辦事端保留配對日記文件的文件名 --> <logrecfile>server-logs.txt</logrecfile> <!-- 線程池線程數目 --> <threadsum>30</threadsum> <!-- 辦事端端口 --> <serverport>8088</serverport> </config>
以上就是本文的全體內容,願望對年夜家的進修有所贊助。