读取用户登入出日志并上传服务端

下面是编程之家 jb51.cc 通过网络收集整理的代码片段。

编程之家小编现在分享给大家,也给大家做个参考。

该客户端运行在给用户提供unix服务的服务器上。用来读取并收集该服务器上用户的上下线信息,并进行配对整理后发送给服务端汇总。
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();
				}
			}
		}
	}
}





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;
		}
	}
	/**
	 * 构造方法初始化第二步,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,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,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("客户端运行失败!");
		}
	}
}








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();
			}
		}
	}
}







<?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>








<?xml version="1.0" encoding="UTF-8"?>
<config>
	<!-- 服务端保存配对日志文件的文件名 -->
	<logrecfile>server-logs.txt</logrecfile>
	<!-- 线程池线程数量 -->
	<threadsum>30</threadsum>
	<!-- 服务端端口 -->
	<serverport>8088</serverport>
</config>








以上是编程之家(jb51.cc)为你收集整理的全部代码内容,希望文章能够帮你解决所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 连接 连接池产生原因 连接池实现原理 小结 TEMPERANCE:Eat not to dullness;drink not to elevation.节制
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 一个优秀的工程师和一个普通的工程师的区别,不是满天飞的架构图,他的功底体现在所写的每一行代码上。-- 毕玄 1. 命名风格 【书摘】类名用 UpperCamelC
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个人在用”。哪怕只是throw了一个新的Exception。哈哈,这是我犯的错误。一、接口和抽象类类,即一个对象。先抽象类,就是抽象出类的基础部分,即抽象基类(抽象类)。官方定义让人费解,但是记忆方法是也不错的 —包含抽象方法的类叫做抽象类。接口
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket一、引子文件,作为常见的数据源。关于操作文件的字节流就是 —FileInputStream&amp;FileOutputStream。
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节。交流QQ群:【编程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_Aonqz
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object)。用来干什么?Java 线程(也称 JVM 线程)是 Java 进程内允许多个同时进行的任务。该进程内并发的任务成为线程(Thread),一个进程里至少一个线程。 Ja
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket在面向对象编程中,编程人员应该在意“资源”。比如?1String hello = &quot;hello&quot;; 在代码中,我们
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 这是泥瓦匠的第103篇原创 《程序兵法:Java String 源码的排序算法(一)》 文章工程:* JDK 1.8* 工程名:algorithm-core-le
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 目录 一、父子类变量名相同会咋样? 有个小故事,今天群里面有个人问下面如图输出什么? 我回答:60。但这是错的,答案结果是 40 。我知错能改,然后说了下父子类变
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统挺适合开发者进行写代码,最近碰到了一个问题,问题是如何在 macOS 根目录创建文件夹。不同的 ma
作者:李强强上一篇,泥瓦匠基础地讲了下Java I/O : Bit Operation 位运算。这一讲,泥瓦匠带你走进Java中的进制详解。一、引子在Java世界里,99%的工作都是处理这高层。那么二进制,字节码这些会在哪里用到呢?自问自答:在跨平台的时候,就凸显神功了。比如说文件读写,数据通信,还
1 线程中断 1.1 什么是线程中断? 线程中断是线程的标志位属性。而不是真正终止线程,和线程的状态无关。线程中断过程表示一个运行中的线程,通过其他线程调用了该线程的 方法,使得该线程中断标志位属性改变。 深入思考下,线程中断不是去中断了线程,恰恰是用来通知该线程应该被中断了。具体是一个标志位属性,
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want需求 项目在设计表的时候,要处理并发多的一些数据,类似订单号不能重复,要保持唯一。原本以为来个时间戳,精确到毫秒应该不错了。后来觉得是错了,测试环境下很多一
纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 纯技术交流群 每日推荐 - 技术干货推送 跟着泥瓦匠,一起问答交流 扫一扫,我邀请你入群 加微信:bysocket01
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocketReprint it anywhere u want.文章Points:1、介绍RESTful架构风格2、Spring配置CXF3、三层初设计,实现WebService接口层4、撰写HTTPClient 客户
Writer :BYSocket(泥沙砖瓦浆木匠)什么是回调?今天傻傻地截了张图问了下,然后被陈大牛回答道“就一个回调…”。此时千万个草泥马飞奔而过(逃哈哈,看着源码,享受着这种回调在代码上的作用,真是美哉。不妨总结总结。一、什么是回调回调,回调。要先有调用,才有调用者和被调用者之间的回调。所以在百
Writer :BYSocket(泥沙砖瓦浆木匠)一、什么大小端?大小端在计算机业界,Endian表示数据在存储器中的存放顺序。百度百科如下叙述之:大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加
What is a programming language? Before introducing compilation and decompilation, let&#39;s briefly introduce the Programming Language. Programming la
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:BYSocketFaceBook:BYSocketTwitter :BYSocket泥瓦匠喜欢Java,文章总是扯扯Java。 I/O 基础,就是二进制,也就是Bit。一、Bit与二进制什么是Bit(位)呢?位是CPU
Writer:BYSocket(泥沙砖瓦浆木匠)微博:BYSocket豆瓣:BYSocket一、前言 泥瓦匠最近被项目搞的天昏地暗。发现有些要给自己一些目标,关于技术的目标:专注很重要。专注Java 基础 + H5(学习) 其他操作系统,算法,数据结构当成课外书博览。有时候,就是那样你越是专注方面越