提问人:Alem Beskovic 提问时间:6/9/2023 更新时间:6/10/2023 访问量:40
如何更新文本文件中的特定数字?
How do I update a specific number in a text file?
问:
我正在编写一个房地产 gui 程序,该程序从租户那里获取信息,例如名字、姓氏、公寓等,并将这些值存储在文本文件中。我为不同的选项提供了不同的类,例如删除租户、更新租户、添加租户和查看所有租户。我有用于添加租户、删除租户和查看租户的类,但在更新类时遇到问题。添加这些租户的方式是通过数组列表,该数组列表采用这些不同的变量,并使用 toString 在文本文件中逐行上传它们。每个租户信息位于不同的行上。我在更新类中尝试做的是,当存入资金时,该特定租户的余额设置为 MonthlyRent - deposit = balance。我遇到的问题是试图弄清楚如何读取 monthlyRent 和余额,将它们设置为 2 变量,然后进行计算并更新该特定部分。我知道我必须删除文件并重新更新文件,我只是不知道如何读取该特定部分并将它们设置为变量。
//////////////////////////////////////////////////////////////////////////////////////////
public class Person extends JFrame{
File log = new File("tenantData.txt");
static ArrayList<Person> tenantData = new ArrayList<Person>();
public String firstName;
public String lastName;
public int apartmentNumber;
public String streetAddress;
public int streetNumber;
public String town;
public String state;
public float balance;
public float deposit;
public float monthRent;
Person( String firstName, String LastName, int apartmentNumber, String streetAddress, int streetNumber, String town, String state, float monthRent, float balance)
{
this.firstName = firstName;
this.lastName = LastName;
this.apartmentNumber = apartmentNumber;
this.streetAddress = streetAddress;
this.streetNumber = streetNumber;
this.town = town;
this.state = state;
this.monthRent = monthRent;
this.balance = balance;
}
@Override
public String toString() {
String str = firstName + " " + lastName + ", apartment" + apartmentNumber + ", " +streetNumber+ " " +streetAddress+ ", " +town+ ", " +state+
". Monthly Rent: "+ monthRent+ " Balance: " + balance + "\n";
return str;
}
这是主类的变量和构造函数
public void buildPanel3() {
JPanel panel = new JPanel();
ButtonHandler4 b = new ButtonHandler4();
label = new JLabel("Enter first and last name of tenant you would like to update");
field = new JTextField(25);
label2 = new JLabel("Enter the amount that the tenant has payed");
paymentAmount = new JTextField(4);
update = new JButton(updateTenant);
update.addActionListener(b);
panel.add(label);
panel.add(field);
panel.add(label2);
panel.add(paymentAmount);
panel.add(update);
add(panel);
}
public class ButtonHandler4 implements ActionListener{
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
if(str.equals(updateTenant)) {
String line = field.getText();
String payment = paymentAmount.getText();
String[] parts = line.split(" ");
String firstName = parts[0];
String lastName = parts[1];
这是 Update 类的生成面板和按钮处理程序。我需要弄清楚如何首先在文件中搜索名字和姓氏,然后使用付款变量进行更新。
答:
为了调整解决方案,我不得不对一些变量进行重新排序。
我将 log 和 tenantData 移动到另一个类。
我的第一个建议是使用不同的分隔符来分隔租户数据 .txt 文件中的值。
这将使与文件之间的解析变得更加容易,因为数据包含逗号。
您可以改用制表符。
这是一个参考,维基百科 - 制表符分隔值。
由于您正在使用 toString 来生成输出,因此可以将其替换为以下内容。
@Override
public String toString() {
return firstName + ' ' + lastName + '\t'
+ apartmentNumber + '\t'
+ streetNumber + ' ' + streetAddress + '\t'
+ town + ", " + state + '\t'
+ monthRent + '\t'
+ balance;
}
此外,还需要一种方法将行转换为 Person 对象。
可以向 Person 类添加静态分析方法。
static Person parse(String string) {
Person person = new Person();
String[] strings = string.split("\t", -1);
int indexOf = strings[0].indexOf(' ');
person.firstName = strings[0].substring(0, indexOf);
person.lastName = strings[0].substring(indexOf + 1);
person.apartmentNumber = Integer.parseInt(strings[1]);
indexOf = strings[2].indexOf(' ');
person.streetNumber = Integer.parseInt(strings[2].substring(0, indexOf));
person.streetAddress = strings[2].substring(indexOf + 1);
indexOf = strings[3].indexOf(", ");
person.town = strings[3].substring(0, indexOf);
person.state = strings[3].substring(indexOf + 2);
person.monthRent = Float.parseFloat(strings[4]);
person.balance = Float.parseFloat(strings[5]);
return person;
}
而且,我们需要一种方法来比较 Person 对象。
这也是在 Person 类中。
boolean equals(Person person) {
return firstName.equals(person.firstName)
&& lastName.equals(person.lastName)
&& apartmentNumber == person.apartmentNumber
&& streetNumber == person.streetNumber
&& streetAddress.equals(person.streetAddress)
&& town.equals(person.town)
&& state.equals(person.state);
}
从这里,您需要创建功能来读取文件,并找到正确的行。
有几种方法可以实现这一点。我通常使用 BufferedReader 类,因为它提供了 readLine 方法。
您还可以使用 Scanner 类,NIO 框架也提供了 Paths 和 Files 类——实际上,我在下面使用它们来编写文件。
我将此方法与 log 和 tenantData 变量一起放在另一个类中。
请注意,由于 Person 对象的唯一性依赖于许多变量,因此我使用 Person 对象作为要匹配的参数。
而不是为每个单独的值设置一个参数。
/** @return null if not found */
Person find(Person person) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(log))) {
String line;
Person value;
while ((line = reader.readLine()) != null) {
if (person.equals(value = Person.parse(line)))
return value;
}
return null;
}
}
因此,您可以根据需要从此处更新 Person 对象的值。
其中,您需要一种方法将数据写回文件中。
我发现 Google AI 有一个有趣的方法,它建议我使用 String#replace 来覆盖原始值。
void save(Person original, Person updated) throws IOException {
String string = new String(Files.readAllBytes(log.toPath()));
string = string.replace(original.toString(), updated.toString());
try (FileWriter writer = new FileWriter(log)) {
writer.write(string);
writer.flush();
}
}
下面是一个基本示例,我在其中创建了包含 3 个 Person 对象的文件,然后更新了一个对象并保存它。
tenantData = new ArrayList<>();
tenantData.add(new Person("firstNameA", "lastNameA", 1, "addressA", 1, "townA", "stateA", 1, 1));
tenantData.add(new Person("firstNameB", "lastNameB", 1, "addressB", 1, "townB", "stateB", 2, 2));
tenantData.add(new Person("firstNameC", "lastNameC", 1, "addressC", 1, "townC", "stateC", 3, 3));
try (FileWriter writer = new FileWriter("files/tenantData.txt")) {
for (Person person : tenantData)
writer.write(person.toString() + System.lineSeparator());
writer.flush();
}
Example example = new Example();
System.out.println("original");
for (String line : Files.readAllLines(example.log.toPath()))
System.out.println(line);
Person person = example.find(new Person("firstNameB", "lastNameB", 1, "addressB", 1, "townB", "stateB", 0, 0));
Person copy = Person.parse(person.toString());
person.balance += 10;
example.save(copy, person);
System.out.println();
System.out.println("updated");
for (String line : Files.readAllLines(example.log.toPath()))
System.out.println(line);
输出
original
firstNameA lastNameA 1 1 addressA townA, stateA 1.0 1.0
firstNameB lastNameB 1 1 addressB townB, stateB 2.0 2.0
firstNameC lastNameC 1 1 addressC townC, stateC 3.0 3.0
updated
firstNameA lastNameA 1 1 addressA townA, stateA 1.0 1.0
firstNameB lastNameB 1 1 addressB townB, stateB 2.0 12.0
firstNameC lastNameC 1 1 addressC townC, stateC 3.0 3.0
而且,这是完整的代码。
public class Example {
File log = new File("tenantData.txt");
static ArrayList<Person> tenantData = new ArrayList<Person>();
/** @return null if not found */
Person find(Person person) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(log))) {
String line;
Person value;
while ((line = reader.readLine()) != null) {
if (person.equals(value = Person.parse(line)))
return value;
}
return null;
}
}
void save(Person original, Person updated) throws IOException {
String string = new String(Files.readAllBytes(log.toPath()));
string = string.replace(original.toString(), updated.toString());
try (FileWriter writer = new FileWriter(log)) {
writer.write(string);
writer.flush();
}
}
static class Person {
public String firstName;
public String lastName;
public int apartmentNumber;
public String streetAddress;
public int streetNumber;
public String town;
public String state;
public float balance;
public float deposit;
public float monthRent;
Person() {
}
Person(String firstName, String LastName, int apartmentNumber, String streetAddress, int streetNumber, String town, String state, float monthRent, float balance) {
this.firstName = firstName;
this.lastName = LastName;
this.apartmentNumber = apartmentNumber;
this.streetAddress = streetAddress;
this.streetNumber = streetNumber;
this.town = town;
this.state = state;
this.monthRent = monthRent;
this.balance = balance;
}
static Person parse(String string) {
Person person = new Person();
String[] strings = string.split("\t", -1);
int indexOf = strings[0].indexOf(' ');
person.firstName = strings[0].substring(0, indexOf);
person.lastName = strings[0].substring(indexOf + 1);
person.apartmentNumber = Integer.parseInt(strings[1]);
indexOf = strings[2].indexOf(' ');
person.streetNumber = Integer.parseInt(strings[2].substring(0, indexOf));
person.streetAddress = strings[2].substring(indexOf + 1);
indexOf = strings[3].indexOf(", ");
person.town = strings[3].substring(0, indexOf);
person.state = strings[3].substring(indexOf + 2);
person.monthRent = Float.parseFloat(strings[4]);
person.balance = Float.parseFloat(strings[5]);
return person;
}
boolean equals(Person person) {
return firstName.equals(person.firstName)
&& lastName.equals(person.lastName)
&& apartmentNumber == person.apartmentNumber
&& streetNumber == person.streetNumber
&& streetAddress.equals(person.streetAddress)
&& town.equals(person.town)
&& state.equals(person.state);
}
@Override
public String toString() {
return firstName + ' ' + lastName + '\t'
+ apartmentNumber + '\t'
+ streetNumber + ' ' + streetAddress + '\t'
+ town + ", " + state + '\t'
+ monthRent + '\t'
+ balance;
}
}
}
评论
new ArrayList<>(Files.readAllLines...