init
This commit is contained in:
26
day02/src/Demo.java
Normal file
26
day02/src/Demo.java
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
循环的嵌套:外层循环执行一次,内层循环要执行一轮
|
||||
*/
|
||||
public class Demo{
|
||||
public static void main(String[] args){
|
||||
//使用循环的嵌套,实现时钟的效果(一天有0~23小时,每小时有0~59分)
|
||||
for(int h = 0;h<24;h++){
|
||||
//System.out.println(h+"点");
|
||||
for(int m = 0;m<60;m++){
|
||||
System.out.println(h+"点"+m+"分");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void test1(String[] args){
|
||||
//打印出一个5行5列的矩形的*
|
||||
for(int i = 1;i<=5;i++){
|
||||
for(int j = 1;j<=5;j++){
|
||||
System.out.print("*");
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
27
day02/src/com/inmind/student/test1/Server4.java
Normal file
27
day02/src/com/inmind/student/test1/Server4.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.inmind.student.test1;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
public class Server4 {
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
ServerSocket serverSocket = new ServerSocket(8002);
|
||||
Socket socket = serverSocket.accept();
|
||||
DataInputStream dis = new DataInputStream(socket.getInputStream());
|
||||
FileOutputStream fos = new FileOutputStream("D:\\io_test\\upload\\1.jpg");
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = dis.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
fos.close();
|
||||
dis.close();
|
||||
socket.close();
|
||||
serverSocket.close();
|
||||
System.out.println("上传成功");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
35
day02/src/com/inmind/student/test1/Test9.java
Normal file
35
day02/src/com/inmind/student/test1/Test9.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.inmind.student.test1;
|
||||
|
||||
/*
|
||||
练习三:上传图片文件
|
||||
客户端需求:把一个图片文件发送到服务端并读取回馈信息。要求判断文件是否存在及格式是否为jpg并要求文件小于2M。
|
||||
服务端需求:接收客户端发送过来的图片数据。进行存储后,回馈一个“上传成功”字样。支持多用户的并发访问。
|
||||
|
||||
*/
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
public class Test9 {
|
||||
public static void main(String[] args) throws IOException {
|
||||
Socket socket = new Socket("192.168.23.34", 8002);
|
||||
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
|
||||
FileInputStream fis = new FileInputStream("aa.jpg");
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
/* if (!"png".equals("jpg")) {
|
||||
System.out.println("文件格式错误");
|
||||
break;
|
||||
}
|
||||
if (fis.available() > 2 * 1024 * 1024) {
|
||||
System.out.println("文件大小错误");
|
||||
break;
|
||||
}*/
|
||||
dos.write(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
fis.close();
|
||||
dos.close();
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
34
day02/src/com/inmind/student/吕征洋/Log.java
Normal file
34
day02/src/com/inmind/student/吕征洋/Log.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.inmind.student.吕征洋;
|
||||
import java.io.Serializable;
|
||||
public class Log implements Serializable, Comparable<Log> {
|
||||
private final long timestamp;
|
||||
private final String level;
|
||||
private final String module;
|
||||
private final String content;
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + timestamp + "] " + level + " " + module + ": " + content;
|
||||
}
|
||||
@Override
|
||||
public int compareTo(Log other) {
|
||||
return Long.compare(this.timestamp, other.timestamp);
|
||||
}
|
||||
}
|
||||
139
day02/src/com/inmind/student/吕征洋/LogAnalyzerClient.java
Normal file
139
day02/src/com/inmind/student/吕征洋/LogAnalyzerClient.java
Normal file
@@ -0,0 +1,139 @@
|
||||
package com.inmind.student.吕征洋;
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.*;
|
||||
import java.util.stream.Collectors;
|
||||
public class LogAnalyzerClient {
|
||||
private static final String LOG_DIR = "D:\\io_test\\";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
private final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzerClient analyzer = new LogAnalyzerClient();
|
||||
analyzer.startAnalysis();
|
||||
}
|
||||
public void startAnalysis() {
|
||||
List<Path> logFiles = findLogFiles();
|
||||
System.out.println("找到 " + logFiles.size() + " 个日志文件,开始解析...");
|
||||
parseLogFiles(logFiles);
|
||||
System.out.println("日志解析完成,共解析 " + logs.size() + " 条日志");
|
||||
Map<String, Long> levelStats = analyzeByLevel();
|
||||
Map<String, Long> moduleErrorStats = analyzeModuleErrors();
|
||||
List<Log> earliestLogs = findEarliestLogs(3);
|
||||
reportToServer(levelStats, moduleErrorStats, earliestLogs);
|
||||
}
|
||||
private List<Path> findLogFiles() {
|
||||
try {
|
||||
try (Stream<Path> paths = Files.list(Paths.get(LOG_DIR))) {
|
||||
return paths
|
||||
.filter(Files::isRegularFile)
|
||||
.filter(path -> path.toString().endsWith(".log"))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取日志目录失败: " + e.getMessage());
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
private void parseLogFiles(List<Path> logFiles) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (Path file : logFiles) {
|
||||
futures.add(executor.submit(() -> parseSingleFile(file)));
|
||||
}
|
||||
for (Future<?> future : futures) {
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
System.err.println("文件解析异常: " + e.getCause().getMessage());
|
||||
}
|
||||
}
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
private void parseSingleFile(Path file) {
|
||||
int lineCount = 0;
|
||||
try (BufferedReader reader = Files.newBufferedReader(file)) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
Log log = parseLogLine(line);
|
||||
logs.add(log);
|
||||
lineCount++;
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("日志解析失败: " + line + " - " + e.getMessage());
|
||||
}
|
||||
}
|
||||
System.out.println("解析完成:" + file.getFileName() + ",共 " + lineCount + " 行");
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件失败: " + file + " - " + e.getMessage());
|
||||
}
|
||||
}
|
||||
private Log parseLogLine(String line) {
|
||||
String[] parts = line.split(",", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException("日志格式错误: " + line);
|
||||
}
|
||||
try {
|
||||
long timestamp = Long.parseLong(parts[0].trim());
|
||||
String level = parts[1].trim();
|
||||
String module = parts[2].trim();
|
||||
String content = parts[3].trim();
|
||||
|
||||
return new Log(timestamp, level, module, content);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("时间戳格式错误: " + parts[0]);
|
||||
}
|
||||
}
|
||||
private Map<String, Long> analyzeByLevel() {
|
||||
return logs.parallelStream()
|
||||
.collect(Collectors.groupingBy(
|
||||
Log::getLevel,
|
||||
Collectors.counting()
|
||||
));
|
||||
}
|
||||
private Map<String, Long> analyzeModuleErrors() {
|
||||
return logs.parallelStream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(
|
||||
Log::getModule,
|
||||
Collectors.counting()
|
||||
));
|
||||
}
|
||||
private List<Log> findEarliestLogs(int count) {
|
||||
return logs.parallelStream()
|
||||
.sorted()
|
||||
.limit(count)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
private void reportToServer(Map<String, Long> levelStats,
|
||||
Map<String, Long> moduleErrorStats,
|
||||
List<Log> earliestLogs) {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
|
||||
oos.writeObject(levelStats);
|
||||
oos.writeObject(moduleErrorStats);
|
||||
oos.writeObject(earliestLogs);
|
||||
oos.flush();
|
||||
String response = (String) ois.readObject();
|
||||
System.out.println("服务器响应:" + response);
|
||||
System.out.println("日志分析和上报完成");
|
||||
} catch (ConnectException e) {
|
||||
System.err.println("无法连接到服务器: " + e.getMessage());
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.err.println("网络通信错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
46
day02/src/com/inmind/student/吕征洋/LogServer.java
Normal file
46
day02/src/com/inmind/student/吕征洋/LogServer.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.inmind.student.吕征洋;
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
public class LogServer {
|
||||
private static final int PORT = 8080;
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||
System.out.println("日志服务器已启动,监听端口:" + PORT);
|
||||
while (true) {
|
||||
try (Socket clientSocket = serverSocket.accept();
|
||||
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream())) {
|
||||
System.out.println("\n客户端连接成功:" + clientSocket.getInetAddress());
|
||||
Map<String, Long> levelStats = (Map<String, Long>) ois.readObject();
|
||||
Map<String, Long> moduleErrorStats = (Map<String, Long>) ois.readObject();
|
||||
List<Log> earliestLogs = (List<Log>) ois.readObject();
|
||||
printStats(levelStats, moduleErrorStats, earliestLogs);
|
||||
oos.writeObject("上报成功");
|
||||
System.out.println("结果已返回客户端");
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("数据格式错误: " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
System.err.println("客户端连接异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
private static void printStats(Map<String, Long> levelStats,
|
||||
Map<String, Long> moduleErrorStats,
|
||||
List<Log> earliestLogs) {
|
||||
System.out.println("\n===== 日志统计结果 =====");
|
||||
System.out.println("\n1. 按级别统计:");
|
||||
levelStats.forEach((level, count) ->
|
||||
System.out.println(level + ": " + count + "条"));
|
||||
System.out.println("\n2. 按模块错误统计:");
|
||||
moduleErrorStats.forEach((module, count) ->
|
||||
System.out.println(module + ": " + count + "条错误"));
|
||||
System.out.println("\n3. 最早的3条日志:");
|
||||
earliestLogs.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
24
day02/src/com/inmind/student/宣智荣/Log.java
Normal file
24
day02/src/com/inmind/student/宣智荣/Log.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.inmind.student.宣智荣;
|
||||
|
||||
import java.io.Serializable; //
|
||||
|
||||
public class Log implements Serializable { // 实现序列化接口
|
||||
private long timestamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
// 构造方法和 getter 不变
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
// getter 方法...
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
}
|
||||
152
day02/src/com/inmind/student/宣智荣/LogClient.java
Normal file
152
day02/src/com/inmind/student/宣智荣/LogClient.java
Normal file
@@ -0,0 +1,152 @@
|
||||
package com.inmind.student.宣智荣;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogClient {
|
||||
// 日志文件目录
|
||||
private static final String LOG_DIR = "D:\\io_test";
|
||||
// 服务器地址与端口
|
||||
private static final String SERVER_HOST = "127.0.0.1";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
|
||||
// 存储所有解析后的日志(线程安全的 List)
|
||||
private static final List<Log> logList = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 1. 获取所有 .log 文件
|
||||
File[] logFiles = getLogFiles();
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.err.println("未找到日志文件");
|
||||
return;
|
||||
}
|
||||
System.out.println("找到 " + logFiles.length + " 个日志文件,开始解析...");
|
||||
|
||||
// 2. 线程池并发解析文件
|
||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
for (File file : logFiles) {
|
||||
executor.submit(() -> parseLogFile(file));
|
||||
}
|
||||
// 关闭线程池(不再接受新任务,等待现有任务完成)
|
||||
executor.shutdown();
|
||||
// 等待所有任务完成
|
||||
while (!executor.isTerminated()) {
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
System.out.println("日志解析完成,共解析 " + logList.size() + " 条日志");
|
||||
|
||||
// 3. 统计分析(Stream + Lambda)
|
||||
Map<String, Long> levelCount = analyzeLevelCount();
|
||||
Map<String, Long> errorModuleCount = analyzeErrorModuleCount();
|
||||
List<Log> earliestLogs = findEarliestLogs(3);
|
||||
|
||||
// 4. 网络上报
|
||||
try {
|
||||
sendToServer(levelCount, errorModuleCount, earliestLogs);
|
||||
System.out.println("日志分析和上报完成");
|
||||
} catch (IOException e) {
|
||||
System.err.println("网络上报失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取目录下所有 .log 文件
|
||||
private static File[] getLogFiles() {
|
||||
File dir = new File(LOG_DIR);
|
||||
if (!dir.exists() || !dir.isDirectory()) {
|
||||
System.err.println("日志目录不存在:" + LOG_DIR);
|
||||
return null;
|
||||
}
|
||||
return dir.listFiles((d, name) -> name.endsWith(".log"));
|
||||
}
|
||||
|
||||
// 解析单个日志文件
|
||||
private static void parseLogFile(File file) {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
// 日志格式正则:时间戳, 级别, 模块, 内容(内容可能包含逗号,简单处理)
|
||||
Pattern pattern = Pattern.compile("(\\d+),(\\w+),(\\w+),(.+)");
|
||||
while ((line = reader.readLine()) != null) {
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
try {
|
||||
long timestamp = Long.parseLong(matcher.group(1));
|
||||
String level = matcher.group(2);
|
||||
String module = matcher.group(3);
|
||||
String content = matcher.group(4);
|
||||
logList.add(new Log(timestamp, level, module, content));
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("解析日志失败(时间戳格式错误):" + line);
|
||||
}
|
||||
} else {
|
||||
System.err.println("解析日志失败(格式不匹配):" + line);
|
||||
}
|
||||
}
|
||||
System.out.println("解析完成:" + file.getName() + ",共 " + logList.size() + " 行");
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("文件未找到:" + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 按级别统计数量
|
||||
private static Map<String, Long> analyzeLevelCount() {
|
||||
return logList.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
}
|
||||
|
||||
// 按模块统计 ERROR 级别日志数量
|
||||
private static Map<String, Long> analyzeErrorModuleCount() {
|
||||
return logList.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
}
|
||||
|
||||
// 找出时间戳最早的 N 条日志
|
||||
private static List<Log> findEarliestLogs(int n) {
|
||||
return logList.stream()
|
||||
.sorted(Comparator.comparingLong(Log::getTimestamp))
|
||||
.limit(n)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 发送数据到服务器
|
||||
private static void sendToServer(Map<String, Long> levelCount,
|
||||
Map<String, Long> errorModuleCount,
|
||||
List<Log> earliestLogs) throws IOException {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
|
||||
|
||||
// 封装要发送的数据(简单用 Map 包含结果)
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("levelCount", levelCount);
|
||||
data.put("errorModuleCount", errorModuleCount);
|
||||
data.put("earliestLogs", earliestLogs);
|
||||
|
||||
oos.writeObject(data);
|
||||
oos.flush();
|
||||
|
||||
// 接收服务器响应:捕获 ClassNotFoundException
|
||||
try {
|
||||
String response = (String) ois.readObject();
|
||||
System.out.println("服务器响应:" + response);
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("反序列化失败!找不到对应类定义,异常信息:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
66
day02/src/com/inmind/student/宣智荣/LogServer.java
Normal file
66
day02/src/com/inmind/student/宣智荣/LogServer.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.inmind.student.宣智荣;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LogServer {
|
||||
private static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||
System.out.println("服务器启动,监听端口:" + PORT);
|
||||
while (true) {
|
||||
// 接受客户端连接
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
System.out.println("客户端连接成功:" + clientSocket.getInetAddress());
|
||||
|
||||
// 处理客户端数据(单独线程,支持多客户端)
|
||||
new Thread(() -> handleClient(clientSocket)).start();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleClient(Socket clientSocket) {
|
||||
try (ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream())) {
|
||||
|
||||
// 读取客户端发送的数据
|
||||
Map<String, Object> data = (Map<String, Object>) ois.readObject();
|
||||
Map<String, Long> levelCount = (Map<String, Long>) data.get("levelCount");
|
||||
Map<String, Long> errorModuleCount = (Map<String, Long>) data.get("errorModuleCount");
|
||||
List<Log> earliestLogs = (List<Log>) data.get("earliestLogs");
|
||||
|
||||
// 打印统计结果
|
||||
System.out.println("===== 日志统计结果 =====");
|
||||
System.out.println("1. 按级别统计:");
|
||||
levelCount.forEach((level, count) -> System.out.println(level + ": " + count + " 条"));
|
||||
|
||||
System.out.println("\n2. 按模块错误统计:");
|
||||
errorModuleCount.forEach((module, count) -> System.out.println(module + ": " + count + " 条错误"));
|
||||
|
||||
System.out.println("\n3. 最早的 " + earliestLogs.size() + " 条日志:");
|
||||
earliestLogs.forEach(log ->
|
||||
System.out.println("[" + log.getTimestamp() + "] " + log.getLevel() + " "
|
||||
+ log.getModule() + ": " + log.getContent())
|
||||
);
|
||||
|
||||
// 发送响应
|
||||
oos.writeObject("上报成功");
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.err.println("处理客户端数据失败:" + e.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
day02/src/com/inmind/student/张宇轩/Log.java
Normal file
31
day02/src/com/inmind/student/张宇轩/Log.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.inmind.student.张宇轩;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable, Comparable<Log> {
|
||||
private final long timestamp;
|
||||
private final String level;
|
||||
private final String module;
|
||||
private final String content;
|
||||
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + timestamp + "] " + level + " " + module + ": " + content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Log other) {
|
||||
return Long.compare(this.timestamp, other.timestamp);
|
||||
}
|
||||
}
|
||||
183
day02/src/com/inmind/student/张宇轩/LogAnalyzer.java
Normal file
183
day02/src/com/inmind/student/张宇轩/LogAnalyzer.java
Normal file
@@ -0,0 +1,183 @@
|
||||
package com.inmind.student.张宇轩;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogAnalyzer {
|
||||
private static final String LOG_DIR = "C:\\io_test";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
private static final Pattern LOG_PATTERN = Pattern.compile("(\\d+),(\\w+),(\\w+),(.*)");
|
||||
|
||||
private final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzer analyzer = new LogAnalyzer();
|
||||
analyzer.startAnalysis();
|
||||
}
|
||||
|
||||
public void startAnalysis() {
|
||||
try {
|
||||
File[] logFiles = getLogFiles();
|
||||
processFilesConcurrently(logFiles);
|
||||
executor.shutdown();
|
||||
if (!executor.awaitTermination(1, TimeUnit.MINUTES)) {
|
||||
System.err.println("线程池未在指定时间内关闭");
|
||||
}
|
||||
if (logs.isEmpty()) {
|
||||
System.out.println("未找到有效日志");
|
||||
return;
|
||||
}
|
||||
Map<String, Long> levelCounts = countByLevel();
|
||||
Map<String, Long> moduleErrorCounts = countErrorByModule();
|
||||
List<Log> earliestLogs = findEarliestLogs(3);
|
||||
sendResultsToServer(levelCounts, moduleErrorCounts, earliestLogs);
|
||||
} catch (Exception e) {
|
||||
System.err.println("分析失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (!executor.isShutdown()) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private File[] getLogFiles() throws IOException {
|
||||
Path dirPath = Paths.get(LOG_DIR);
|
||||
if (!Files.exists(dirPath)) {
|
||||
throw new FileNotFoundException("日志目录不存在: " + LOG_DIR);
|
||||
}
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dirPath, "*.log")) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (Path path : stream) {
|
||||
files.add(path.toFile());
|
||||
}
|
||||
|
||||
if (files.isEmpty()) {
|
||||
throw new FileNotFoundException("目录中没有日志文件");
|
||||
}
|
||||
|
||||
System.out.println("找到 " + files.size() + " 个日志文件");
|
||||
return files.toArray(new File[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private void processFilesConcurrently(File[] files) {
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
|
||||
for (File file : files) {
|
||||
futures.add(executor.submit(() -> {
|
||||
try {
|
||||
parseLogFile(file);
|
||||
System.out.println("完成处理: " + file.getName());
|
||||
} catch (IOException e) {
|
||||
System.err.println("处理文件出错 [" + file.getName() + "]: " + e.getMessage());
|
||||
}
|
||||
}));
|
||||
}
|
||||
for (Future<?> future : futures) {
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
System.err.println("任务执行异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLogFile(File file) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
Log log = parseLogLine(line);
|
||||
if (log != null) {
|
||||
logs.add(log);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("解析失败 [" + file.getName() + "]: " + line + " | 原因: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Log parseLogLine(String line) {
|
||||
if (line == null || line.trim().isEmpty()) return null;
|
||||
|
||||
String[] parts = line.split(",", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException("日志格式错误");
|
||||
}
|
||||
|
||||
try {
|
||||
long timestamp = Long.parseLong(parts[0].trim());
|
||||
String level = parts[1].trim().toUpperCase();
|
||||
String module = parts[2].trim();
|
||||
String content = parts[3].trim();
|
||||
|
||||
return new Log(timestamp, level, module, content);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("时间戳格式错误");
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Long> countByLevel() {
|
||||
return logs.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
Log::getLevel,
|
||||
Collectors.counting()
|
||||
));
|
||||
}
|
||||
|
||||
private Map<String, Long> countErrorByModule() {
|
||||
return logs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(
|
||||
Log::getModule,
|
||||
Collectors.counting()
|
||||
));
|
||||
}
|
||||
|
||||
private List<Log> findEarliestLogs(int count) {
|
||||
return logs.stream()
|
||||
.sorted()
|
||||
.limit(count)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void sendResultsToServer(
|
||||
Map<String, Long> levelCounts,
|
||||
Map<String, Long> moduleErrorCounts,
|
||||
List<Log> earliestLogs
|
||||
) {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) {
|
||||
|
||||
out.writeObject(levelCounts);
|
||||
out.writeObject(moduleErrorCounts);
|
||||
out.writeObject(earliestLogs);
|
||||
out.flush();
|
||||
|
||||
String response = (String) in.readObject();
|
||||
System.out.println("服务器响应: " + response);
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("网络通信失败: " + e.getMessage());
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("响应解析失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
59
day02/src/com/inmind/student/张宇轩/LogServer.java
Normal file
59
day02/src/com/inmind/student/张宇轩/LogServer.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package com.inmind.student.张宇轩;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LogServer {
|
||||
private static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||
System.out.println("日志服务器启动,监听端口: " + PORT);
|
||||
|
||||
while (true) {
|
||||
try (Socket clientSocket = serverSocket.accept();
|
||||
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream())) {
|
||||
|
||||
Map<String, Long> levelCounts = (Map<String, Long>) in.readObject();
|
||||
Map<String, Long> moduleErrorCounts = (Map<String, Long>) in.readObject();
|
||||
List<Log> earliestLogs = (List<Log>) in.readObject();
|
||||
|
||||
printResults(levelCounts, moduleErrorCounts, earliestLogs);
|
||||
|
||||
out.writeObject("上报成功");
|
||||
out.flush();
|
||||
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.err.println("客户端处理异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printResults(
|
||||
Map<String, Long> levelCounts,
|
||||
Map<String, Long> moduleErrorCounts,
|
||||
List<Log> earliestLogs
|
||||
) {
|
||||
System.out.println("\n===== 日志分析报告 =====");
|
||||
System.out.println("\n[级别统计]");
|
||||
levelCounts.forEach((level, count) ->
|
||||
System.out.printf("%-6s: %d 条%n", level, count));
|
||||
System.out.println("\n[模块错误统计]");
|
||||
moduleErrorCounts.forEach((module, count) ->
|
||||
System.out.printf("%-10s: %d 条错误%n", module, count));
|
||||
System.out.println("\n[最早的3条日志]");
|
||||
earliestLogs.forEach(System.out::println);
|
||||
|
||||
System.out.println("======================\n");
|
||||
}
|
||||
}
|
||||
68
day02/src/com/inmind/student/张崇昊/Log.java
Normal file
68
day02/src/com/inmind/student/张崇昊/Log.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package com.inmind.student.张崇昊;
|
||||
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
//解析每条日志,提取时间戳(long)、级别(String)、模块(String)、内容(String)。
|
||||
public class Log implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
Long timeChuo;
|
||||
String level;
|
||||
String moudel;
|
||||
String context;
|
||||
|
||||
|
||||
public Log(Long timeChuo, String level, String moudel, String context) {
|
||||
this.timeChuo = timeChuo;
|
||||
this.level = level;
|
||||
this.moudel = moudel;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Log() {
|
||||
}
|
||||
|
||||
public Long getTimeChuo() {
|
||||
return timeChuo;
|
||||
}
|
||||
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getMoudel() {
|
||||
return moudel;
|
||||
}
|
||||
|
||||
public String getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setTimeChuo(Long timeChuo) {
|
||||
this.timeChuo = timeChuo;
|
||||
}
|
||||
|
||||
public void setLevel(String level) {
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
public void setMoudel(String moudel) {
|
||||
this.moudel = moudel;
|
||||
}
|
||||
|
||||
public void setContext(String context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Log{" +
|
||||
"timeChuo=" + timeChuo +
|
||||
", level='" + level + '\'' +
|
||||
", moudel='" + moudel + '\'' +
|
||||
", context='" + context + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
180
day02/src/com/inmind/student/张崇昊/LogAnalysisClient.java
Normal file
180
day02/src/com/inmind/student/张崇昊/LogAnalysisClient.java
Normal file
@@ -0,0 +1,180 @@
|
||||
package com.inmind.student.张崇昊;
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogAnalysisClient {
|
||||
private static final String LOG_DIRECTORY = "C:\\Users\\21554\\Desktop\\桌面\\javaSE上机测试题内容";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
private List<Log> allLogs = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalysisClient client = new LogAnalysisClient();
|
||||
try {
|
||||
// 1. 读取并解析所有日志文件
|
||||
client.readAndParseLogs();
|
||||
|
||||
// 2. 分析日志
|
||||
Result result = client.analyzeLogs();
|
||||
|
||||
// 3. 上报结果
|
||||
client.reportResult(result);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用线程池并发读取并解析所有日志文件
|
||||
*/
|
||||
public void readAndParseLogs() throws IOException, InterruptedException, ExecutionException {
|
||||
// 获取目录下所有.log文件
|
||||
Path dirPath = Paths.get(LOG_DIRECTORY);
|
||||
if (!Files.exists(dirPath) || !Files.isDirectory(dirPath)) {
|
||||
throw new FileNotFoundException("日志目录不存在: " + LOG_DIRECTORY);
|
||||
}
|
||||
|
||||
List<Path> logFiles = Files.list(dirPath)
|
||||
.filter(p -> Files.isRegularFile(p) && p.getFileName().toString().endsWith(".log"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (logFiles.isEmpty()) {
|
||||
System.out.println("没有找到日志文件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建线程池
|
||||
int threadCount = Math.min(logFiles.size(), Runtime.getRuntime().availableProcessors() + 1);
|
||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
||||
|
||||
try {
|
||||
// 提交所有文件处理任务
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (Path file : logFiles) {
|
||||
futures.add(executor.submit(() -> processLogFile(file)));
|
||||
}
|
||||
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
future.get(); // 等待任务完成,会抛出异常
|
||||
}
|
||||
|
||||
System.out.println("所有日志文件解析完成,共解析 " + allLogs.size() + " 条日志");
|
||||
} finally {
|
||||
executor.shutdown(); // 关闭线程池
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个日志文件,读取并解析每一行
|
||||
*/
|
||||
private void processLogFile(Path file) {
|
||||
try (BufferedReader reader = Files.newBufferedReader(file)) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
Log log = parseLogLine(line);
|
||||
if (log != null) {
|
||||
allLogs.add(log);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析日志行失败,文件: " + file.getFileName() + ", 行内容: " + line);
|
||||
System.err.println("错误信息: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取日志文件失败: " + file.getFileName());
|
||||
System.err.println("错误信息: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析单行日志
|
||||
*/
|
||||
private Log parseLogLine(String line) {
|
||||
|
||||
// 分割日志行,处理可能的逗号
|
||||
String[] parts = line.split(",", 4);
|
||||
|
||||
long timestamp = Long.parseLong(parts[0].trim());
|
||||
String level = parts[1].trim();
|
||||
String module = parts[2].trim();
|
||||
String content = parts[3].trim();
|
||||
|
||||
return new Log(timestamp, level, module, content);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 分析日志数据,使用Stream和Lambda表达式
|
||||
*/
|
||||
public Result analyzeLogs() {
|
||||
// 1. 按级别统计日志数量
|
||||
Map<String, Long> levelCount = allLogs.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
|
||||
// 2. 按模块统计错误日志数量
|
||||
Map<String, Long> moduleErrorCount = allLogs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(Log::getMoudel, Collectors.counting()));
|
||||
|
||||
// 3. 找出时间戳最早的3条日志
|
||||
List<Log> earliestLogs = allLogs.stream()
|
||||
.sorted(Comparator.comparingLong(Log::getTimeChuo))
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new Result(levelCount, moduleErrorCount, earliestLogs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将分析结果通过Socket上报到服务器
|
||||
*/
|
||||
public void reportResult(Result result) throws IOException {
|
||||
Socket socket = null;
|
||||
ObjectOutputStream out = null;
|
||||
BufferedReader in = null;
|
||||
|
||||
try {
|
||||
// 连接服务器
|
||||
socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
|
||||
// 发送结果对象
|
||||
out = new ObjectOutputStream(socket.getOutputStream());
|
||||
out.writeObject(result);
|
||||
out.flush();
|
||||
|
||||
// 接收服务器响应
|
||||
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
String response = in.readLine();
|
||||
System.out.println("服务器响应: " + response);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
} finally {
|
||||
// 释放资源
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) { /* 忽略关闭异常 */ }
|
||||
}
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) { /* 忽略关闭异常 */ }
|
||||
}
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) { /* 忽略关闭异常 */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
day02/src/com/inmind/student/张崇昊/LogAnalysisServer.java
Normal file
106
day02/src/com/inmind/student/张崇昊/LogAnalysisServer.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package com.inmind.student.张崇昊;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 日志分析服务器,负责接收客户端上报的分析结果
|
||||
*/
|
||||
public class LogAnalysisServer {
|
||||
private static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
ServerSocket serverSocket = null;
|
||||
|
||||
try {
|
||||
// 创建服务器Socket并监听端口
|
||||
serverSocket = new ServerSocket(PORT);
|
||||
System.out.println("服务器已启动,监听端口 " + PORT + " ...");
|
||||
|
||||
while (true) { // 循环接受客户端连接
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
System.out.println("接收到客户端连接: " + clientSocket.getInetAddress());
|
||||
|
||||
// 为每个客户端连接创建一个新线程处理
|
||||
new Thread(() -> handleClient(clientSocket)).start();
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
System.out.println("服务器已关闭");
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器关闭失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理客户端连接,接收分析结果并返回响应
|
||||
*/
|
||||
private static void handleClient(Socket clientSocket) {
|
||||
ObjectInputStream in = null;
|
||||
PrintWriter out = null;
|
||||
|
||||
try {
|
||||
// 获取输入流,读取客户端发送的对象
|
||||
in = new ObjectInputStream(clientSocket.getInputStream());
|
||||
Result result = (Result) in.readObject();
|
||||
|
||||
// 打印接收的分析结果
|
||||
printAnalysisResult(result);
|
||||
|
||||
// 发送响应
|
||||
out = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||
out.println("上报成功");
|
||||
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.err.println("处理客户端请求出错: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (clientSocket != null) {
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印分析结果到控制台
|
||||
*/
|
||||
private static void printAnalysisResult(Result result) {
|
||||
System.out.println("\n===== 接收到的日志分析结果 =====");
|
||||
|
||||
// 打印级别统计
|
||||
System.out.println("1. 各级别日志数量统计:");
|
||||
Map<String, Long> levelCount = result.getLevelCount();
|
||||
for (Map.Entry<String, Long> entry : levelCount.entrySet()) {
|
||||
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
|
||||
}
|
||||
|
||||
// 打印模块错误统计
|
||||
System.out.println("2. 各模块错误日志数量统计:");
|
||||
Map<String, Long> moduleErrorCount = result.getModuleErrorCount();
|
||||
for (Map.Entry<String, Long> entry : moduleErrorCount.entrySet()) {
|
||||
System.out.println(" " + entry.getKey() + ": " + entry.getValue());
|
||||
}
|
||||
|
||||
// 打印最早的3条日志
|
||||
System.out.println("3. 时间戳最早的3条日志:");
|
||||
List<Log> earliestLogs = result.getEarliestLogs();
|
||||
for (int i = 0; i < earliestLogs.size(); i++) {
|
||||
System.out.println(" " + (i + 1) + ". " + earliestLogs.get(i));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
43
day02/src/com/inmind/student/张崇昊/Result.java
Normal file
43
day02/src/com/inmind/student/张崇昊/Result.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package com.inmind.student.张崇昊;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Result implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Map<String, Long> levelCount;
|
||||
private Map<String, Long> moduleErrorCount;
|
||||
private List<Log> earliestLogs;
|
||||
|
||||
public Result(Map<String, Long> levelCount, Map<String, Long> moduleErrorCount, List<Log> earliestLogs) {
|
||||
this.levelCount = levelCount;
|
||||
this.moduleErrorCount = moduleErrorCount;
|
||||
this.earliestLogs = earliestLogs;
|
||||
}
|
||||
|
||||
public Map<String, Long> getLevelCount() {
|
||||
return levelCount;
|
||||
}
|
||||
|
||||
public Map<String, Long> getModuleErrorCount() {
|
||||
return moduleErrorCount;
|
||||
}
|
||||
|
||||
public List<Log> getEarliestLogs() {
|
||||
return earliestLogs;
|
||||
}
|
||||
|
||||
public void setLevelCount(Map<String, Long> levelCount) {
|
||||
this.levelCount = levelCount;
|
||||
}
|
||||
|
||||
public void setModuleErrorCount(Map<String, Long> moduleErrorCount) {
|
||||
this.moduleErrorCount = moduleErrorCount;
|
||||
}
|
||||
|
||||
public void setEarliestLogs(List<Log> earliestLogs) {
|
||||
this.earliestLogs = earliestLogs;
|
||||
}
|
||||
}
|
||||
35
day02/src/com/inmind/student/张洁/Log.java
Normal file
35
day02/src/com/inmind/student/张洁/Log.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package com.inmind.student.张洁;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable {
|
||||
private long timetamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
public Log(long timetamp, String level, String module, String content) {
|
||||
this.timetamp = timetamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
public long getTimetamp() {
|
||||
return timetamp;
|
||||
}
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "["+timetamp+"] "+level+" "+module+": "+content;
|
||||
}
|
||||
}
|
||||
151
day02/src/com/inmind/student/张洁/LogAnalyzer.java
Normal file
151
day02/src/com/inmind/student/张洁/LogAnalyzer.java
Normal file
@@ -0,0 +1,151 @@
|
||||
package com.inmind.student.张洁;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
public class LogAnalyzer {
|
||||
public static final String LOG_DIR = "D:/workspace_idea/JavaSE202507/NextDay13_test/logs/";
|
||||
private static final String serverAdd = "localhost";
|
||||
private static final int port = 8080;
|
||||
|
||||
private List<Log> logs = new ArrayList<Log>();
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
if (!Files.exists(Paths.get(LOG_DIR))) {
|
||||
throw new FileNotFoundException("<EFBFBD><EFBFBD>־Ŀ¼<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + LOG_DIR);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// <20><>ȡ<EFBFBD><C8A1>־<EFBFBD>ļ<EFBFBD><C4BC>б<EFBFBD>
|
||||
File logFile = new File(LOG_DIR);
|
||||
File[] files = logFile.listFiles((dir, name) -> name.endsWith(".log"));
|
||||
if (files == null) {
|
||||
System.out.println("δ<EFBFBD>ҵ<EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD>");
|
||||
return;
|
||||
}
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
LogAnalyzer analyzer = new LogAnalyzer();
|
||||
for (File file : files) {
|
||||
Thread thread = new Thread(() -> analyzer.parseLogFile(file));
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
LogAnalyzer analyzer2= new LogAnalyzer();
|
||||
Map<String, Integer> levelmap = analyzer2.levelmapCount();
|
||||
Map<String, Integer> moduleErrorMap = analyzer2.moduleErrorCount();
|
||||
List<Log> earlistLogs = analyzer2.earlistLogsCount();
|
||||
analyzer2.sendToServer(levelmap, moduleErrorMap, earlistLogs);
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>Ǿ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ö<EFBFBD><C3B6><EFBFBD><EFBFBD><EFBFBD>
|
||||
private void parseLogFile(File file) {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
try {
|
||||
Log log = parseLogLine(line);
|
||||
synchronized (LOCK) {
|
||||
logs.add(log);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD>ļ<EFBFBD> " + file.getName() + " <20><><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD>" + line + "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD>" + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static Log parseLogLine(String line) {
|
||||
String[] parts = line.split(",", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException("<EFBFBD><EFBFBD>־<EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ ʱ<><CAB1><EFBFBD>,<2C><><EFBFBD><EFBFBD>,ģ<><C4A3>,<2C><><EFBFBD><EFBFBD>");
|
||||
}
|
||||
|
||||
try {
|
||||
long timestamp = Long.parseLong(parts[0]);
|
||||
return new Log(timestamp, parts[1], parts[2], parts[3]);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("ʱ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>" + parts[0], e);
|
||||
}
|
||||
}
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD><CDB3>
|
||||
public Map<String, Integer> levelmapCount() {
|
||||
HashMap<String, Integer> hmap = new HashMap<>();
|
||||
synchronized (LOCK) {
|
||||
for (Log log : logs) {
|
||||
String level = log.getLevel();
|
||||
hmap.put(level, hmap.getOrDefault(level, 0) + 1);
|
||||
}
|
||||
}
|
||||
return hmap;
|
||||
}
|
||||
|
||||
// <20><>ģ<EFBFBD><C4A3>ͳ<EFBFBD>ƴ<EFBFBD><C6B4><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><D6BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DFBC><EFBFBD>key Ϊģ<CEAA><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
public Map<String, Integer> moduleErrorCount() {
|
||||
HashMap<String, Integer> hmap = new HashMap<>();
|
||||
synchronized (LOCK) {
|
||||
for (Log log : logs) {
|
||||
if ("ERROR".equals(log.getLevel())) {
|
||||
String module = log.getModule();
|
||||
hmap.put(module, hmap.getOrDefault(module, 0) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hmap;
|
||||
}
|
||||
|
||||
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD> 3 <20><><EFBFBD><EFBFBD>־
|
||||
public List<Log> earlistLogsCount() {
|
||||
List<Log> copy;
|
||||
synchronized (LOCK) {
|
||||
copy = new ArrayList<>(logs);
|
||||
}
|
||||
Collections.sort(copy, Comparator.comparingLong(Log::getTimetamp));
|
||||
if (copy.size() <= 3) {
|
||||
return copy;
|
||||
} else {
|
||||
return copy.subList(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// <20>ϱ<EFBFBD>ͳ<EFBFBD>ƽ<EFBFBD><C6BD>
|
||||
private void sendToServer(Map<String, Integer> levelStats, Map<String, Integer> moduleErrorStats, List<Log> earliestLogs) {
|
||||
try (Socket socket = new Socket(serverAdd, port);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
|
||||
|
||||
oos.writeObject(levelStats);
|
||||
oos.writeObject(moduleErrorStats);
|
||||
oos.writeObject(earliestLogs);
|
||||
oos.flush();
|
||||
|
||||
String response = (String) ois.readObject();
|
||||
System.out.println("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>" + response);
|
||||
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.out.println(e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
48
day02/src/com/inmind/student/张洁/LogServer.java
Normal file
48
day02/src/com/inmind/student/张洁/LogServer.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.inmind.student.张洁;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LogServer {
|
||||
public static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
ServerSocket ss = new ServerSocket(PORT);
|
||||
while(true){
|
||||
try{
|
||||
Socket s = ss.accept();
|
||||
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
Map<String,Integer> levelmap = (Map<String, Integer>) ois.readObject();
|
||||
Map<String,Integer> mouduleErrorMap = (Map<String, Integer>) ois.readObject();
|
||||
List<Log> earlistLogs = (List<Log>) ois.readObject();
|
||||
|
||||
System.out.println("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ƣ<EFBFBD>");
|
||||
for(String key : levelmap.keySet()){
|
||||
System.out.println(key+"<EFBFBD><EFBFBD>"+levelmap.get(key));
|
||||
}
|
||||
System.out.println("ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ƣ<EFBFBD>");
|
||||
for(String key : mouduleErrorMap.keySet()){
|
||||
System.out.println(key+":"+mouduleErrorMap.get(key));
|
||||
}
|
||||
System.out.println("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>3<EFBFBD><EFBFBD><EFBFBD><EFBFBD>־<EFBFBD><EFBFBD>");
|
||||
for (Log earlistLog : earlistLogs) {
|
||||
System.out.println(earlistLog);
|
||||
}
|
||||
oos.writeObject("<EFBFBD>ϱ<EFBFBD><EFBFBD>ɹ<EFBFBD>");
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
day02/src/com/inmind/student/张洁/Main.java
Normal file
17
day02/src/com/inmind/student/张洁/Main.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.inmind.student.张洁;
|
||||
|
||||
//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
//TIP Press <shortcut actionId="ShowIntentionActions"/> with your caret at the highlighted text
|
||||
// to see how IntelliJ IDEA suggests fixing it.
|
||||
System.out.printf("Hello and welcome!");
|
||||
|
||||
for (int i = 1; i <= 5; i++) {
|
||||
//TIP Press <shortcut actionId="Debug"/> to start debugging your code. We have set one <icon src="AllIcons.Debugger.Db_set_breakpoint"/> breakpoint
|
||||
// for you, but you can always add more by pressing <shortcut actionId="ToggleLineBreakpoint"/>.
|
||||
System.out.println("i = " + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
day02/src/com/inmind/student/张洁/logback.xml
Normal file
41
day02/src/com/inmind/student/张洁/logback.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!--
|
||||
CONSOLE :表示当前的日志信息是可以输出到控制台的。
|
||||
-->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!--输出流对象 默认 System.out 改为 System.err-->
|
||||
<target>System.out</target>
|
||||
<encoder>
|
||||
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度
|
||||
%msg:日志消息,%n是换行符-->
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] %c [%thread] : %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- File是输出的方向通向文件的 -->
|
||||
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<!--日志输出路径-->
|
||||
<file>D:/log/inmind-data.log</file>
|
||||
<!--指定日志文件拆分和压缩规则-->
|
||||
<rollingPolicy
|
||||
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!--通过指定压缩文件名称,来确定分割文件方式-->
|
||||
<fileNamePattern>D:/log/inmind-data-%i-%d{yyyy-MM-dd}-.log.gz</fileNamePattern>
|
||||
<!--文件拆分大小-->
|
||||
<maxFileSize>1MB</maxFileSize>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!--
|
||||
1、控制日志的输出情况:如,开启日志,取消日志
|
||||
-->
|
||||
<root level="debug">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
</configuration>
|
||||
37
day02/src/com/inmind/student/杨靖宇/Log.java
Normal file
37
day02/src/com/inmind/student/杨靖宇/Log.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.inmind.student.杨靖宇;
|
||||
|
||||
public class Log {
|
||||
private long timestamp;
|
||||
|
||||
private String level;
|
||||
|
||||
private String module;
|
||||
|
||||
private String content;
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s] [%s] [%s] %s", timestamp, level, module, content);
|
||||
}
|
||||
}
|
||||
227
day02/src/com/inmind/student/杨靖宇/LogAnalyzer.java
Normal file
227
day02/src/com/inmind/student/杨靖宇/LogAnalyzer.java
Normal file
@@ -0,0 +1,227 @@
|
||||
package com.inmind.student.杨靖宇;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.util.*;
|
||||
import java.net.*;
|
||||
|
||||
|
||||
public class LogAnalyzer {
|
||||
private static final String LOG_DIR = "D:\\io_test";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
|
||||
private final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
private final List<Thread> threads = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzer analyzer = new LogAnalyzer();
|
||||
try {
|
||||
analyzer.analyze();
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("[错误] 日志目录不存在: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
System.err.println("[错误] 分析过程中出现异常: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void analyze() throws FileNotFoundException {
|
||||
// 1. 检查并创建日志目录
|
||||
ensureLogDirectoryExists();
|
||||
|
||||
// 2. 读取日志文件
|
||||
readLogFiles();
|
||||
|
||||
// 3. 等待所有线程完成
|
||||
waitForThreads();
|
||||
|
||||
if (logs.isEmpty()) {
|
||||
System.out.println("[提示] 没有解析到任何有效日志");
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 统计日志数据
|
||||
Map<String, Integer> levelStats = countByLevel();
|
||||
Map<String, Integer> moduleErrorStats = countModuleErrors();
|
||||
List<Log> earliestLogs = getEarliestLogs(3);
|
||||
|
||||
// 5. 上报统计结果
|
||||
reportToServer(levelStats, moduleErrorStats, earliestLogs);
|
||||
}
|
||||
|
||||
private void ensureLogDirectoryExists() throws FileNotFoundException {
|
||||
File logDir = new File(LOG_DIR);
|
||||
if (!logDir.exists()) {
|
||||
System.out.println("[提示] 日志目录不存在,尝试创建...");
|
||||
if (!logDir.mkdirs()) {
|
||||
throw new FileNotFoundException("无法创建日志目录: " + LOG_DIR);
|
||||
}
|
||||
System.out.println("[成功] 已创建日志目录: " + LOG_DIR);
|
||||
}
|
||||
}
|
||||
|
||||
private void readLogFiles() throws FileNotFoundException {
|
||||
File logDir = new File(LOG_DIR);
|
||||
File[] logFiles = logDir.listFiles((dir, name) -> name.endsWith(".log"));
|
||||
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("[提示] 目录中没有找到.log文件");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.printf("[信息] 找到 %d 个日志文件\n", logFiles.length);
|
||||
|
||||
for (File file : logFiles) {
|
||||
Thread thread = new Thread(() -> parseLogFile(file));
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForThreads() {
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println("[警告] 线程等待被中断");
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLogFile(File file) {
|
||||
System.out.printf("[信息] 开始解析文件: %s\n", file.getName());
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
int lineNum = 0;
|
||||
int successCount = 0;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
lineNum++;
|
||||
try {
|
||||
Log log = parseLogLine(line);
|
||||
logs.add(log);
|
||||
successCount++;
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.printf("[警告] %s 第 %d 行: 时间戳格式错误\n",
|
||||
file.getName(), lineNum);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.printf("[警告] %s 第 %d 行: 日志格式错误\n",
|
||||
file.getName(), lineNum);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.printf("[成功] 文件 %s 解析完成: 总行数 %d, 成功 %d, 失败 %d\n",
|
||||
file.getName(), lineNum, successCount, lineNum - successCount);
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.printf("[错误] 文件不存在: %s\n", file.getPath());
|
||||
} catch (IOException e) {
|
||||
System.err.printf("[错误] 读取文件 %s 失败: %s\n", file.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Log parseLogLine(String line) throws IllegalArgumentException, NumberFormatException {
|
||||
String[] parts = line.split(",", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException("需要4个字段但找到" + parts.length);
|
||||
}
|
||||
|
||||
long timestamp = Long.parseLong(parts[0].trim());
|
||||
return new Log(timestamp, parts[1].trim(), parts[2].trim(), parts[3].trim());
|
||||
}
|
||||
|
||||
private Map<String, Integer> countByLevel() {
|
||||
Map<String, Integer> stats = new HashMap<>();
|
||||
synchronized (logs) {
|
||||
for (Log log : logs) {
|
||||
stats.merge(log.getLevel(), 1, Integer::sum);
|
||||
}
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
private Map<String, Integer> countModuleErrors() {
|
||||
Map<String, Integer> stats = new HashMap<>();
|
||||
synchronized (logs) {
|
||||
for (Log log : logs) {
|
||||
if ("ERROR".equals(log.getLevel())) {
|
||||
stats.merge(log.getModule(), 1, Integer::sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
private List<Log> getEarliestLogs(int count) {
|
||||
List<Log> copy;
|
||||
synchronized (logs) {
|
||||
copy = new ArrayList<>(logs);
|
||||
}
|
||||
|
||||
if (copy.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
copy.sort(Comparator.comparingLong(Log::getTimestamp));
|
||||
return new ArrayList<>(copy.subList(0, Math.min(count, copy.size())));
|
||||
}
|
||||
|
||||
private void reportToServer(Map<String, Integer> levelStats,
|
||||
Map<String, Integer> moduleErrorStats,
|
||||
List<Log> earliestLogs) {
|
||||
final int maxRetries = 3;
|
||||
int attempt = 0;
|
||||
|
||||
while (attempt < maxRetries) {
|
||||
attempt++;
|
||||
try (Socket socket = new Socket()) {
|
||||
// 设置连接和读取超时
|
||||
socket.connect(new InetSocketAddress(SERVER_HOST, SERVER_PORT), 5000);
|
||||
socket.setSoTimeout(10000);
|
||||
|
||||
try (ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
|
||||
|
||||
// 确保发送的是可序列化的ArrayList
|
||||
oos.writeObject(new HashMap<>(levelStats));
|
||||
oos.writeObject(new HashMap<>(moduleErrorStats));
|
||||
oos.writeObject(new ArrayList<>(earliestLogs));
|
||||
oos.flush();
|
||||
|
||||
String response = (String) ois.readObject();
|
||||
System.out.println("[成功] 服务器响应: " + response);
|
||||
return;
|
||||
}
|
||||
} catch (ConnectException e) {
|
||||
System.err.printf("[错误] 连接失败(尝试 %d/%d): %s\n",
|
||||
attempt, maxRetries, e.getMessage());
|
||||
if (attempt >= maxRetries) {
|
||||
System.err.println("[错误] 达到最大重试次数,放弃连接");
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(1000 * attempt);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (SocketTimeoutException e) {
|
||||
System.err.println("[错误] 连接或读取超时");
|
||||
} catch (EOFException e) {
|
||||
System.err.println("[错误] 连接意外中断");
|
||||
} catch (UnknownHostException e) {
|
||||
System.err.println("[错误] 未知主机: " + SERVER_HOST);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
System.err.println("[错误] 通信错误: " + e.getMessage());
|
||||
break;
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("[错误] 协议错误: 收到未知响应类型");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
day02/src/com/inmind/student/杨靖宇/LogServer.java
Normal file
79
day02/src/com/inmind/student/杨靖宇/LogServer.java
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
package com.inmind.student.杨靖宇;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class LogServer {
|
||||
// 定义服务器端口常量
|
||||
private static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 创建ServerSocket,监听指定端口
|
||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||
System.out.println("日志服务器已启动,正在监听端口 " + PORT + "...");
|
||||
|
||||
// 持续等待客户端连接
|
||||
while (true) {
|
||||
try (Socket clientSocket = serverSocket.accept();
|
||||
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream())) {
|
||||
|
||||
System.out.println("客户端连接成功: " + clientSocket.getInetAddress());
|
||||
|
||||
// 接收3类数据
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Integer> levelStats = (Map<String, Integer>) ois.readObject();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Integer> moduleErrorStats = (Map<String, Integer>) ois.readObject();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Log> earliestLogs = (List<Log>) ois.readObject();
|
||||
|
||||
// 打印统计结果
|
||||
printStatistics(levelStats, moduleErrorStats, earliestLogs);
|
||||
|
||||
// 向客户端返回响应
|
||||
oos.writeObject("上报成功");
|
||||
oos.flush();
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("类未找到异常: " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
System.err.println("客户端连接处理异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 打印统计结果
|
||||
private static void printStatistics(Map<String, Integer> levelStats,
|
||||
Map<String, Integer> moduleErrorStats,
|
||||
List<Log> earliestLogs) {
|
||||
System.out.println("\n=== 日志统计结果 ===");
|
||||
|
||||
// 打印级别统计
|
||||
System.out.println("\n日志级别统计:");
|
||||
for (Map.Entry<String, Integer> entry : levelStats.entrySet()) {
|
||||
System.out.println(entry.getKey() + ": " + entry.getValue() + " 条");
|
||||
}
|
||||
|
||||
// 打印模块错误统计
|
||||
System.out.println("\n模块错误统计:");
|
||||
for (Map.Entry<String, Integer> entry : moduleErrorStats.entrySet()) {
|
||||
System.out.println(entry.getKey() + ": " + entry.getValue() + " 次错误");
|
||||
}
|
||||
|
||||
// 打印最早的3条日志
|
||||
System.out.println("\n最早的3条日志:");
|
||||
for (Log log : earliestLogs) {
|
||||
System.out.println(log);
|
||||
}
|
||||
|
||||
System.out.println("=== 统计结束 ===\n");
|
||||
}
|
||||
}
|
||||
34
day02/src/com/inmind/student/狄德蓉/Log.java
Normal file
34
day02/src/com/inmind/student/狄德蓉/Log.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.inmind.student.狄德蓉;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Log implements Serializable {
|
||||
|
||||
|
||||
private long timestamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = Objects.requireNonNull(level, "日志级别不可为空");
|
||||
this.module = Objects.requireNonNull(module, "日志模块不可为空");
|
||||
this.content = Objects.requireNonNull(content, "日志内容不可为空");
|
||||
}
|
||||
|
||||
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + timestamp + "] " + level + " " + module + ": " + content;
|
||||
}
|
||||
}
|
||||
|
||||
176
day02/src/com/inmind/student/狄德蓉/LogAnalyzer.java
Normal file
176
day02/src/com/inmind/student/狄德蓉/LogAnalyzer.java
Normal file
@@ -0,0 +1,176 @@
|
||||
package com.inmind.student.狄德蓉;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class LogAnalyzer {
|
||||
|
||||
private static final String LOG_DIR = "D:\\io_test";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
|
||||
|
||||
private static final List<Log> logs = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
try {
|
||||
|
||||
int fileCount = readLogFiles();
|
||||
System.out.println("找到 " + fileCount + " 个日志文件,开始解析...");
|
||||
|
||||
Map<String, Long> levelCountMap = countByLevel();
|
||||
Map<String, Long> errorModuleCountMap = countErrorByModule();
|
||||
List<Log> earliestLogs = getEarliestLogs(3);
|
||||
|
||||
|
||||
reportToServer(levelCountMap, errorModuleCountMap, earliestLogs);
|
||||
|
||||
System.out.println("日志分析和上报完成");
|
||||
} catch (Exception e) {
|
||||
System.err.println("程序执行异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int readLogFiles() throws Exception {
|
||||
File logDir = new File(LOG_DIR);
|
||||
if (!logDir.exists() || !logDir.isDirectory()) {
|
||||
throw new RuntimeException("日志目录不存在:" + LOG_DIR);
|
||||
}
|
||||
|
||||
|
||||
File[] logFiles = logDir.listFiles(file ->
|
||||
file.isFile() && file.getName().endsWith(".log")
|
||||
);
|
||||
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
throw new RuntimeException("日志目录中没有 .log 文件:" + LOG_DIR);
|
||||
}
|
||||
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(logFiles.length);
|
||||
|
||||
try {
|
||||
for (File logFile : logFiles) {
|
||||
|
||||
executor.submit(() -> parseLogFile(logFile));
|
||||
}
|
||||
|
||||
|
||||
executor.shutdown();
|
||||
while (!executor.isTerminated()) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
} finally {
|
||||
|
||||
executor.shutdownNow();
|
||||
}
|
||||
|
||||
System.out.println("日志解析完成,共解析 " + logs.size() + " 条日志");
|
||||
return logFiles.length;
|
||||
}
|
||||
|
||||
|
||||
private static void parseLogFile(File logFile) {
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(logFile))) {
|
||||
String line;
|
||||
int lineCount = 0;
|
||||
|
||||
Pattern pattern = Pattern.compile(
|
||||
"^(\\d+),(\\w+),(\\w+),(.*)$"
|
||||
);
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
lineCount++;
|
||||
Matcher matcher = pattern.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
try {
|
||||
|
||||
long timestamp = Long.parseLong(matcher.group(1));
|
||||
String level = matcher.group(2);
|
||||
String module = matcher.group(3);
|
||||
String content = matcher.group(4);
|
||||
|
||||
|
||||
synchronized (logs) {
|
||||
logs.add(new Log(timestamp, level, module, content));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析日志失败(跳过该行):" + line);
|
||||
System.err.println(" 异常:" + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
System.err.println("日志格式错误(跳过该行):" + line);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("解析完成:" + logFile.getName() + ",共 " + (lineCount-1) + " 行");
|
||||
} catch (Exception e) {
|
||||
System.err.println(" 解析日志文件失败:" + logFile.getAbsolutePath());
|
||||
System.err.println(" 异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static Map<String, Long> countByLevel() {
|
||||
return logs.stream()
|
||||
.collect(Collectors.groupingBy(
|
||||
Log::getLevel,
|
||||
Collectors.counting()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
private static Map<String, Long> countErrorByModule() {
|
||||
return logs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel())) // 只统计 ERROR 级别
|
||||
.collect(Collectors.groupingBy(
|
||||
Log::getModule,
|
||||
Collectors.counting()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
private static List<Log> getEarliestLogs(int n) {
|
||||
return logs.stream()
|
||||
.sorted((log1, log2) ->
|
||||
Long.compare(log1.getTimestamp(), log2.getTimestamp())
|
||||
)
|
||||
.limit(n)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
private static void reportToServer(
|
||||
Map<String, Long> levelCountMap,
|
||||
Map<String, Long> errorModuleCountMap,
|
||||
List<Log> earliestLogs
|
||||
) throws Exception {
|
||||
try (
|
||||
Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())
|
||||
) {
|
||||
|
||||
oos.writeObject(levelCountMap);
|
||||
oos.writeObject(errorModuleCountMap);
|
||||
oos.writeObject(earliestLogs);
|
||||
|
||||
System.out.println("服务器响应:上报成功");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("上报失败:" + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
day02/src/com/inmind/student/狄德蓉/LogServer.java
Normal file
69
day02/src/com/inmind/student/狄德蓉/LogServer.java
Normal file
@@ -0,0 +1,69 @@
|
||||
package com.inmind.student.狄德蓉;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class LogServer {
|
||||
|
||||
private static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||
|
||||
while (true) {
|
||||
try (
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream())
|
||||
) {
|
||||
System.out.println("客户端连接成功:" + clientSocket.getInetAddress());
|
||||
|
||||
|
||||
Map<String, Long> levelCountMap = (Map<String, Long>) ois.readObject();
|
||||
Map<String, Long> errorModuleCountMap = (Map<String, Long>) ois.readObject();
|
||||
List<Log> earliestLogs = (List<Log>) ois.readObject();
|
||||
|
||||
|
||||
printStatistics(levelCountMap, errorModuleCountMap, earliestLogs);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("服务器处理异常:" + e.getMessage() );
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("服务器启动失败:" + e.getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void printStatistics(
|
||||
Map<String, Long> levelCountMap,
|
||||
Map<String, Long> errorModuleCountMap,
|
||||
List<Log> earliestLogs
|
||||
) {
|
||||
System.out.println("\n=== 日志统计结果 ===");
|
||||
|
||||
|
||||
System.out.println("1. 按级别统计:");
|
||||
levelCountMap.forEach((level, count) ->
|
||||
System.out.println(" " + level + ":" + count + " 条")
|
||||
);
|
||||
|
||||
|
||||
System.out.println("\n2. 按模块错误统计:");
|
||||
errorModuleCountMap.forEach((module, count) ->
|
||||
System.out.println(" " + module + ":" + count + " 条错误")
|
||||
);
|
||||
|
||||
|
||||
System.out.println("\n3. 最早的 3 条日志:");
|
||||
earliestLogs.forEach(log ->
|
||||
System.out.println(" " + log)
|
||||
);
|
||||
}
|
||||
}
|
||||
28
day02/src/com/inmind/student/罗康凯/Log.java
Normal file
28
day02/src/com/inmind/student/罗康凯/Log.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.inmind.student.罗康凯;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable, Comparable<Log> {
|
||||
private long timestamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
|
||||
@Override
|
||||
public int compareTo(Log other) {
|
||||
return Long.compare(this.timestamp, other.timestamp);
|
||||
}
|
||||
}
|
||||
106
day02/src/com/inmind/student/罗康凯/LogAnalyzer.java
Normal file
106
day02/src/com/inmind/student/罗康凯/LogAnalyzer.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package com.inmind.student.罗康凯;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
public class LogAnalyzer {
|
||||
private static final String LOG_DIR = "C:\\Users\\30914\\IdeaProjects\\WebProject\\summerday\\S_day13\\src\\testkaoshi";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
private static final Pattern LOG_PATTERN = Pattern.compile("^(\\d+),(\\w+),(\\w+),(.*)$");
|
||||
|
||||
private static final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// 1. 读取并解析日志文件
|
||||
File[] logFiles = new File(LOG_DIR).listFiles(f -> f.getName().endsWith(".log"));
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("未找到日志文件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 多线程处理日志文件
|
||||
List<Future<?>> futures = Arrays.stream(logFiles)
|
||||
.map(file -> executor.submit(() -> processLogFile(file)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
|
||||
// 3. 统计分析
|
||||
Map<String, Long> levelCount = logs.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
|
||||
Map<String, Long> moduleErrorCount = logs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
// .collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
.collect(Collectors.groupingBy(l->l.getModule(), Collectors.counting()));
|
||||
|
||||
List<Log> earliestLogs = logs.stream()
|
||||
.sorted()
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 4. 网络上报
|
||||
sendResults(levelCount, moduleErrorCount, earliestLogs);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理过程中发生错误: " + e.getMessage());
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private static void processLogFile(File file) {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
Matcher matcher = LOG_PATTERN.matcher(line.trim());
|
||||
if (matcher.matches()) {
|
||||
long timestamp = Long.parseLong(matcher.group(1));
|
||||
String level = matcher.group(2);
|
||||
String module = matcher.group(3);
|
||||
String content = matcher.group(4);
|
||||
logs.add(new Log(timestamp, level, module, content));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析日志行失败: " + line + ", 错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件失败: " + file.getName() + ", 错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendResults(Map<String, Long> levelCount,
|
||||
Map<String, Long> moduleErrorCount,
|
||||
List<Log> earliestLogs) {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
// 发送统计结果
|
||||
out.writeObject(levelCount);
|
||||
out.writeObject(moduleErrorCount);
|
||||
out.writeObject(earliestLogs);
|
||||
out.flush();
|
||||
|
||||
// 接收服务器响应
|
||||
String response = in.readLine();
|
||||
System.out.println("服务器响应: " + response);
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("网络通信失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
44
day02/src/com/inmind/student/罗康凯/LogServer.java
Normal file
44
day02/src/com/inmind/student/罗康凯/LogServer.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.inmind.student.罗康凯;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class LogServer {
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(8080)) {
|
||||
System.out.println("服务器已启动,等待客户端连接...");
|
||||
|
||||
while (true) {
|
||||
try (Socket socket = serverSocket.accept();
|
||||
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
|
||||
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
|
||||
|
||||
System.out.println("客户端已连接: " + socket.getInetAddress());
|
||||
|
||||
// 接收客户端数据
|
||||
Map<String, Long> levelCount = (Map<String, Long>) in.readObject();
|
||||
Map<String, Long> moduleErrorCount = (Map<String, Long>) in.readObject();
|
||||
List<Log> earliestLogs = (List<Log>) in.readObject();
|
||||
|
||||
// 打印统计结果
|
||||
System.out.println("\n=== 接收到的统计结果 ===");
|
||||
System.out.println("按级别统计: " + levelCount);
|
||||
System.out.println("按模块错误统计: " + moduleErrorCount);
|
||||
System.out.println("最早的3条日志:");
|
||||
earliestLogs.forEach(log -> System.out.printf(
|
||||
"[%d] %s %s: %s%n",
|
||||
log.getTimestamp(), log.getLevel(), log.getModule(), log.getContent()));
|
||||
|
||||
// 发送响应
|
||||
out.println("上报成功");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理客户端请求时出错: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
28
day02/src/com/inmind/student/罗康凯2/Log.java
Normal file
28
day02/src/com/inmind/student/罗康凯2/Log.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package com.inmind.student.罗康凯2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable, Comparable<Log> {
|
||||
private long timestamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
|
||||
@Override
|
||||
public int compareTo(Log other) {
|
||||
return Long.compare(this.timestamp, other.timestamp);
|
||||
}
|
||||
}
|
||||
105
day02/src/com/inmind/student/罗康凯2/LogAnalyzer.java
Normal file
105
day02/src/com/inmind/student/罗康凯2/LogAnalyzer.java
Normal file
@@ -0,0 +1,105 @@
|
||||
package com.inmind.student.罗康凯2;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
public class LogAnalyzer {
|
||||
private static final String LOG_DIR = "C:\\Users\\30914\\IdeaProjects\\WebProject\\summerday\\S_day13\\src\\testkaoshi";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
private static final Pattern LOG_PATTERN = Pattern.compile("^(\\d+),(\\w+),(\\w+),(.*)$");
|
||||
|
||||
private static final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
// 1. 读取并解析日志文件
|
||||
File[] logFiles = new File(LOG_DIR).listFiles(f -> f.getName().endsWith(".log"));
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("未找到日志文件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 多线程处理日志文件
|
||||
List<Future<?>> futures = Arrays.stream(logFiles)
|
||||
.map(file -> executor.submit(() -> processLogFile(file)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
|
||||
// 3. 统计分析
|
||||
Map<String, Long> levelCount = logs.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
|
||||
Map<String, Long> moduleErrorCount = logs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
|
||||
List<Log> earliestLogs = logs.stream()
|
||||
.sorted()
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 4. 网络上报
|
||||
sendResults(levelCount, moduleErrorCount, earliestLogs);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理过程中发生错误: " + e.getMessage());
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private static void processLogFile(File file) {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
Matcher matcher = LOG_PATTERN.matcher(line.trim());
|
||||
if (matcher.matches()) {
|
||||
long timestamp = Long.parseLong(matcher.group(1));
|
||||
String level = matcher.group(2);
|
||||
String module = matcher.group(3);
|
||||
String content = matcher.group(4);
|
||||
logs.add(new Log(timestamp, level, module, content));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析日志行失败: " + line + ", 错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件失败: " + file.getName() + ", 错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendResults(Map<String, Long> levelCount,
|
||||
Map<String, Long> moduleErrorCount,
|
||||
List<Log> earliestLogs) {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
// 发送统计结果
|
||||
out.writeObject(levelCount);
|
||||
out.writeObject(moduleErrorCount);
|
||||
out.writeObject(earliestLogs);
|
||||
out.flush();
|
||||
|
||||
// 接收服务器响应
|
||||
String response = in.readLine();
|
||||
System.out.println("服务器响应: " + response);
|
||||
|
||||
} catch (IOException e) {
|
||||
System.err.println("网络通信失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
133
day02/src/com/inmind/student/罗康凯2/LogProcessor.java
Normal file
133
day02/src/com/inmind/student/罗康凯2/LogProcessor.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package com.inmind.student.罗康凯2;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogProcessor implements AutoCloseable {
|
||||
// 配置常量
|
||||
private static final String LOG_DIR = "C:\\Users\\30914\\IdeaProjects\\WebProject\\summerday\\S_day13\\src\\testkaoshi";
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
private static final int THREAD_POOL_SIZE = 5;
|
||||
private static final Pattern LOG_PATTERN = Pattern.compile("^(\\d+),(\\w+),(\\w+),(.*)$");
|
||||
|
||||
// 线程安全集合与线程池
|
||||
private final List<Log> logs = Collections.synchronizedList(new ArrayList<>());
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
|
||||
|
||||
// 主处理流程
|
||||
public void process() {
|
||||
try {
|
||||
File[] logFiles = listLogFiles();
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("未找到日志文件");
|
||||
return;
|
||||
}
|
||||
|
||||
processFilesAsync(logFiles);
|
||||
Stats stats = calculateStats();
|
||||
sendStatsToServer(stats);
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取日志文件列表
|
||||
private File[] listLogFiles() throws IOException {
|
||||
File dir = new File(LOG_DIR);
|
||||
if (!dir.exists()) throw new FileNotFoundException("日志目录不存在: " + LOG_DIR);
|
||||
if (!dir.isDirectory()) throw new IOException("路径不是目录: " + LOG_DIR);
|
||||
|
||||
File[] files = dir.listFiles(f -> f.getName().endsWith(".log"));
|
||||
return files == null ? new File[0] : files;
|
||||
}
|
||||
|
||||
// 异步处理文件
|
||||
private void processFilesAsync(File[] files) throws InterruptedException, ExecutionException {
|
||||
List<Future<?>> futures = Arrays.stream(files)
|
||||
.map(file -> executor.submit(() -> processSingleFile(file)))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
}
|
||||
|
||||
// 处理单个日志文件
|
||||
private void processSingleFile(File file) {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
parseLogLine(line.trim());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件失败[" + file.getName() + "]: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 解析日志行
|
||||
private void parseLogLine(String line) {
|
||||
try {
|
||||
Matcher matcher = LOG_PATTERN.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
logs.add(new Log(
|
||||
Long.parseLong(matcher.group(1)),
|
||||
matcher.group(2),
|
||||
matcher.group(3),
|
||||
matcher.group(4)
|
||||
));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("解析日志行失败[" + line + "]: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 计算统计结果
|
||||
private Stats calculateStats() {
|
||||
Map<String, Long> levelCount = logs.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
|
||||
Map<String, Long> moduleErrorCount = logs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
|
||||
List<Log> earliestLogs = logs.stream()
|
||||
.sorted()
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new Stats(levelCount, moduleErrorCount, earliestLogs);
|
||||
}
|
||||
|
||||
// 发送统计结果到服务器
|
||||
private void sendStatsToServer(Stats stats) throws IOException {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
out.writeObject(stats);
|
||||
out.flush();
|
||||
System.out.println("服务器响应: " + in.readLine());
|
||||
} catch (ConnectException e) {
|
||||
throw new IOException("连接服务器失败,请确保服务器已启动", e);
|
||||
}
|
||||
}
|
||||
|
||||
// 资源释放
|
||||
@Override
|
||||
public void close() {
|
||||
executor.shutdown();
|
||||
}
|
||||
|
||||
// 程序入口
|
||||
public static void main(String[] args) {
|
||||
try (LogProcessor processor = new LogProcessor()) {
|
||||
processor.process();
|
||||
}
|
||||
}
|
||||
}
|
||||
42
day02/src/com/inmind/student/罗康凯2/LogServer.java
Normal file
42
day02/src/com/inmind/student/罗康凯2/LogServer.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package com.inmind.student.罗康凯2;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class LogServer {
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(8080)) {
|
||||
System.out.println("服务器已启动,等待客户端连接...");
|
||||
|
||||
while (true) {
|
||||
try (Socket socket = serverSocket.accept();
|
||||
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
|
||||
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
|
||||
System.out.println("客户端已连接: " + socket.getInetAddress());
|
||||
// 接收客户端数据
|
||||
Map<String, Long> levelCount = (Map<String, Long>) in.readObject();
|
||||
Map<String, Long> moduleErrorCount = (Map<String, Long>) in.readObject();
|
||||
List<Log> earliestLogs = (List<Log>) in.readObject();
|
||||
|
||||
// 打印统计结果
|
||||
System.out.println("\n=== 接收到的统计结果 ===");
|
||||
System.out.println("按级别统计: " + levelCount);
|
||||
System.out.println("按模块错误统计: " + moduleErrorCount);
|
||||
System.out.println("最早的3条日志:");
|
||||
earliestLogs.forEach(log -> System.out.printf(
|
||||
"[%d] %s %s: %s%n",
|
||||
log.getTimestamp(), log.getLevel(), log.getModule(), log.getContent()));
|
||||
|
||||
// 发送响应
|
||||
out.println("上报成功");
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理客户端请求时出错: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
39
day02/src/com/inmind/student/罗康凯2/LogServer2.java
Normal file
39
day02/src/com/inmind/student/罗康凯2/LogServer2.java
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.inmind.student.罗康凯2;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
public class LogServer2 {
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(8080)) {
|
||||
System.out.println("服务器已启动,监听端口8080...");
|
||||
|
||||
while (true) {
|
||||
try (Socket socket = serverSocket.accept();
|
||||
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
|
||||
PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) {
|
||||
|
||||
Stats stats = (Stats) in.readObject();
|
||||
printStats(stats);
|
||||
out.println("上报成功");
|
||||
} catch (Exception e) {
|
||||
System.err.println("处理客户端请求异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 打印统计结果
|
||||
private static void printStats(Stats stats) {
|
||||
System.out.println("\n=== 接收到统计结果 ===");
|
||||
System.out.println("级别统计: " + stats.getLevelCount());
|
||||
System.out.println("模块错误统计: " + stats.getModuleErrorCount());
|
||||
System.out.println("最早3条日志:");
|
||||
stats.getEarliestLogs().forEach(log ->
|
||||
System.out.printf("[%d] %s-%s: %s%n",
|
||||
log.getTimestamp(), log.getLevel(), log.getModule(), log.getContent())
|
||||
);
|
||||
}
|
||||
}
|
||||
23
day02/src/com/inmind/student/罗康凯2/Stats.java
Normal file
23
day02/src/com/inmind/student/罗康凯2/Stats.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package com.inmind.student.罗康凯2;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// 统计结果封装类
|
||||
public class Stats implements Serializable {
|
||||
private final Map<String, Long> levelCount;
|
||||
private final Map<String, Long> moduleErrorCount;
|
||||
private final List<Log> earliestLogs;
|
||||
|
||||
public Stats(Map<String, Long> levelCount, Map<String, Long> moduleErrorCount, List<Log> earliestLogs) {
|
||||
this.levelCount = levelCount;
|
||||
this.moduleErrorCount = moduleErrorCount;
|
||||
this.earliestLogs = earliestLogs;
|
||||
}
|
||||
|
||||
// Getter方法
|
||||
public Map<String, Long> getLevelCount() { return levelCount; }
|
||||
public Map<String, Long> getModuleErrorCount() { return moduleErrorCount; }
|
||||
public List<Log> getEarliestLogs() { return earliestLogs; }
|
||||
}
|
||||
37
day02/src/com/inmind/student/金雯欣/Log.java
Normal file
37
day02/src/com/inmind/student/金雯欣/Log.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.inmind.student.金雯欣;
|
||||
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
// 日志时间戳(毫秒级)
|
||||
private final long timestamp;
|
||||
// 日志级别(如 ERROR、INFO 等)
|
||||
private final String level;
|
||||
// 日志所属模块(如 Payment、User 等)
|
||||
private final String module;
|
||||
// 日志具体内容
|
||||
private final String content;
|
||||
|
||||
// 带参构造方法
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
// Getter 方法(日志属性创建后不可修改,无需 Setter)
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
|
||||
// 重写 toString,方便日志内容打印(格式:[时间戳] 级别 模块: 内容)
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + timestamp + "] " + level + " " + module + ": " + content;
|
||||
}
|
||||
}
|
||||
|
||||
159
day02/src/com/inmind/student/金雯欣/LogAnalyzer.java
Normal file
159
day02/src/com/inmind/student/金雯欣/LogAnalyzer.java
Normal file
@@ -0,0 +1,159 @@
|
||||
package com.inmind.student.金雯欣;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class LogAnalyzer {
|
||||
// 日志文件目录(题目要求:D:\\io_test)
|
||||
private static final String LOG_DIR = "D:\\io_test";
|
||||
// 服务器地址(本地测试)
|
||||
private static final String SERVER_HOST = "127.0.0.1";
|
||||
// 服务器端口
|
||||
private static final int SERVER_PORT = 8080;
|
||||
|
||||
// 存储解析后的日志(通过 synchronized 保证线程安全)
|
||||
private List<Log> logs = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzer analyzer = new LogAnalyzer();
|
||||
try {
|
||||
// 1. 多线程读取并解析日志
|
||||
analyzer.readAndParseLogs();
|
||||
// 2. 统计分析
|
||||
Map<String, Long> levelStats = analyzer.analyzeByLevel();
|
||||
Map<String, Long> moduleErrorStats = analyzer.analyzeErrorByModule();
|
||||
List<Log> top3Logs = analyzer.findTop3EarlyLogs();
|
||||
|
||||
// 3. 网络上报
|
||||
analyzer.reportToServer(levelStats, moduleErrorStats, top3Logs);
|
||||
|
||||
System.out.println("日志分析和上报完成");
|
||||
} catch (IOException e) {
|
||||
System.err.println("客户端执行异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 多线程读取并解析日志文件(使用线程池)
|
||||
private void readAndParseLogs() throws IOException {
|
||||
File dir = new File(LOG_DIR);
|
||||
if (!dir.exists() || !dir.isDirectory()) {
|
||||
throw new IOException("日志目录不存在: " + LOG_DIR);
|
||||
}
|
||||
|
||||
// 筛选 .log 后缀的文件
|
||||
File[] logFiles = dir.listFiles(file -> file.getName().endsWith(".log"));
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.err.println("目录中无 .log 日志文件: " + LOG_DIR);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建线程池(题目要求:Executors.newFixedThreadPool(5))
|
||||
ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
for (File file : logFiles) {
|
||||
// 提交文件解析任务
|
||||
executor.submit(() -> parseLogFile(file));
|
||||
}
|
||||
// 关闭线程池(不再接受新任务,等待现有任务完成)
|
||||
executor.shutdown();
|
||||
while (!executor.isTerminated()) {
|
||||
// 等待任务完成
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
System.out.println("日志解析完成,共解析 " + logs.size() + " 条日志");
|
||||
}
|
||||
|
||||
// 解析单个日志文件(线程任务)
|
||||
private void parseLogFile(File file) {
|
||||
// try-with-resources 自动关闭流
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
int lineNum = 0;
|
||||
// 正则匹配日志格式:时间戳,级别,模块,内容(内容可能包含逗号,需限制分割)
|
||||
Pattern pattern = Pattern.compile("^\\d+,\\w+,\\w+,.*$");
|
||||
while ((line = br.readLine()) != null) {
|
||||
lineNum++;
|
||||
try {
|
||||
if (!pattern.matcher(line).matches()) {
|
||||
throw new IllegalArgumentException("日志格式错误");
|
||||
}
|
||||
// 分割日志(限制分割为4部分,保留内容中的逗号)
|
||||
String[] parts = line.split(",", 4);
|
||||
if (parts.length != 4) {
|
||||
throw new IllegalArgumentException("日志字段数量错误");
|
||||
}
|
||||
|
||||
long timestamp = Long.parseLong(parts[0]);
|
||||
String level = parts[1].trim();
|
||||
String module = parts[2].trim();
|
||||
String content = parts[3].trim();
|
||||
|
||||
// 线程安全地添加到 logs(synchronized 保证)
|
||||
synchronized (this) {
|
||||
logs.add(new Log(timestamp, level, module, content));
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.err.println("解析文件 " + file.getName()
|
||||
+ " 第" + lineNum + "行失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
System.out.println("解析完成: " + file.getName() + ",共 " + lineNum + " 行");
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件 " + file.getName() + " 失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 按级别统计日志数量(Stream + Lambda)
|
||||
private Map<String, Long> analyzeByLevel() {
|
||||
return logs.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
}
|
||||
|
||||
// 按模块统计错误日志(级别为 ERROR)数量(Stream + Lambda)
|
||||
private Map<String, Long> analyzeErrorByModule() {
|
||||
return logs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
}
|
||||
|
||||
// 找出时间戳最早的3条日志
|
||||
private List<Log> findTop3EarlyLogs() {
|
||||
return logs.stream()
|
||||
.sorted(Comparator.comparingLong(Log::getTimestamp))
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 通过 Socket 上报统计结果到服务器
|
||||
private void reportToServer(Map<String, Long> levelStats,
|
||||
Map<String, Long> moduleErrorStats,
|
||||
List<Log> top3Logs) throws IOException {
|
||||
// try-with-resources 自动关闭 Socket
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
|
||||
|
||||
// 发送统计结果
|
||||
oos.writeObject(levelStats);
|
||||
oos.writeObject(moduleErrorStats);
|
||||
oos.writeObject(top3Logs);
|
||||
|
||||
// 接收响应
|
||||
String response = (String) new java.io.ObjectInputStream(socket.getInputStream()).readObject();
|
||||
System.out.println("服务器响应: " + response);
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("解析服务器响应异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
66
day02/src/com/inmind/student/金雯欣/LogServer.java
Normal file
66
day02/src/com/inmind/student/金雯欣/LogServer.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package com.inmind.student.金雯欣;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class LogServer {
|
||||
// 服务器监听端口
|
||||
private static final int PORT = 8080;
|
||||
|
||||
public static void main(String[] args) {
|
||||
// try-with-resources 自动关闭 ServerSocket
|
||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||
System.out.println("服务器启动,监听端口: " + PORT);
|
||||
while (true) {
|
||||
// 等待客户端连接
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
System.out.println("客户端连接成功: " + clientSocket.getInetAddress());
|
||||
|
||||
// 处理客户端连接(try-with-resources 处理流)
|
||||
try (ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream())) {
|
||||
|
||||
// 接收统计结果
|
||||
Map<String, Long> levelStats = (Map<String, Long>) ois.readObject();
|
||||
Map<String, Long> moduleErrorStats = (Map<String, Long>) ois.readObject();
|
||||
List<Log> top3Logs = (List<Log>) ois.readObject();
|
||||
|
||||
// 打印统计结果
|
||||
printStats(levelStats, moduleErrorStats, top3Logs);
|
||||
|
||||
// 返回响应
|
||||
oos.writeObject("上报成功");
|
||||
} catch (ClassNotFoundException | IOException e) {
|
||||
System.err.println("服务器处理客户端数据异常: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("服务器启动失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 按格式打印统计结果到控制台
|
||||
private static void printStats(Map<String, Long> levelStats,
|
||||
Map<String, Long> moduleErrorStats,
|
||||
List<Log> top3Logs) {
|
||||
System.out.println("\n===== 日志统计结果 =====");
|
||||
// 打印级别统计
|
||||
System.out.println("1. 按级别统计:");
|
||||
levelStats.forEach((level, count) ->
|
||||
System.out.println(level + ": " + count + "条"));
|
||||
|
||||
// 打印模块错误统计
|
||||
System.out.println("\n2. 按模块错误统计:");
|
||||
moduleErrorStats.forEach((module, count) ->
|
||||
System.out.println(module + ": " + count + "条错误"));
|
||||
|
||||
// 打印最早3条日志
|
||||
System.out.println("\n3. 最早的3条日志:");
|
||||
top3Logs.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
38
day02/src/com/inmind/student/陈家芮/Log.java
Normal file
38
day02/src/com/inmind/student/陈家芮/Log.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.inmind.student.陈家芮;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable, Comparable<Log> {
|
||||
private final long timestamp;
|
||||
private final String level;
|
||||
private final String module;
|
||||
private final String content;
|
||||
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public long getTimestamp() { return timestamp; }
|
||||
public String getLevel() { return level; }
|
||||
public String getModule() { return module; }
|
||||
public String getContent() { return content; }
|
||||
|
||||
@Override
|
||||
public int compareTo(Log other) {
|
||||
return Long.compare(this.timestamp, other.timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Log{" +
|
||||
"timestamp=" + timestamp +
|
||||
", level='" + level + '\'' +
|
||||
", module='" + module + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
164
day02/src/com/inmind/student/陈家芮/LogAnalyzer.java
Normal file
164
day02/src/com/inmind/student/陈家芮/LogAnalyzer.java
Normal file
@@ -0,0 +1,164 @@
|
||||
package com.inmind.student.陈家芮;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.regex.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
public class LogAnalyzer {
|
||||
private static final String LOG_DIR = "D:\\io_test";
|
||||
private static final String LOG_FILE_PATTERN = ".*\\.log$";
|
||||
private static final Pattern LOG_LINE_PATTERN =
|
||||
Pattern.compile("^(\\d+),(\\w+),(\\w+),(.*)$");
|
||||
private static final String SERVER_HOST = "localhost";
|
||||
private static final int SERVER_PORT = 8080;
|
||||
|
||||
private final List<Log> allLogs = Collections.synchronizedList(new ArrayList<>());
|
||||
private final ExecutorService executor = Executors.newFixedThreadPool(5);
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzer analyzer = new LogAnalyzer();
|
||||
try {
|
||||
analyzer.processLogs();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error processing logs: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
analyzer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public void processLogs() throws InterruptedException {
|
||||
// 1. 读取并解析日志文件
|
||||
readAndParseLogFiles();
|
||||
|
||||
// 2. 统计分析
|
||||
Map<String, Long> levelCounts = countLogsByLevel();
|
||||
Map<String, Long> moduleErrorCounts = countErrorLogsByModule();
|
||||
List<Log> earliestLogs = findEarliestLogs(3);
|
||||
|
||||
// 3. 打印统计结果(可选)
|
||||
printStatistics(levelCounts, moduleErrorCounts, earliestLogs);
|
||||
|
||||
// 4. 上报结果到服务器
|
||||
reportToServer(levelCounts, moduleErrorCounts, earliestLogs);
|
||||
}
|
||||
|
||||
private void readAndParseLogFiles() throws InterruptedException {
|
||||
try {
|
||||
File[] logFiles = Paths.get(LOG_DIR).toFile()
|
||||
.listFiles((dir, name) -> name.matches(LOG_FILE_PATTERN));
|
||||
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("No log files found in directory: " + LOG_DIR);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Future<?>> futures = new ArrayList<>();
|
||||
for (File file : logFiles) {
|
||||
futures.add(executor.submit(() -> parseLogFile(file)));
|
||||
}
|
||||
|
||||
// 等待所有任务完成
|
||||
for (Future<?> future : futures) {
|
||||
future.get();
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
System.err.println("Error processing log files: " + e.getCause().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void parseLogFile(File file) {
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
try {
|
||||
Matcher matcher = LOG_LINE_PATTERN.matcher(line.trim());
|
||||
if (matcher.matches()) {
|
||||
long timestamp = Long.parseLong(matcher.group(1));
|
||||
String level = matcher.group(2);
|
||||
String module = matcher.group(3);
|
||||
String content = matcher.group(4);
|
||||
allLogs.add(new Log(timestamp, level, module, content));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to parse line: " + line + " in file: " + file.getName());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("Error reading file: " + file.getName() + " - " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Long> countLogsByLevel() {
|
||||
return allLogs.stream()
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
}
|
||||
|
||||
private Map<String, Long> countErrorLogsByModule() {
|
||||
return allLogs.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()))
|
||||
.collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
}
|
||||
|
||||
private List<Log> findEarliestLogs(int count) {
|
||||
return allLogs.stream()
|
||||
.sorted()
|
||||
.limit(count)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void printStatistics(Map<String, Long> levelCounts,
|
||||
Map<String, Long> moduleErrorCounts,
|
||||
List<Log> earliestLogs) {
|
||||
System.out.println("\n=== 日志统计结果 ===");
|
||||
System.out.println("按级别统计:");
|
||||
levelCounts.forEach((level, count) -> System.out.printf("%s: %d%n", level, count));
|
||||
|
||||
System.out.println("\n按模块统计错误日志:");
|
||||
moduleErrorCounts.forEach((module, count) -> System.out.printf("%s: %d%n", module, count));
|
||||
|
||||
System.out.println("\n最早的3条日志:");
|
||||
earliestLogs.forEach(System.out::println);
|
||||
}
|
||||
|
||||
private void reportToServer(Map<String, Long> levelCounts,
|
||||
Map<String, Long> moduleErrorCounts,
|
||||
List<Log> earliestLogs) {
|
||||
try (Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream in = new ObjectInputStream(socket.getInputStream())) {
|
||||
|
||||
// 创建结果对象
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("levelCounts", levelCounts);
|
||||
result.put("moduleErrorCounts", moduleErrorCounts);
|
||||
result.put("earliestLogs", earliestLogs);
|
||||
|
||||
// 发送结果
|
||||
out.writeObject(result);
|
||||
out.flush();
|
||||
|
||||
// 接收服务器响应
|
||||
String response = (String) in.readObject();
|
||||
System.out.println("\n服务器响应: " + response);
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.err.println("Error reporting to server: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
executor.shutdown();
|
||||
try {
|
||||
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
executor.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executor.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
64
day02/src/com/inmind/student/陈家芮/Server.java
Normal file
64
day02/src/com/inmind/student/陈家芮/Server.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package com.inmind.student.陈家芮;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
/**
|
||||
* ClassName:Server
|
||||
*
|
||||
* @author: karoy
|
||||
* @Date: 2025/8/13
|
||||
* @Description:
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class Server {
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(8080)) {
|
||||
System.out.println("日志服务器启动,监听端口 8080...");
|
||||
|
||||
while (true) {
|
||||
try (Socket clientSocket = serverSocket.accept();
|
||||
ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
|
||||
ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream())) {
|
||||
|
||||
System.out.println("\n接收到客户端连接: " + clientSocket.getInetAddress());
|
||||
|
||||
// 接收客户端数据
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> result = (Map<String, Object>) in.readObject();
|
||||
|
||||
// 打印统计结果
|
||||
printResults(result);
|
||||
|
||||
// 发送响应
|
||||
out.writeObject("上报成功");
|
||||
out.flush();
|
||||
} catch (IOException | ClassNotFoundException e) {
|
||||
System.err.println("处理客户端请求时出错: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.err.println("无法启动服务器: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static void printResults(Map<String, Object> result) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Long> levelCounts = (Map<String, Long>) result.get("levelCounts");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Long> moduleErrorCounts = (Map<String, Long>) result.get("moduleErrorCounts");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Log> earliestLogs = (List<Log>) result.get("earliestLogs");
|
||||
|
||||
System.out.println("\n=== 接收到的日志统计 ===");
|
||||
System.out.println("按级别统计:");
|
||||
levelCounts.forEach((level, count) -> System.out.printf("%s: %d%n", level, count));
|
||||
|
||||
System.out.println("\n按模块统计错误日志:");
|
||||
moduleErrorCounts.forEach((module, count) -> System.out.printf("%s: %d%n", module, count));
|
||||
|
||||
System.out.println("\n最早的3条日志:");
|
||||
earliestLogs.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
104
day02/src/com/inmind/student/陈桐/LogAnalyzer.java
Normal file
104
day02/src/com/inmind/student/陈桐/LogAnalyzer.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package com.inmind.student.陈桐;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class LogAnalyzer {
|
||||
//定义日志目录LOG_DIR = "logs/"、服务器地址和端口
|
||||
// 日志目录(确保目录以斜杠结尾,方便拼接文件路径)
|
||||
public static final String LOG_DIR = "E:\\workspace_idea\\Java_Advanced\\Day13_Test\\Log/";
|
||||
|
||||
// 服务器地址(localhost表示本地,可根据需要修改为具体IP)
|
||||
public static final String SERVER_HOST = "localhost";
|
||||
|
||||
// 服务器端口(建议使用1024以上的端口,避免与系统端口冲突)
|
||||
public static final int SERVER_PORT = 8080;
|
||||
|
||||
//声明日志集合private List<Log> logs = new ArrayList<>()(非线程安全,后续通过同步机制保证安全)
|
||||
private List<MyLog> logs = new ArrayList<>();
|
||||
|
||||
|
||||
public void readLogFiles() throws FileNotFoundException, InterruptedException {
|
||||
// 检查日志目录是否存在
|
||||
File logDirectory = new File(LOG_DIR);
|
||||
if (!logDirectory.exists() || !logDirectory.isDirectory()) {
|
||||
throw new FileNotFoundException("日志目录不存在: " + LOG_DIR);
|
||||
}
|
||||
|
||||
// 获取.log后缀的日志文件列表
|
||||
File[] logFiles = logDirectory.listFiles((log, name) ->
|
||||
name.endsWith(".log")
|
||||
);
|
||||
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("日志目录中没有找到.log文件");
|
||||
return;
|
||||
}
|
||||
|
||||
// 存储所有线程的列表
|
||||
List<Thread> threadList = new ArrayList<>();
|
||||
|
||||
// 为每个日志文件创建并启动线程
|
||||
for (File logFile : logFiles) {
|
||||
Thread thread = new Thread(() -> {
|
||||
try {
|
||||
parseLogFile(logFile);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
threadList.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
// 等待所有线程执行完毕
|
||||
for (Thread thread : threadList) {
|
||||
thread.join();
|
||||
}
|
||||
|
||||
System.out.println("所有日志文件解析完成,共解析 " + logFiles.length + " 条日志");
|
||||
}
|
||||
|
||||
private void parseLogFile(File logFile) throws IOException {
|
||||
System.out.println("开始解析日志文件: " + logFile.getName() + ",线程: " + Thread.currentThread().getName());
|
||||
|
||||
// 使用try-with-resources自动关闭资源
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(logFile));
|
||||
Socket socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) {
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
writer.write(line);
|
||||
writer.newLine(); // 确保每行有换行符,便于服务器解析
|
||||
writer.flush(); // 立即发送数据
|
||||
}
|
||||
System.out.println("日志文件解析完成: " + logFile.getName());
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("日志文件不存在: " + logFile.getName() + ",错误: " + e.getMessage());
|
||||
} catch (ConnectException e) {
|
||||
System.err.println("无法连接到服务器 " + SERVER_HOST + ":" + SERVER_PORT + ",错误: " + e.getMessage());
|
||||
} catch (SocketException e) {
|
||||
System.err.println("网络连接异常,文件: " + logFile.getName() + ",错误: " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
System.err.println("IO操作异常,文件: " + logFile.getName() + ",错误: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
LogAnalyzer reader = new LogAnalyzer();
|
||||
try {
|
||||
reader.readLogFiles();
|
||||
} catch (FileNotFoundException e) {
|
||||
System.err.println("错误: " + e.getMessage());
|
||||
} catch (InterruptedException e) {
|
||||
System.err.println("线程等待被中断: " + e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
131
day02/src/com/inmind/student/陈桐/LogServe.java
Normal file
131
day02/src/com/inmind/student/陈桐/LogServe.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package com.inmind.student.陈桐;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
定义服务器端口常量PORT = 8080
|
||||
在main方法中创建ServerSocket,监听指定端口
|
||||
使用while(true)循环持续等待客户端连接
|
||||
客户端连接后,通过ObjectInputStream接收 3 类数据:
|
||||
级别统计 Map(Map<String, Integer>)
|
||||
模块错误统计 Map(Map<String, Integer>)
|
||||
最早的 3 条日志(List<Log>)
|
||||
遍历接收的 Map 和 List,按格式打印统计结果到控制台
|
||||
通过ObjectOutputStream向客户端返回 "上报成功" 响应
|
||||
使用try-with-resources自动关闭ServerSocket、Socket和流资源
|
||||
捕获并处理IOException等异常,确保服务器稳定运行
|
||||
*/
|
||||
public class LogServe {
|
||||
public static void main(String[] args) throws IOException {
|
||||
System.out.println("服务器启动");
|
||||
//在main方法中创建ServerSocket,监听指定端口
|
||||
ServerSocket serverSocket = new ServerSocket(8080);
|
||||
HashMap<String, Integer> levelMap = new HashMap<>();
|
||||
levelMap.put("ERROR", 0);
|
||||
levelMap.put("INFO", 0);
|
||||
levelMap.put("WARNING", 0);
|
||||
levelMap.put("DEBUG", 0);
|
||||
HashMap<String, Integer> errMap = new HashMap<>();
|
||||
errMap.put("SystemModule", 0);
|
||||
errMap.put("PaymentGateway",0);
|
||||
errMap.put("DatabaseModule",0);
|
||||
|
||||
ArrayList<MyLog> list = new ArrayList<>();
|
||||
|
||||
//使用while(true)循环持续等待客户端连接
|
||||
int count = 0;
|
||||
while (true) {
|
||||
try (Socket socket = serverSocket.accept();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
OutputStream os = socket.getOutputStream()) {
|
||||
//客户端连接后,通过ObjectInputStream接收 3 类数据
|
||||
String msg;
|
||||
while ((msg = br.readLine()) != null) {
|
||||
String[] split = msg.split(",");
|
||||
if(split.length != 5 || !levelMap.containsKey(split[1]) || !errMap.containsKey(split[2])){
|
||||
// 创建日志对象
|
||||
MyLog log = new MyLog(Long.parseLong(split[0]), split[1], split[2], split[3]);
|
||||
// 创建level集合
|
||||
getLeveMap(split, levelMap, msg);
|
||||
// 创建err集合
|
||||
getErrMap(split, errMap, msg);
|
||||
list.add(log);
|
||||
}else{
|
||||
throw new IllegalArgumentException("不符合日志格式");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 遍历接收的 Map 和 List,按格式打印统计结果到控制台
|
||||
System.out.println(socket.getLocalAddress()+"已成功连接客户端");
|
||||
System.out.println("======日志统计结果=====");
|
||||
|
||||
System.out.println("1.按级别统计结果");
|
||||
for(Map.Entry<String, Integer> entry: levelMap.entrySet()) {
|
||||
System.out.println(entry.getKey() + " : " + entry.getValue());
|
||||
}
|
||||
|
||||
System.out.println("2.按模块错误统计");
|
||||
for(Map.Entry<String, Integer> entry: errMap.entrySet()) {
|
||||
System.out.println(entry.getKey() + " : " + entry.getValue());
|
||||
}
|
||||
|
||||
System.out.println("3.最早的三条日志");
|
||||
list.sort(new Comparator<MyLog>() {
|
||||
|
||||
@Override
|
||||
public int compare(MyLog o1, MyLog o2) {
|
||||
return Long.compare(o1.getTimestamp(),o2.getTimestamp());
|
||||
}
|
||||
});
|
||||
int count2 = 0;
|
||||
for (MyLog log : list) {
|
||||
if(count2 < 3){
|
||||
System.out.println(log.toString());
|
||||
}
|
||||
count2++;
|
||||
}
|
||||
|
||||
// 通过OutputStream向客户端返回 "上报成功" 响应
|
||||
os.write("上报成功".getBytes());
|
||||
os.flush(); // 确保数据被发送出去
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void getErrMap(String[] split, HashMap<String, Integer> errMap, String msg) {
|
||||
if (split[2].equals("SystemModule")) {
|
||||
errMap.put("SystemModule", errMap.get("SystemModule")+1);
|
||||
}
|
||||
if (split[2].equals("PaymentGateway")) {
|
||||
errMap.put("PaymentGateway", errMap.get("PaymentGateway")+1);
|
||||
}
|
||||
if (split[2].equals("DatabaseModule")) {
|
||||
errMap.put("DatabaseModule", errMap.get("DatabaseModule")+1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void getLeveMap(String[] split, HashMap<String, Integer> levelMap, String msg) {
|
||||
if (split[1].equals("ERROR")) {
|
||||
levelMap.put("ERROR", levelMap.get("ERROR")+1);
|
||||
}else if (split[1].equals("INFO")) {
|
||||
levelMap.put("INFO", levelMap.get("INFO")+1);
|
||||
}else if (split[1].equals("WARNING")) {
|
||||
levelMap.put("WARNING", levelMap.get("WARNING")+1);
|
||||
} else if (split[1].equals("DEBUG")) {
|
||||
levelMap.put("DEBUG", levelMap.get("DEBUG")+1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
54
day02/src/com/inmind/student/陈桐/MyLog.java
Normal file
54
day02/src/com/inmind/student/陈桐/MyLog.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.inmind.student.陈桐;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/*
|
||||
定义Log类,封装日志的核心属性:
|
||||
private long timestamp:日志时间戳(毫秒级)
|
||||
private String level:日志级别(如 ERROR、INFO 等)
|
||||
private String module:日志所属模块(如 Payment、User 等)
|
||||
private String content:日志具体内容
|
||||
提供带参构造方法Log(long timestamp, String level, String module, String content),用于初始化日志对象
|
||||
生成所有属性的getter方法(无需 setter,日志属性创建后不可修改)
|
||||
实现Serializable接口,使对象可通过网络传输
|
||||
重写toString()方法,方便日志内容打印(格式:[时间戳] 级别 模块: 内容)
|
||||
*/
|
||||
public class MyLog implements Serializable {
|
||||
private long timestamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
public MyLog(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MyLog{" +
|
||||
"[时间戳]:" + timestamp +
|
||||
", 级别:'" + level + '\'' +
|
||||
", 模块:'" + module + '\'' +
|
||||
", 内容:'" + content + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
40
day02/src/com/inmind/student/黄越/Log.java
Normal file
40
day02/src/com/inmind/student/黄越/Log.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package com.inmind.student.黄越;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Log implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private long timestamp;
|
||||
private String level;
|
||||
private String module;
|
||||
private String content;
|
||||
|
||||
public Log(long timestamp, String level, String module, String content) {
|
||||
}
|
||||
|
||||
public void Log(long timestamp, String level, String module, String content) {
|
||||
this.timestamp = timestamp;
|
||||
this.level = level;
|
||||
this.module = module;
|
||||
this.content = content;
|
||||
}
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[" + timestamp + "] " + level + " " + module + ": " + content;
|
||||
}
|
||||
}
|
||||
120
day02/src/com/inmind/student/黄越/LogClient.java
Normal file
120
day02/src/com/inmind/student/黄越/LogClient.java
Normal file
@@ -0,0 +1,120 @@
|
||||
package com.inmind.student.黄越;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LogClient {
|
||||
private static final Pattern LOG_PATTERN = Pattern.compile("(\\d+),(\\w+),(\\w+),(.*)");
|
||||
private static final List<Log> logList = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final String DIR_PATH = "D:\\io_test";
|
||||
|
||||
public static void main(String[] args) {
|
||||
File dir = new File(DIR_PATH);
|
||||
if (!dir.exists() || !dir.isDirectory()) {
|
||||
System.out.println("Directory " + DIR_PATH + " does not exist or is not a directory");
|
||||
return;
|
||||
}
|
||||
|
||||
File[] logFiles = dir.listFiles((file) -> file.getName().endsWith(".log"));
|
||||
if (logFiles == null || logFiles.length == 0) {
|
||||
System.out.println("No .log files found in " + DIR_PATH);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("找到 " + logFiles.length + " 个日志文件,开始解析...");
|
||||
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(5);
|
||||
List<Thread> threads = new ArrayList<>();
|
||||
for (File file : logFiles) {
|
||||
Thread thread = new Thread(() -> readAndParseLogFile(file));
|
||||
threads.add(thread);
|
||||
executorService.submit(thread);
|
||||
}
|
||||
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
System.out.println("Thread join interrupted: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
executorService.shutdown();
|
||||
try {
|
||||
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executorService.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
System.out.println("日志解析完成,共解析 " + logList.size() + " 条日志");
|
||||
|
||||
// 统计分析
|
||||
Map<String, Long> levelCountMap = logList.stream()
|
||||
.filter(log -> log.getLevel() != null)
|
||||
.collect(Collectors.groupingBy(Log::getLevel, Collectors.counting()));
|
||||
|
||||
Map<String, Long> errorModuleCountMap = logList.stream()
|
||||
.filter(log -> "ERROR".equals(log.getLevel()) && log.getModule() != null)
|
||||
.collect(Collectors.groupingBy(Log::getModule, Collectors.counting()));
|
||||
|
||||
Log[] earliestLogs = logList.stream()
|
||||
.sorted(Comparator.comparingLong(Log::getTimestamp))
|
||||
.limit(3)
|
||||
.toArray(Log[]::new);
|
||||
|
||||
// 网络上报
|
||||
try (Socket socket = new Socket("localhost", 8080);
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
|
||||
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream())) {
|
||||
oos.writeObject(levelCountMap);
|
||||
oos.writeObject(errorModuleCountMap);
|
||||
oos.writeObject(earliestLogs);
|
||||
|
||||
String response = (String) ois.readObject();
|
||||
System.out.println("服务器响应:" + response);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Client socket error: " + e.getMessage());
|
||||
}
|
||||
|
||||
System.out.println("日志分析和上报完成");
|
||||
}
|
||||
|
||||
private static void readAndParseLogFile(File file) {
|
||||
try (BufferedReader br = Files.newBufferedReader(Paths.get(file.getPath()))) {
|
||||
String line;
|
||||
int lineCount = 0;
|
||||
while ((line = br.readLine()) != null) {
|
||||
lineCount++;
|
||||
Matcher matcher = LOG_PATTERN.matcher(line);
|
||||
if (matcher.matches()) {
|
||||
long timestamp = Long.parseLong(matcher.group(1));
|
||||
String level = matcher.group(2);
|
||||
String module = matcher.group(3);
|
||||
String content = matcher.group(4);
|
||||
logList.add(new Log(timestamp, level, module, content));
|
||||
} else {
|
||||
System.out.println("Parse failed for line: " + line + " in file: " + file.getName());
|
||||
}
|
||||
}
|
||||
System.out.println("解析完成:" + file.getName() + ",共 " + lineCount + " 行");
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error reading file " + file.getName() + ": " + e.getMessage());
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Number format error when parsing timestamp in file " + file.getName() + ": " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Unexpected error when parsing file " + file.getName() + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
46
day02/src/com/inmind/student/黄越/LogServer.java
Normal file
46
day02/src/com/inmind/student/黄越/LogServer.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package com.inmind.student.黄越;
|
||||
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
|
||||
public class LogServer {
|
||||
public static void main(String[] args) {
|
||||
try (ServerSocket serverSocket = new ServerSocket(8080)) {
|
||||
System.out.println("LogServer started, listening on port 8080");
|
||||
while (true) {
|
||||
Socket socket = serverSocket.accept();
|
||||
try (ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
|
||||
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {
|
||||
Map<String, Long> levelCountMap = (Map<String, Long>) ois.readObject();
|
||||
Map<String, Long> errorModuleCountMap = (Map<String, Long>) ois.readObject();
|
||||
Log[] earliestLogs = (Log[]) ois.readObject();
|
||||
|
||||
System.out.println("1. 按级别统计:");
|
||||
levelCountMap.forEach((level, count) -> {
|
||||
String color = "ERROR".equals(level) ? "\u001B[43m" : ("WARNING".equals(level) ? "\u001B[43m" : "\u001B[37m");
|
||||
System.out.println(color + level + ": " + count + "条" + "\u001B[0m");
|
||||
});
|
||||
|
||||
System.out.println("\n2. 按模块错误统计:");
|
||||
errorModuleCountMap.forEach((module, count) -> System.out.println(module + ": " + count + "条错误"));
|
||||
|
||||
System.out.println("\n3. 最早的3条日志:");
|
||||
for (int i = 0; i < earliestLogs.length; i++) {
|
||||
Log log = earliestLogs[i];
|
||||
String color = i == 1 ? "\u001B[43m" : (i == 2 ? "\u001B[43m" : "\u001B[37m");
|
||||
System.out.println(color + log + "\u001B[0m");
|
||||
}
|
||||
|
||||
oos.writeObject("上报成功");
|
||||
} catch (Exception e) {
|
||||
System.out.println("Server error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Server socket error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user