This commit is contained in:
2025-12-21 17:24:54 +08:00
commit e8c50a3d78
660 changed files with 29599 additions and 0 deletions

26
day02/src/Demo.java Normal file
View 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("");
}
}
}

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

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

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

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

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

View 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; }
}

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

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

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

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

View 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");
}
}

View 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 + '\'' +
'}';
}
}

View 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) { /* 忽略关闭异常 */ }
}
}
}
}

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

View 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;
}
}

View 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;
}
}

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

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

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

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

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

View 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;
}
}
}
}

View 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");
}
}

View 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;
}
}

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

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

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

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

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

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

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

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

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

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

View 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; }
}

View 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;
}
}

View 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();
// 线程安全地添加到 logssynchronized 保证)
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());
}
}
}

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

View 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 + '\'' +
'}';
}
}

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

View File

@@ -0,0 +1,64 @@
package com.inmind.student.陈家芮;
import java.io.*;
import java.net.*;
import java.util.*;
/**
* ClassNameServer
*
* @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);
}
}

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

View 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 类数据:
级别统计 MapMap<String, Integer>
模块错误统计 MapMap<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);
}
}
}

View 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 + '\'' +
'}';
}
}

View 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;
}
}

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

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