如何从ArrayList写入txt数据

问题描述

我正在尝试从类的ArrayList中获取数据并将其写入txt,但是它会创建临时文件,不执行任何操作,打印我要放入txt中的内容,然后不会删除温度。我在做什么错了?

try
{
    File temp = new File("temp.txt");
    File file = new File(prop.getProperty("path"));
    BufferedWriter writer = new BufferedWriter(new FileWriter(temp));
    ArrayList<Contact> contacts = gestor.checkData();
                        
    if(temp.createNewFile())
    {
        for(int i = 0; i < contacts.size(); i++)
        {
            writer.write(contacts.get(i).getName());
            writer.write(contacts.get(i).getLastNames());
                                
            DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            String date = df.format(contacts.get(i).getBirthday());
                                
            writer.write(date);
            writer.write(contacts.get(i).getEmail());
        }
    writer.close();
    file.delete();
    temp.renameto(file);
    }
}
catch (IOException e)
{
    e.printstacktrace();
}

checkData的代码仅返回ArrayList contactList。

解决方法

您的代码有很多问题:

资源泄漏

诸如new FileWriter之类的东西是资源。资源必须必须关闭。因此,您永远都不应制造资源(制造资源时通常会知道:您调用new X,其中X明显代表资源,或者调用类似socket.getInputStream或{{ 1}} ......除非您做的正确,否则只有两种方法可以做到:

Files.newBufferedReader

或者,如果您需要将资源作为类的一个字段,那么唯一安全的方法是将您的类变成资源:将其设置为try (FileWriter w = new FileWriter(...)) { // use it here } ,创建一个close方法,现在负担使用该try语法的对象是使用您的类的任何人。 没有try-with-resources *,没有办法安全地完成这些工作。

Charset messup

文件是字节。不是字符。另外,文件系统不知道什么是“编码”。您如何将implements AutoClosable(或与此有关的)转换为字节?答案取决于字符集编码。所有不在é软件包中的将字节转换为字符或反之亦然的方法的问题在于它们使用“平台默认编码”。这是说“有史以来最糟糕的主意”的一种有趣方式,因为它将在您的机器上“起作用”并通过所有测试,然后在最坏的时刻生产失败。解决方案是从不永远依靠平台默认值。如果您真的打算使用它,请使其明确。不幸的是,直到java11之前,FileWriter一直无法指定字符集编码,这使它成为一个完全没用的类,如果不编写错误的代码,您将无法使用它。所以不要这样我建议您切换到新文件API,该文件默认为UTF-8(相当合理的默认值),并且可以一口气完成许多复杂的事情。

没有换行符

您只需java.nio.file所有这些数据。 write完全按照它说的去做,并且精确地写字符串。它不再打印任何内容。具体来说,它不会打印任何换行符。您肯定不打算像这样一团糟地将.write写到文件中吗?编写JoeSteel1990-10-01可以避免这种情况,或者根据需要使用换行符预先构造整个字符串,然后编写。

在意外情况下默默无事

如果'temp'文件已经存在,则您的代码将不执行任何操作。听起来设计上这是一个奇怪的情况(因为临时文件在此之后被“重命名”)。根据一般经验,当您遇到不太可能或似乎不可能的情况时,“无所事事”完全是错误的本能。正确的本能恰恰相反:尽最大可能失败。 (当然,最好的选择是考虑怪异场景的含义并正确处理它,但这并不总是可能的)。因此,请尝试:

\n

这是正确的心态:如果发生怪异的事情,请以足够的详细信息尽可能快地炸毁,以便您知道出了什么问题。 (处理此问题的最可能的“正确”方法是删除临时文件。该临时文件的要点是,如果在输入此代码时该临时文件仍然存在,则上一次尝试会失败一半,因此只需删除该临时文件即可。操作失败的结果,它没有用)。

异常处理。

尽管在示例甚至IDE模板中很常见,但您做得不好。您绝对不应通过打印某些东西并继续进行处理来处理异常。仔细考虑一下:如果出现问题,继续执行代码将导致麻烦的问题(因为您肯定不认为编写代码时程序中的一个步骤失败了),或者将导致另一个问题。错误。如果这样处理所有错误,一件事就会出错,并且您的日志中会出现85条错误跟踪。没用如果出现问题并且您不知道如何处理,请不要继续运行。唯一明智的“我不知道如何处理”异常处理是:

if (!temp.creatNewFile()) {
    throw new RuntimeException("That is weird - tempfile already exists: " + temp);
}

有时比RuntimeException更好的异常是可能的(例如UncheckedIOException或ServletException,这取决于情况)。另外,有时正确的答案是仅catch (IOException e) { throw new RuntimeException("unhandled",e); } 起例外。请记住,throws可以(通常应该!)被声明为public static void main

将它们放在一起

throws Exception

以上内容可能会失败,但无法告诉您失败的确切原因。例如,它可能会告诉您您要写入的目录不存在,或者您没有写入权限。然后您的代码将无提示地执行任何操作。

*)当然,对于您的Java专业人士来说,您可以手动编写自己的try / finally循环。让我知道当您这样做时,有多少Java新手曾经设法躲过雷区中的每个地雷。除非您过冬,否则这种经验法则实际上已成为法治:没有t-w-r,您将无法安全地做到这一点。让我们保持简单。