diff --git a/README.md b/README.md deleted file mode 100644 index 8a4459c..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# partner_project - diff --git a/src/auth/User.java b/src/auth/User.java new file mode 100644 index 0000000..fdb6079 --- /dev/null +++ b/src/auth/User.java @@ -0,0 +1,20 @@ +package auth; + +public class User { + private String username; + private String password; + private String type; + private String email; + + public User(String username, String password, String type, String email) { + this.username = username; + this.password = password; + this.type = type; + this.email = email; + } + + public String getUsername() { return username; } + public String getPassword() { return password; } + public String getType() { return type; } + public String getEmail() { return email; } +} diff --git a/src/auth/UserManager.java b/src/auth/UserManager.java new file mode 100644 index 0000000..f2efced --- /dev/null +++ b/src/auth/UserManager.java @@ -0,0 +1,13 @@ +package auth; + +public class UserManager { + private final AuthService authService; + + public UserManager() { + this.authService = new AuthService(); + } + + public User login(String username, String password) { + return authService.login(username, password); + } +} diff --git a/src/generator/HighGenerator.java b/src/generator/HighGenerator.java new file mode 100644 index 0000000..905edf1 --- /dev/null +++ b/src/generator/HighGenerator.java @@ -0,0 +1,28 @@ +package generator; + +import util.ExpressionUtils; +import java.util.*; + +public class HighGenerator implements ProblemGenerator { + @Override + public List generateProblems(int count) { + List problems = new ArrayList<>(); + int attempts = 0; + final int maxAttempts = count * 3; // 最多尝试3倍数量 + + while (problems.size() < count && attempts < maxAttempts) { + Problem problem = ExpressionUtils.generateHighExpr(); + if (problem != null) { + problems.add(problem); + } + attempts++; + } + + // 如果无法生成足够题目,用简单题目填充 + while (problems.size() < count) { + problems.add(ExpressionUtils.createProblem("sin(30) + " + (problems.size() + 1))); + } + + return problems; + } +} \ No newline at end of file diff --git a/src/generator/MiddleGenerator.java b/src/generator/MiddleGenerator.java new file mode 100644 index 0000000..1815304 --- /dev/null +++ b/src/generator/MiddleGenerator.java @@ -0,0 +1,15 @@ +package generator; + +import util.ExpressionUtils; +import java.util.*; + +public class MiddleGenerator implements ProblemGenerator { + @Override + public List generateProblems(int count) { + List problems = new ArrayList<>(); + for (int i = 0; i < count; i++) { + problems.add(ExpressionUtils.generateMiddleExpr()); + } + return problems; + } +} \ No newline at end of file diff --git a/src/generator/PrimaryGenerator.java b/src/generator/PrimaryGenerator.java new file mode 100644 index 0000000..4609a5a --- /dev/null +++ b/src/generator/PrimaryGenerator.java @@ -0,0 +1,15 @@ +package generator; + +import util.ExpressionUtils; +import java.util.*; + +public class PrimaryGenerator implements ProblemGenerator { + @Override + public List generateProblems(int count) { + List problems = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + problems.add( ExpressionUtils.generatePrimaryExpr()); + } + return problems; + } +} \ No newline at end of file diff --git a/src/generator/Problem.java b/src/generator/Problem.java new file mode 100644 index 0000000..bbf5127 --- /dev/null +++ b/src/generator/Problem.java @@ -0,0 +1,61 @@ +package generator; + +import java.util.List; +import java.util.Collections; + +public class Problem { + private final String expression; + private final double result; + private final List options; + private final String correctAnswerOption; + + public Problem(String expression, double result, List options, + String correctAnswerOption) { + this.expression = expression; + this.result = result; + this.options = options; + this.correctAnswerOption = correctAnswerOption; + } + + public String getQuestionText() { + return "计算: " + expression + " = ?"; + } + + public String getExpression() { + return expression; + } + + public List getOptions() { + return Collections.unmodifiableList(options); + } + + public String getCorrectAnswerOption() { + return formatResult(result); + } + + private String formatResult(double result) { + if (Double.isNaN(result)) { + return "Error"; + } + if (Math.abs(result - Math.round(result)) < 0.0001) { + return String.valueOf((int) Math.round(result)); + } + return String.format("%.2f", result); + } + + public double getResult() { + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getQuestionText()).append("\n"); + char optionChar = 'A'; + for (String option : options) { + sb.append(optionChar++).append(". ").append(option).append(" "); + } + sb.append("\n正确答案: ").append(correctAnswerOption); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/generator/ProblemGenerator.java b/src/generator/ProblemGenerator.java new file mode 100644 index 0000000..d9a821e --- /dev/null +++ b/src/generator/ProblemGenerator.java @@ -0,0 +1,7 @@ +package generator; + +import java.util.List; + +public interface ProblemGenerator { + List generateProblems(int count); +} diff --git a/src/service/ExamService.java b/src/service/ExamService.java new file mode 100644 index 0000000..ff1e339 --- /dev/null +++ b/src/service/ExamService.java @@ -0,0 +1,109 @@ +package service; + +import auth.User; +import generator.Problem; +import generator.ProblemGenerator; +import generator.PrimaryGenerator; +import generator.MiddleGenerator; +import generator.HighGenerator; +import util.FileUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class ExamService { + + public ProblemGenerator getGenerator(String type) { + switch (type) { + case "小学": return new PrimaryGenerator(); + case "初中": return new MiddleGenerator(); + case "高中": return new HighGenerator(); + default: return null; + } + } + + private Problem generateUniqueProblem(ProblemGenerator generator, + Set historyExpressions) { + int attempts = 0; + final int maxAttemptsPerProblem = 1000; + + while (attempts < maxAttemptsPerProblem) { + Problem problem = generator.generateProblems(1).get(0); + // 查重基于题干 (表达式字符串) + if (!historyExpressions.contains(problem.getExpression())) { + historyExpressions.add(problem.getExpression()); + return problem; + } + attempts++; + } + return null; + } + + // R5: 生成一张唯一试卷,并将其保存到用户的历史记录中。 + public List generateExam(User currentUser, int count) { + if (count < 10 || count > 30) { + throw new IllegalArgumentException("题目数量必须在 10 到 30 之间"); + } + + ProblemGenerator generator = getGenerator(currentUser.getType()); + if (generator == null) { + System.err.println("错误: 无法获取题目生成器,用户类型: " + currentUser.getType()); + return new ArrayList<>(); + } + + Set historyExpressions = FileUtils.loadHistory(currentUser.getUsername()); + List problems = new ArrayList<>(); + + for(int i = 0; i < count; i++) { + Problem problem = generateUniqueProblem(generator, historyExpressions); + if (problem != null) { + problems.add(problem); + } else { + System.err.println("警告: 无法生成足够数量的唯一题目。已生成: " + problems.size() + " 题"); + break; + } + } + + if (!problems.isEmpty()) { + FileUtils.saveProblems(currentUser.getUsername(), problems); + } else { + System.err.println("错误: 未能生成任何题目"); + } + + return problems; + } + + // 将这个私有方法改为公共方法,以便在其他类中调用 + public boolean isAnswerCorrect(Problem problem, String userAnswer) { + if (userAnswer == null || problem.getCorrectAnswerOption() == null) { + return false; + } + + boolean isCorrect = userAnswer.trim().equalsIgnoreCase(problem.getCorrectAnswerOption().trim()); + return isCorrect; + } + + // R6: 根据答对的百分比计算分数。 + public int calculateScore(List problems, List answers) { + if (problems == null || answers == null || + problems.size() != answers.size() || + problems.isEmpty()) { + System.err.println("评分错误: 题目和答案数量不匹配"); + return 0; + } + + int correctCount = 0; + for (int i = 0; i < problems.size(); i++) { + Problem problem = problems.get(i); + String userAnswer = answers.get(i); + + if (isAnswerCorrect(problem, userAnswer)) { + correctCount++; + } + } + + double score = ((double) correctCount / problems.size()) * 100; + int finalScore = (int) Math.round(score); + return finalScore; + } +} \ No newline at end of file diff --git a/src/util/EmailService.java b/src/util/EmailService.java new file mode 100644 index 0000000..1535aab --- /dev/null +++ b/src/util/EmailService.java @@ -0,0 +1,69 @@ +package util; + +import java.util.Properties; +import java.util.Random; +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; + +public class EmailService { + // 邮件配置:请修改此处或设置环境变量 + private static final String SENDER_EMAIL = "2810672597@qq.com"; + private static final String SENDER_PASSWORD =("acyhhpwgcqkqdgff"); + private static final String SMTP_HOST = "smtp.qq.com"; // 例如: smtp.gmail.com + private static final String SMTP_PORT = "587"; // 或 465 (SSL) + private static final String SUBJECT = "数学学习软件注册验证码"; + + public String generateVerificationCode() { + Random rand = new Random(); + return String.format("%06d", rand.nextInt(1000000)); + } + + private Properties getMailProperties() { + Properties props = new Properties(); + props.put("mail.smtp.auth", "true"); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.host", SMTP_HOST); + props.put("mail.smtp.port", SMTP_PORT); + return props; + } + + private Message createMessage(Session session, String recipientEmail, + String code) throws MessagingException { + Message message = new MimeMessage(session); + message.setFrom(new InternetAddress(SENDER_EMAIL)); + message.setRecipients( + Message.RecipientType.TO, + InternetAddress.parse(recipientEmail) + ); + message.setSubject(SUBJECT); + message.setText("您的注册验证码是: " + code + + "\n\n请在应用中输入此代码完成注册。"); + return message; + } + + // R2: 实际发送验证邮件 + public boolean sendVerificationEmail(String recipientEmail, String code) { + if (SENDER_EMAIL == null || SENDER_PASSWORD == null) { + System.err.println("错误: 邮件发送凭证未设置。"); + return false; + } + + Session session = Session.getInstance(getMailProperties(), new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(SENDER_EMAIL, SENDER_PASSWORD); + } + }); + + try { + Message message = createMessage(session, recipientEmail, code); + Transport.send(message); + return true; + + } catch (MessagingException e) { + System.err.println("邮件发送失败: " + e.getMessage()); + return false; + } + } +} diff --git a/src/util/ExpressionUtils.java b/src/util/ExpressionUtils.java new file mode 100644 index 0000000..02d59a1 --- /dev/null +++ b/src/util/ExpressionUtils.java @@ -0,0 +1,358 @@ +package util; + +import generator.Problem; + +import java.util.*; + +public class ExpressionUtils { + private static Random rand = new Random(); + + private static final String[] OPS_PRIMARY = {"+", "-", "*", "/"}; + private static final String[] OPS_MIDDLE = {"+", "-", "*", "/"}; + //private static final String[] OPS_HIGH = {"+", "-", "*", "/", "^2", "sqrt"}; + + + public static String randomNumber() { + return String.valueOf(rand.nextInt(100) + 1); + } + + // --- 表达式求解和选项生成辅助方法 --- + + public static double solveExpression(String expr) { + // 预处理表达式,确保格式正确 + String parsableExpr = expr + .replaceAll("(\\d+|\\([^)]+\\))\\^2", "pow($1, 2)") // 处理平方 + .replaceAll("sqrt\\s+(\\d+)", "sqrt($1)") // 处理缺少括号的sqrt + .replaceAll("\\s+", " "); // 标准化空格 + + try { + return new Object() { + int pos = -1, ch; + + void nextChar() { + ch = (++pos < parsableExpr.length()) ? parsableExpr.charAt(pos) : -1; + } + + boolean eat(int charToEat) { + while (ch == ' ') nextChar(); + if (ch == charToEat) { + nextChar(); + return true; + } + return false; + } + + double parse() { + nextChar(); + double x = parseExpression(); + if (pos < parsableExpr.length()) throw new RuntimeException("Unexpected: " + (char) ch); + return x; + } + + double parseExpression() { + double x = parseTerm(); + for (; ; ) { + if (eat('+')) x += parseTerm(); // addition + else if (eat('-')) x -= parseTerm(); // subtraction + else return x; + } + } + + double parseTerm() { + double x = parseFactor(); + for (; ; ) { + if (eat('*')) x *= parseFactor(); // multiplication + else if (eat('/')) { // division + double divisor = parseFactor(); + if (divisor == 0) throw new ArithmeticException("Division by zero"); + x /= divisor; + } else return x; + } + } + + double parseFactor() { + if (eat('+')) return parseFactor(); // unary plus + if (eat('-')) return -parseFactor(); // unary minus + + double x; + int startPos = this.pos; + if (eat('(')) { // parentheses + x = parseExpression(); + eat(')'); + } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers + while ((ch >= '0' && ch <= '9') || ch == '.') nextChar(); + x = Double.parseDouble(parsableExpr.substring(startPos, this.pos)); + } else if (ch >= 'a' && ch <= 'z') { // functions + while (ch >= 'a' && ch <= 'z') nextChar(); + String func = parsableExpr.substring(startPos, this.pos); + x = parseFactor(); + switch (func) { + case "sqrt": + x = Math.sqrt(x); + break; + case "sin": + x = Math.sin(Math.toRadians(x)); + break; + case "cos": + x = Math.cos(Math.toRadians(x)); + break; + case "tan": + x = Math.tan(Math.toRadians(x)); + break; + case "pow": + eat(','); + double y = parseExpression(); + x = Math.pow(x, y); + eat(')'); + break; + default: + throw new RuntimeException("Unknown function: " + func); + } + } else { + throw new RuntimeException("Unexpected: " + (char) ch); + } + + return x; + } + }.parse(); + } catch (Exception e) { + System.err.println("Error parsing expression: '" + expr + "'. Parsable version: '" + parsableExpr + "'. Error: " + e.getMessage()); + return Double.NaN; + } + } + + + private static String formatResult(double result) { + if (Double.isNaN(result)) { + return "Error"; + } + if (Math.abs(result - Math.round(result)) < 0.0001) { + return String.valueOf((int) Math.round(result)); + } + return String.format("%.2f", result); + } + + /** + * MODIFICATION: 确保为整数答案生成整数干扰项 + */ + private static String generateDistractor(double correctResult, List existingOptions) { + if (Double.isNaN(correctResult)) { + return String.valueOf(rand.nextInt(100)); + } + + // 检查正确答案是否为整数 + boolean isIntegerResult = Math.abs(correctResult - Math.round(correctResult)) < 0.0001; + + double distractor; + String distractorStr; + + do { + if (isIntegerResult) { + // 生成一个整数干扰项 + int offset = rand.nextInt(20) + 1; // 扩大随机范围以避免重复 + distractor = rand.nextBoolean() ? Math.round(correctResult) + offset : Math.round(correctResult) - offset; + // 确保干扰项不为负数 + if (distractor < 0) { + distractor = Math.round(correctResult) + offset; + } + } else { + // 答案是小数,则生成小数干扰项 + distractor = correctResult + + (rand.nextInt(10) + 1) * (rand.nextBoolean() ? 1 : -1) + + (rand.nextDouble() * 0.9); + } + distractorStr = formatResult(distractor); + } while (existingOptions.contains(distractorStr)); // 确保选项不重复 + return distractorStr; + } + + + public static List generateOptions(double correctResult) { + List options = new ArrayList<>(); + options.add(formatResult(correctResult)); + + for (int i = 0; i < 3; i++) { + options.add(generateDistractor(correctResult, options)); + } + + Collections.shuffle(options); + return options; + } + + public static Problem createProblem(String expression) { + double result = solveExpression(expression); + + // 如果解析失败,返回null,让调用者重新生成 + if (Double.isNaN(result)) { + return null; + } + + String correctAnswerOption = formatResult(result); + List options = generateOptions(result); + return new Problem(expression, result, options, correctAnswerOption); + } + + // --- 题目生成方法 --- + + private static int getDivisor(int dividend) { + List divisors = new ArrayList<>(); + for (int j = 1; j <= dividend; j++) { + if (dividend % j == 0) { + divisors.add(j); + } + } + return divisors.get(rand.nextInt(divisors.size())); + } + + /** + * MODIFICATION: 增加答案非负、括号数量和操作数关联的逻辑 + */ + public static Problem generatePrimaryExpr() { + Problem problem; + double result; + + do { + // 生成 2 到 4 个操作数 + int operands = rand.nextInt(3) + 2; + List parts = new ArrayList<>(); + + for (int i = 0; i < operands; i++) { + if (i > 0) { + parts.add(OPS_PRIMARY[rand.nextInt(OPS_PRIMARY.length)]); + } + + // 仅当操作数 >= 3 时,才有可能生成括号 + if (operands >= 3 && rand.nextBoolean() && i < operands - 1) { + int num1 = rand.nextInt(50) + 1; + String innerOp = OPS_PRIMARY[rand.nextInt(OPS_PRIMARY.length)]; + int num2; + if (innerOp.equals("/")) { + num2 = getDivisor(num1); + } else { + num2 = rand.nextInt(50) + 1; + } + parts.add("(" + num1 + " " + innerOp + " " + num2 + ")"); + i++; // 括号表达式计为2个操作数 + } else { + int num; + if (i > 0 && parts.get(parts.size() - 1).equals("/")) { + String dividendStr = parts.get(parts.size() - 2); + if (dividendStr.startsWith("(")) { + // 为避免 (a+b)/c 这种复杂情况无法保证整数结果,直接替换运算符 + parts.set(parts.size() - 1, OPS_PRIMARY[rand.nextInt(3)]); // +, -, * + num = rand.nextInt(100) + 1; + } else { + int dividend = Integer.parseInt(dividendStr); + num = getDivisor(dividend); + } + } else { + num = rand.nextInt(100) + 1; + } + parts.add(String.valueOf(num)); + } + } + String expression = String.join(" ", parts); + problem = createProblem(expression); + result = problem.getResult(); + // 循环直到答案为非负整数 + } while (result < 0 || Double.isNaN(result) || Math.abs(result - Math.round(result)) > 0.0001); + + return problem; + } + + + public static Problem generateMiddleExpr() { + int operands = rand.nextInt(5) + 1; + StringBuilder expr = new StringBuilder(); + boolean hasSquareOrSqrt = false; + + for (int i = 0; i < operands; i++) { + if (i > 0) { + expr.append(" ").append(OPS_MIDDLE[rand.nextInt(OPS_MIDDLE.length)]).append(" "); + } + int num = rand.nextInt(100) + 1; + if (!hasSquareOrSqrt && rand.nextBoolean()) { + expr.append(rand.nextBoolean() ? "sqrt(" + num + ")" : num + "^2"); + hasSquareOrSqrt = true; + } else { + expr.append(num); + } + } + + if (!hasSquareOrSqrt) { + expr.append(" + ").append(rand.nextInt(50) + 1).append("^2"); + } + + return createProblem(expr.toString()); + } + + public static Problem generateHighExpr() { + int attempts = 0; + final int maxAttempts = 10; + + while (attempts < maxAttempts) { + int operands = rand.nextInt(3) + 2; // 2-4个操作数 + StringBuilder expr = new StringBuilder(); + boolean hasTrig = false; + + for (int i = 0; i < operands; i++) { + if (i > 0) { + String[] validOps = {"+", "-", "*", "/"}; + String op = validOps[rand.nextInt(validOps.length)]; + expr.append(" ").append(op).append(" "); + } + + // 强制至少有一个操作数是三角函数 + if (!hasTrig && (i == operands - 1 || rand.nextBoolean())) { + String[] funcs = {"sin", "cos", "tan"}; + String func = funcs[rand.nextInt(funcs.length)]; + int angle = rand.nextInt(90) + 1; // 1-90度 + expr.append(func).append("(").append(angle).append(")"); + hasTrig = true; + } else { + // 其他操作数可以是普通数字、平方或开方 + int num = rand.nextInt(100) + 1; + if (rand.nextBoolean() && hasTrig) { // 确保已经有三角函数后再添加其他函数 + if (rand.nextBoolean()) { + expr.append(num).append("^2"); + } else { + expr.append("sqrt(").append(num).append(")"); + } + } else { + expr.append(num); + } + } + } + + // 如果没有三角函数,强制添加一个 + if (!hasTrig) { + String[] funcs = {"sin", "cos", "tan"}; + String func = funcs[rand.nextInt(funcs.length)]; + int angle = rand.nextInt(90) + 1; + + if (rand.nextBoolean()) { + // 在开头添加 + expr.insert(0, func + "(" + angle + ") + "); + } else { + // 在结尾添加 + expr.append(" + ").append(func).append("(").append(angle).append(")"); + } + hasTrig = true; + } + + String expression = expr.toString(); + + // 验证表达式 + Problem problem = createProblem(expression); + if (problem != null) { + return problem; + } + + attempts++; + System.err.println("生成高中题目失败,尝试次数: " + attempts + ", 表达式: " + expression); + } + + return createProblem("sin(30) + cos(60)"); + } + +} \ No newline at end of file diff --git a/src/util/FileUtils.java b/src/util/FileUtils.java new file mode 100644 index 0000000..ce0c7f7 --- /dev/null +++ b/src/util/FileUtils.java @@ -0,0 +1,79 @@ +package util; + +import generator.Problem; +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.*; + +public class FileUtils { + private static final String FOLDER_PATH = "exams/"; + + public static String getUserFolder(String username) { + String folder = FOLDER_PATH + username; + File dir = new File(folder); + if (!dir.exists()) { + dir.mkdirs(); + } + return folder; + } + + private static void processHistoryFile(File file, Set history) { + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line; + while ((line = br.readLine()) != null) { + if (!line.trim().isEmpty() && line.matches("^\\d+\\..*")) { + // 仅提取题干 (表达式字符串) 用于查重 + history.add(line.substring(line.indexOf('.') + 1).trim()); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static Set loadHistory(String username) { + Set history = new HashSet<>(); + File dir = new File(getUserFolder(username)); + File[] files = dir.listFiles((d, name) -> name.endsWith(".txt")); + + if (files != null) { + for (File file : files) { + processHistoryFile(file, history); + } + } + return history; + } + + private static void writeProblem(BufferedWriter bw, int index, Problem problem) throws IOException { + bw.write(index + "." + problem.getExpression()); + bw.newLine(); + + char optionChar = 'A'; + StringBuilder optionsLine = new StringBuilder(); + for (String option : problem.getOptions()) { + optionsLine.append(optionChar++).append(". ").append(option).append(" "); + } + + bw.write(optionsLine.toString().trim()); + bw.newLine(); + bw.write("答案: " + problem.getCorrectAnswerOption()); + bw.newLine(); + bw.newLine(); + } + + public static void saveProblems(String username, List problems) { + String folder = getUserFolder(username); + String timestamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); + String filename = folder + "/" + timestamp + ".txt"; + + try (BufferedWriter bw = new BufferedWriter(new FileWriter(filename))) { + int index = 1; + for (Problem problem : problems) { + writeProblem(bw, index++, problem); + } + System.out.println("卷子已保存到: " + filename); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/util/ModifyUtils.java b/src/util/ModifyUtils.java new file mode 100644 index 0000000..ab02695 --- /dev/null +++ b/src/util/ModifyUtils.java @@ -0,0 +1,76 @@ +package util; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +/** + * Utility class to modify specific fields in user.txt. + * 替换了 ModifyClass.java 和 ModifyPassword.java。 + */ +public class ModifyUtils { + + private static List readAllLines(String filePath, List lines) throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + String line; + while ((line = reader.readLine()) != null) { + lines.add(line); + } + } + return lines; + } + + private static void writeAllLines(String filePath, List lines) throws IOException { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) { + for (String l : lines) { + writer.write(l + System.lineSeparator()); + } + } + } + + private static int findTargetLine(List lines, String targetName) { + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i).trim(); + if (line.isEmpty()) continue; + + String[] parts = line.split("\\s+"); + if (parts.length > 0 && parts[0].equals(targetName)) { + return i; // 0-based index + } + } + return -1; + } + + // 核心逻辑:修改文件中特定用户的某个字段 (0-based) + public static int modifyFileField(String filePath, String targetName, + int fieldIndex, String newValue) { + List lines = new ArrayList<>(); + try { + readAllLines(filePath, lines); + } catch (IOException e) { + System.err.println("读取文件错误: " + e.getMessage()); + return -1; + } + + int idx = findTargetLine(lines, targetName); + if (idx == -1) { + return -1; + } + + String[] parts = lines.get(idx).trim().split("\\s+"); + if (parts.length > fieldIndex) { + parts[fieldIndex] = newValue; + lines.set(idx, String.join(" ", parts)); + try { + writeAllLines(filePath, lines); + return idx + 1; // 返回 1-based 行号 + } catch (IOException e) { + System.err.println("写入文件错误: " + e.getMessage()); + return -1; + } + } else { + System.out.println("目标行元素不足。"); + return -1; + } + } +} \ No newline at end of file