【问题标题】:How to read from files and store it in ArrayList of objects?如何从文件中读取并将其存储在对象的 ArrayList 中?
【发布时间】:2020-02-24 07:12:33
【问题描述】:

这是我的保存方法

public static void save() {
        try {
            PrintWriter myWriter = new PrintWriter("database.txt");
            for(int i=0; i<people.size(); i++) {
                myWriter.println(people.get(i).toString());
            }
            myWriter.close();
            System.out.println("Successfully wrote to the file.");
            menu();
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }

这是文件中的样子

    Donald     Trump  23323.00

这是数组列表的字段和名称

ArrayList<Person> people = new ArrayList<Person>();
public Person(String name, String password, double money) {
        this.name = name;
        this.password = password;
        this.money = money;
    }
constructors below.....

如何读取该文件并将其存储在对象数组列表中?需要帮助:D

【问题讨论】:

标签: java arraylist file-handling readfile


【解决方案1】:

并不是说您写入数据文本文件的方式有什么问题,只是我认为最好遵循更传统的CSV 样式文件格式,该格式专用于这种类型的数据存储。

例如,CSV 文件中的每一行都被视为一个记录行,并且通常使用逗号 (,) 来分隔该行中的字段数据列,而不是空格或制表符(就像在您的文件中一样),并且显然有充分的理由。最终需要检索文件中的数据,如果列字段中包含空格怎么办?例如,一些姓氏包含两个词(Simone de Beauvoir、Herbert M. Turner III、Ashley M. St. John 等)。必须对此进行一些考虑,是的,肯定有一种解决方法,但总而言之,使用除空格之外的更具体的分隔符更容易。您可能需要考虑将空格分隔符更改为逗号或分号分隔符。您甚至可以在您的 PersontoString() 方法中提供此选项:

/* Example Person Class...    */
import java.io.Serializable;

public class Person implements Serializable {

    // Default serialVersion id
    private static final long serialVersionUID = 1212L;

    private String name;
    private String password;
    private double money;

    public Person() { }

    public Person(String name, String password, double money) {
        this.name = name;
        this.password = password;
        this.money = money;
    }

    public String toString(String delimiterToUse) {
        return new StringBuffer("").append(this.name).append(delimiterToUse)
                                   .append(this.password).append(delimiterToUse)
                                   .append(String.format("%.2f", this.money)).toString();
    }

    @Override
    public String toString() {
        return new StringBuffer("").append(this.name).append(" ")
                                   .append(this.password).append(" ")
                                   .append(String.format("%.2f", this.money)).toString();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
}

在您的 save() 方法中,您可能有现有的行来利用空白的类默认分隔符 (" "):

myWriter.println(people.get(i).toString());

或使用不同的分隔符,例如 逗号/空格组合 (", "):

    myWriter.println(people.get(i).toString(", "));

文件中的数据记录如下所示:

Donald Trump, myPassword, 23323.0

现在使用String#split() 之类的方法更容易解析上面的这条数据行,例如:

public static List<Person> readInPeople(String databaseFile) {
    /* Declare a List Interface to hold all the read in records 
       of people from the database.txt file.        */
    List<Person> people = new ArrayList<>();

    // 'Try With Resouces' is used to so as to auto-close the reader.
    try (BufferedReader reader = new BufferedReader(new FileReader("database.txt"))) {
        String dataLine;
        while ((dataLine = reader.readLine()) != null) {
            dataLine = dataLine.trim();
            // Skip past blank lines.
            if (dataLine.equals("")) {
                continue;
            }

            /* Split the read in dataline delimited field values into a 
               String Array. A Regular Expression is used within the split()
               method that takes care of any comma/space delimiter combination
               situation such as: "," or ", " or " ," or " , "   */
            String[] dataLineParts = dataLine.split("\\s{0,},\\s{0,}");

            // Ensure defaults for people.
            String name = "", password = "";
            double money = 0.0d;

            /* Place each split data line part into the appropriate variable 
               IF it exists otherwise the initialized default (above) is used. */
            if (dataLineParts.length >= 1) {
                name = dataLineParts[0];
                if (dataLineParts.length >= 2) {
                    password = dataLineParts[1];
                    if (dataLineParts.length >= 3) {
                        /* Make sure the data read in is indeed a string
                           representation of a signed or unsigned Integer 
                           or double/float type numerical value. The Regular
                           Expression within the String#matches() method 
                           does this.                                    */
                        if (dataLineParts[2].matches("-?\\d+(\\.\\d+)?")) {
                            money = Double.parseDouble(dataLineParts[2]);
                        }
                    }
                }
            }

            // Add the person from file into the people List.
            people.add(new Person(name, password, money));
        }
    }
    // Catch Exceptions...
    catch (FileNotFoundException ex) {
        System.err.println(ex.getMessage());
    }
    catch (IOException ex) {
        System.err.println(ex.getMessage());
    }
    /* Return the list of people read in from the 
       database text file.   */
    return people;
}

要使用这种方法,你可以这样做:

// Call the readInPeople() method to fill the people List.
List<Person> people = readInPeople("database.txt");

/* Display the people List in Console Window 
   using a for/each loop.     */
// Create a header for the data display.
// Also taking advantage of the String#format() and String#join() methods.
// String#join() is used to create the "=" Header underline.
String header = String.format("%-20s %-15s %s\n", "Name", "Password", "Money");
header += String.join("", Collections.nCopies(header.length(), "="));
System.out.println(header);

// Display the list. Also taking advantage of the printf() method.
for (Person peeps : people) {
    System.out.printf("%-20s %-15s %s\n", peeps.getName(), peeps.getPassword(), 
                      String.format("%.2f", peeps.getMoney()));
}

控制台显示可能如下所示:

Name                 Password        Money
===========================================
Donald Trump         myPassword      23323.00
Tracey Johnson       baseball        2233.00
Simone de Beauvoir   IloveFrance     32000.00

【讨论】:

    【解决方案2】:

    逐行读取文件并使用您在toStringPerson 类中使用的相同分隔符。

    Like:假设你使用了" " 作为分隔符。

    然后read line by line 并使用该分隔符拆分数据并分别转换数据

    String line = reader.readLine();
    String[] array = line.split(" ")// use same delimiter used to write
    if(array.lenght() ==3){ // to check if data has all three parameter 
        people.add(new Person(array[0], array[1], Double.parseDouble(array[2]))); 
        // you have to handle case if Double.parseDouble(array[2]) throws exception
    }
    

    【讨论】:

    • return String.format("%10s%10s%10.2f\n", name, password, money); //这是我的 toString 格式我真的不明白什么是分隔符抱歉
    • 使用返回名 +" " +password+" "+money.这里“”是你的分隔符,在string.fomate的情况下很难编写拆分逻辑。
    • 在上面的例子中,你必须格式化钱来获得 2 个十进制值:比如stackoverflow.com/questions/12806278/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 2020-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2017-04-25
    相关资源
    最近更新 更多