[英]write data from an arraylist of objects and arraylist within objects to a text file
[英]How to write to a text file from an ArrayList
我正在嘗試從類的ArrayList
中獲取數據並將其寫入文本文件。 它創建臨時文件,但不對它做任何事情。 它會打印我要放入文件的內容,並且不會刪除臨時文件。 我究竟做錯了什么?
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<Contact> contactList
。
您的代碼存在許多問題:
像new FileWriter
這樣的東西是一種資源。 資源必須關閉。 因此,你永遠不應該創建資源(你通常在創建資源時就知道:你要么調用new X
其中 X 顯然代表資源,要么調用諸如socket.getInputStream
或Files.newBufferedReader
類的東西......除非你做對了。只有兩種方法可以做到:
try (FileWriter w = new FileWriter(...)) {
// use it here
}
或者,如果您需要資源成為您的類的一個字段,那么唯一安全的方法是將您的類變成一個資源:使其implements AutoClosable
,創建一個 close 方法,現在使用該 try 語法的負擔是誰使用你的課。 沒有 try-with-resources * 就沒有辦法安全地做這些事情。
文件是字節。 不是字符。 此外,文件系統不知道“編碼”是什么。 您如何將☃
或就此而言é
轉換為字節? 答案取決於字符集編碼。 所有將字節轉換為字符或反之亦然java.nio.file
包中的方法的問題在於它們使用“平台默認編碼”。 這是說“有史以來最糟糕的想法”的一種有趣方式,因為這將在您的機器上“工作”並通過所有測試,然后在最糟糕的時刻在生產中失敗。 解決方案是永遠不要依賴平台默認值。 如果您真的打算使用它,請明確說明。 不幸的是,在 java11 之前,FileWriter無法指定 charset 編碼,這使得它成為一個完全無用的類,如果不編寫錯誤代碼,您將無法真正使用它。 所以不要。 我建議你切換到新的文件 API,它默認為 UTF-8(相當合理的默認值),並且可以在一行中完成很多復雜的事情。
您只需.write
所有這些數據。 write 完全按照它所說的去做,並且准確地寫入字符串。 它不再打印任何東西。 具體來說,它不打印任何換行符。 您肯定不打算只將JoeSteel1990-10-01
文件中,像這樣一團糟? 寫\n
來避免這種情況,或者按照你的意願預先構造整個字符串(使用換行符),然后寫下它。
如果“臨時”文件已經存在,您的代碼將不執行任何操作。 聽起來設計是這是一個奇怪的情況(因為臨時文件在之后被“重命名”)。 作為一般的經驗法則,當您遇到您知道不太可能或看似不可能的情況時,“默默地什么都不做”完全是錯誤的本能。 正確的直覺恰恰相反:盡可能地失敗。 (當然,最好的選擇是考慮奇怪的場景意味着什么並正確處理它,但這並不總是可能的)。 因此,請嘗試:
if (!temp.creatNewFile()) {
throw new RuntimeException("That is weird - tempfile already exists: " + temp);
}
這是正確的心態:如果發生了奇怪的事情,請盡快炸毀,並提供足夠的細節,以便您知道出了什么問題。 (最可能的“正確”處理方法是刪除臨時文件。該臨時文件的全部意義在於,如果在您輸入此代碼時它仍然存在,則之前的嘗試中途失敗,所以只需刪除失敗操作的產物,它沒有用)。
雖然在示例甚至 IDE 模板中很常見,但您做得不對。 你永遠不應該通過打印一些東西並繼續處理異常。 想一想:如果出現問題,繼續執行代碼要么會導致嚴重的問題(因為您在編寫代碼時肯定沒有考慮到程序中的一個步驟失敗),或者會導致另一個錯誤。 如果所有錯誤都這樣處理,那么就會出現一件事,並且您的日志中會出現 85 個錯誤跟蹤。 那沒用。 如果出現問題而您不知道如何處理,請不要繼續運行。 唯一明智的“我不知道如何處理”異常處理是:
catch (IOException e) {
throw new RuntimeException("unhandled", e);
}
有時比 RuntimeException 更好的異常是可能的(例如 UncheckedIOException 或 ServletException,這取決於情況)。 此外,有時正確的答案是向前throws
異常。 請記住, public static void main
可以(並且通常應該!)被聲明為throws Exception
。
try {
Path temp = Paths.get("temp.txt");
Path file = Paths.get(prop.getProperty("path"));
ArrayList<Contact> contacts = gestor.checkData();
try (BufferedWriter writer = Files.newBufferedWriter(temp)) {
for (Contact contact : contacts) {
writer.write(contact.getName());
writer.write("\n");
writer.write(contact.getLastNames());
writer.write("\n");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String date = df.format(contact.getBirthday());
writer.write(date);
writer.write("\n");
writer.write(contact.getEmail());
writer.write("\n");
}
}
Files.delete(file);
Files.move(temp, file);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
以上可能會失敗,但它會失敗告訴你它失敗的確切原因。 例如,它可能會告訴您您嘗試寫入的目錄不存在,或者您沒有寫入權限。 而您的代碼將默默地什么也不做。
*) 對於您的 java 專業人士,當然,您可以手動處理自己的 try/finally 循環。 讓我知道當你這樣做時,有多少 Java 新手曾設法避開雷區中的每一個地雷。 直到你完全過冬,這條經驗法則實際上變成了一條法則:沒有 twr,你就無法安全地做到這一點。 讓我們保持簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.