1. 程式人生 > >java中讓人蛋疼的delete

java中讓人蛋疼的delete

專案中要刪除資料夾, 只有一層, 下面有zip包, jpg圖片, xml檔案, 但是在刪除時, 有一部分檔案卻刪不掉, delete的結果是false:
public void deleteDir(File file)
	{
		if (file.exists())
		{

			File files[] = file.listFiles();
			for (int i = 0; i < files.length; i++)
			{
				System.out.println("刪除" + files[i].getAbsolutePath());
				boolean b = files[i].delete();
				System.out.println(b);
			}

			file.delete();
		}
		else
		{
			System.out.println("所刪除的檔案不存在!" + '\n');
		}

	}

但是, 寫一個個main方法, 傳進去目錄路徑, 可以全部刪除, 百思不得其解。

經過google之後, 很幸運, 找到了相同的遭遇者:

引用:

I would argue it's a bug then: java.sun.com/javase/6/docs/api/java/io/…() It says in there that the method should close the stream and any resources associated with it. I usually like to close all the streams in the inverted sequence (the last ones to be open are the first ones to be closed) using IOUtils.closeQuietly, but it tends to be overkill.


Another bug in Java. I seldom find them, only my second in my 10 year career. This is my solution, as others have mentioned. I have nether used System.gc(). But here, in my case, it is absolutely crucial. Weird? YES!
finally{try{
        in.close();
        in =null;
        out.flush();
        out
.close();         out =null;System.gc();}catch(IOException e){         logger.error(e.getMessage());         e.printStackTrace();}}
YEP! That was it for me too. I was using FileOutputStream. After setting out=null and then explicit call to System.gc() , it worked


然後, 我突然明白了, 趕緊測試, 果然搞定, 是這樣的, 

我們的業務邏輯是, 根據業務號從資料庫讀取該業務號下影像的路徑, 然後找到對應的檔案並複製到以業務號命名的資料夾下, 以業務號命名的資料夾放在指定的資料夾destdir下, 然後然後根據影像資訊生成xml報文, 

當報文生成後, 將影像和報文打包成zip, 然後將zip通過第三方介面上傳到影像平臺。當一個業務上傳成功後, 要刪除以這個業務號命名的目錄, 就是在刪除時出現了以上描述的問題, 那麼到底是哪個環節的問題?

一個是拷貝檔案, 一個是生成zip包, 無非這兩個地方, 所以, 統統加了賦空和回收的操作:

	fos.flush();
			fos.close();
			fis.close();
			fis = null;
			fos = null;
			System.gc();

public boolean zipMaterial(String dir, String busNO)
	{
		File directory = new File(dir);
		File[] files = directory.listFiles();

		try
		{
			FileOutputStream output = new FileOutputStream(new File(dir + busNO
					+ ".zip"));
			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
					output));

			for (int i = 0; i < files.length; i++)
			{
				InputStream in = new FileInputStream(files[i]);
				ZipEntry e = new ZipEntry(files[i].getName());
				out.putNextEntry(e);

				int len = 0;
				byte[] b = new byte[1024];
				while ((len = in.read(b)) != -1)
				{
					out.write(b, 0, len);
					out.flush();
				}

				out.closeEntry();
			}
			out.flush();
			output.flush();
			out.close();
			output.close();
			out = null;
			output = null;
			System.gc();
		}
		catch (FileNotFoundException e)
		{

			return false;
		}
		catch (IOException e)
		{

			return false;
		}

		return true;
	}

執行測試, 搞定!!

File的delete方法:

  /**
     * Deletes the file or directory denoted by this abstract pathname.  If
     * this pathname denotes a directory, then the directory must be empty in
     * order to be deleted.
     *
     * @return  <code>true</code> if and only if the file or directory is
     *          successfully deleted; <code>false</code> otherwise
     *
     * @throws  SecurityException
     *          If a security manager exists and its <code>{@link
     *          java.lang.SecurityManager#checkDelete}</code> method denies
     *          delete access to the file
     */
    public boolean delete() {
	SecurityManager security = System.getSecurityManager();
	if (security != null) {
	    security.checkDelete(path);
	}
	return fs.delete(this);


可見如果是檔案, 可以刪除, 

但如果是目錄, 必須是空的才可以刪除。