【问题标题】:How can I update specific parts of a text file in java?如何在 java 中更新文本文件的特定部分?
【发布时间】:2021-06-01 17:18:06
【问题描述】:

这个程序应该接受关于球员姓名、助攻、所玩比赛、得分等的用户输入,并将其打印在 .txt 文件中。当 updateData();方法被调用我希望能够向用户询问玩家姓名以及他们想要更新的数据,然后我应该能够编辑文本的特定部分。我该怎么做呢?

主类

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Scanner;

public class TextReader {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("/Users/Coding/Desktop/myFile.txt").toAbsolutePath();
        try (Scanner scan = new Scanner(System.in);
             BufferedReader fileReader = new BufferedReader(new FileReader(String.valueOf(path)));
             BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {

            Reader reader = new Reader(scan, path, fileWriter, fileReader);
            reader.menu();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}



阅读器类

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;

public class Reader {

    Path path;
    Scanner scan;
    BufferedWriter fileWriter;
    BufferedReader fileReader;


    Reader(Scanner scan, Path path, BufferedWriter fileWriter, BufferedReader fileReader) {

        this.scan = scan;
        this.path = path;
        this.fileWriter = fileWriter;
        this.fileReader = fileReader;
    }

    public void menu() throws IOException {
        String task;

        do{
            System.out.print("What would you like to do today?: ");
            task = scan.nextLine();
            switch (task) {
                case "1":
                    addData();
                    break;
                case "2":
                    updateData();
                    break;
                case "6":
                    System.out.println("Goodbye!");
                    System.exit(0);
            }
        }while(!task.equals("6"));


    }

    void addData() throws IOException {
        boolean cont;

        DateTimeFormatter log = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        LocalDateTime time = LocalDateTime.now();
        String logTime = log.format(time);

        do try {
            System.out.print("Enter Name of Player: ");
            String playerName = scan.nextLine();

            System.out.print("Enter Number of Games Played: ");
            int gamesPlayed = Integer.parseInt(scan.nextLine());

            System.out.print("Enter Number of Goals Made: ");
            int goals = Integer.parseInt(scan.nextLine());

            System.out.print("Enter Number of Assists Made: ");
            int assists = Integer.parseInt(scan.nextLine());

            System.out.print("Enter Number of Points Scored: ");
            int points = Integer.parseInt(scan.nextLine());

            System.out.print("Enter Number of Saves Made: ");
            int saves = Integer.parseInt(scan.nextLine());

            System.out.print("Enter Number of Shots Made: ");
            int shotsOnGoal = Integer.parseInt(scan.nextLine());

            fileWriter.write(
                    playerName + " " + gamesPlayed + " " + goals + " " +
                            assists + " " + points + " " + saves + " " + shotsOnGoal + " (" + logTime + ") \n");
            cont = false;
        } catch(NumberFormatException e){
            System.out.println("Enter Valid Input");
            cont = true;
        }while(cont);


    }

    void updateData() throws IOException {
        System.out.print("Enter Player Name To Edit Data: ");
        String playerName = scan.nextLine();

        System.out.print("Enter Stat You Want To Change: ");
        String stat = scan.nextLine().toLowerCase().trim();

        if(fileReader.readLine().contains(playerName)){
            String statSearch = fileReader.readLine();
            

            }
        }

    }


}


文本文件格式:

姓名 GP G A P S S%

鲍比 2 3 6 14 7 50

乔治 1 3 14 2 9 23

因此,如果用户想要编辑姓名:George,请输入:Assists,仅编辑 Georges 姓名旁边的值 14

我尝试使用 if 语句在文本中定位字符串并附加它,但我无法弄清楚如何只更改指定的数字而不更改找到的所有数字。例如:如果在上面的示例中附加了 14,则两者都将被更改而不是一个

【问题讨论】:

  • 我投票结束这个问题,因为no researchnoattempt
  • 我建议使用正则表达式模式来做到这一点。如果您可以发布示例文本文件以及更新位置。
  • 我已经添加了文本文件示例和我尝试过但没有成功的东西。

标签: java text-files bufferedreader nio


【解决方案1】:

如果您被允许参与此项目(即不是学校作业),我建议您使用 JSON、YAML 或 XML。推荐使用这些类型文件的 Java 库太多,但您可以搜索“Java JSON 库”例如。

首先,需要解决一些问题...

Scanner scan = new Scanner(System.in); 放入try-with-resource 不是一个好习惯。它将自动关闭System.in,并且在您的Reader 课程中使用后将无法使用。相反,只需这样做:

Scanner scan = new Scanner(System.in);
Reader reader = new Reader(scan, path, fileWriter, fileReader);

或者,更好的是,不要将它传递给构造函数,而只需在构造函数中将scan设置为this.scan = new Scanner(System.in);

接下来,对于fileReader,您可以像为fileWriter 一样初始化它:

BufferedReader fileReader = Files.newBufferedReader(path, StandardCharsets.UTF_8);

接下来,这一行:

BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)

每次运行这个程序,这一行都会将文件覆盖为空,这可能不是你想要的。您可以添加StandardOpenOption.APPEND,但这意味着您只会写入文件末尾。

当您更新数据时,您还会遇到需要“下推”数据之后的所有数据的问题。例如:

Bobby 1 2 3 4 5
Fred 1 2 3 4 5

如果您将名称 Bobby 更改为更长的名称,例如 Mr. President,那么它将覆盖其后的数据。

虽然有不同的选项,但最好和最简单的方法是读取整个文件并将每一位数据存储在一个类中(名称、分数等),然后关闭 fileReader。

然后当用户更新某些数据时,更改类中的数据(实例变量),然后将所有数据写入文件。

这是一些伪代码:

class MyProg {
  // This could be a Map/HashMap instead.
  // See updateData().
  public List<Player> players = new ArrayList<>();

  public void readData(String filename) throws IOException {
    Path path = Paths.get(filename);
    
    try(BufferedReader fileReader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
      // Read each Player (using specific format)
      // and store in this.players
    }
  }

  public void writeData(String filename) throws IOException {
    Path path = Paths.get(filename);

    try(BufferedWriter fileWriter = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
      // Write each Player from this.players in specific format
    }
  }

  public void updateData() {
    // 1. Find user-requested Player from this.players
    // 2. Update that specific Player class
    // 3. Call writeData()
    
    // If you are familiar with Maps, then it would be faster
    // to use a Map/HashMap with the key being the player's name.
  }
}

class Player {
  public String name;
  public int games;
  public int goals;
  //...
}

【讨论】:

    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 2011-08-30
    • 1970-01-01
    相关资源
    最近更新 更多