Java - 如何将我的ArrayList写入文件,并将该文件读取(加载)到原始ArrayList?

use*_*264 22 java inputstream outputstream arraylist text-files

我正在用Java编写一个程序,它显示了一系列的课后俱乐部(EG Football,Hockey - 由用户输入).俱乐部添加到以下内容ArrayList:

private ArrayList<Club> clubs = new ArrayList<Club>();
Run Code Online (Sandbox Code Playgroud)

通过以下方法:

public void addClub(String clubName) {
    Club club = findClub(clubName);
    if (club == null)
        clubs.add(new Club(clubName));
}
Run Code Online (Sandbox Code Playgroud)

'Club'是一个带有构造函数的类 - 名称:

public class Club {

    private String name;

    public Club(String name) {
        this.name = name;
    }

    //There are more methods in my program but don't affect my query..
}
Run Code Online (Sandbox Code Playgroud)

我的程序正在运行 - 它允许我在我的arraylist中添加一个新的Club对象,我可以查看arraylist,我可以删除任何我想要的等等.

但是,我现在想将该arrayList(俱乐部)保存到文件中,然后我希望能够稍后加载该文件并再次使用相同的arraylist.

我有两种方法(见下文),并一直试图让它工作,但没有任何帮助,任何帮助或建议将不胜感激.

保存方法(fileName由用户选择)

public void save(String fileName) throws FileNotFoundException {
    String tmp = clubs.toString();
    PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
    pw.write(tmp);
    pw.close();
}
Run Code Online (Sandbox Code Playgroud)

加载方法(当前代码不会运行 - 文件是一个字符串,但需要是俱乐部?

public void load(String fileName) throws FileNotFoundException {
    FileInputStream fileIn = new FileInputStream(fileName);
    Scanner scan = new Scanner(fileIn);
    String loadedClubs = scan.next();
    clubs.add(loadedClubs);
}
Run Code Online (Sandbox Code Playgroud)

我也使用GUI来运行应用程序,此刻,我可以单击"保存"按钮,然后允许我键入名称和位置并保存.该文件出现,可以在记事本中打开,但显示为像Club @ c5d8jdj(我列表中的每个俱乐部)

Ami*_*ost 70

您应该使用Java的内置序列化机制.要使用它,您需要执行以下操作:

  1. Club类声明为实现Serializable:

    public class Club implements Serializable {
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这告诉JVM该类可以序列化为流.您不必实现任何方法,因为这是一个标记接口.

  2. 要将列表写入文件,请执行以下操作:

    FileOutputStream fos = new FileOutputStream("t.tmp");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(clubs);
    oos.close();
    
    Run Code Online (Sandbox Code Playgroud)
  3. 要从文件中读取列表,请执行以下操作:

    FileInputStream fis = new FileInputStream("t.tmp");
    ObjectInputStream ois = new ObjectInputStream(fis);
    List<Club> clubs = (List<Club>) ois.readObject();
    ois.close();
    
    Run Code Online (Sandbox Code Playgroud)

  • 这不应该是公认的答案吗? (4认同)
  • 很好,谢谢 (3认同)
  • 如果您遇到“只读文件系统”异常,则可以将“ t.tmp”更改为“ file”,其中“ File file = new File(getFilesDir(),“ t.tmp”);”或`File file = new File(getExternalFilesDir(null),“ t.tmp”);`,但后者可能需要`WRITE_EXTERNAL_STORAGE`权限。 (3认同)

Sot*_*lis 9

作为练习,我建议做以下事项:

public void save(String fileName) throws FileNotFoundException {
    PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
    for (Club club : clubs)
        pw.println(club.getName());
    pw.close();
}
Run Code Online (Sandbox Code Playgroud)

这将在您的文件中的新行上写下每个俱乐部的名称.

Soccer
Chess
Football
Volleyball
...
Run Code Online (Sandbox Code Playgroud)

我会把装载留给你.提示:你一次写了一行,然后你可以一次读一行.

Java中的每个类都扩展了Object该类.因此,您可以覆盖其方法.在这种情况下,您应该对该toString()方法感兴趣.在您的Club课程中,您可以覆盖它,以任何您喜欢的格式打印有关该课程的消息.

public String toString() {
    return "Club:" + name;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以将上面的代码更改为:

public void save(String fileName) throws FileNotFoundException {
    PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
    for (Club club : clubs)
         pw.println(club); // call toString() on club, like club.toString()
    pw.close();
}
Run Code Online (Sandbox Code Playgroud)

  • 对于一个小的数据集,它似乎没问题,但我非常怀疑它的有效性给出了一个庞大的数据集. (2认同)

小智 6

在Java 8中,您可以使用带有两个参数的Files.write()方法:PathList<String>类似的东西:

List<String> clubNames = clubs.stream()
    .map(Club::getName)
    .collect(Collectors.toList())

try {
    Files.write(Paths.get(fileName), clubNames);
} catch (IOException e) {
    log.error("Unable to write out names", e);
}
Run Code Online (Sandbox Code Playgroud)