无法使用golang删除未压缩的文件夹。

huangapple go评论72阅读模式
英文:

Unable to delete an unzipped folder using golang

问题

我写了一段代码,用于解压缩文件到指定位置,然后将文件夹的内容复制到解压缩的文件夹外部,最后删除文件夹。

问题是除了删除文件夹之外,其他都正常工作。文件夹中只有一个文件。文件的位置如下:

E:\go\copyDirectory\myfile\mytextfile.txt

压缩文件的位置如下:

E:\go\copyDirectory\myfile.zip

压缩文件中只有一个文本文件。压缩文件中的文件如下:

E:\go\copyDirectory\myfile.zip\myfile\mytextfile.txt

我得到的错误是:

ERRR::: remove myfile\mytextfile.txt: The process cannot
access the file because it is being used by another process.

谢谢。

英文:

I wrote code that unzips a file in a particular location then copies the contents of the folder to outside where the folder is unzipped then it removes the folder.

This is the Code I wrote:

package main

 import (
   "os"
   "flag"
   "fmt"
   "io"
   "path/filepath"
   "os/exec"
   "archive/zip"
   "time"
 )

func RemoveContents(dir string) error {
    d, err := os.Open(dir)
    if err != nil {
        return err
    }
    names, err := d.Readdirnames(-1)
    if err != nil {
        return err
    }
    for _, name := range names { 
	        err = os.RemoveAll(filepath.Join(dir, name))
	        if err != nil {
	            return err
	        }
    }
	d.Close()
    return nil
}


func CopyFile(source string, dest string) (err error) {
     sourcefile, err := os.Open(source)
     if err != nil {
         return err
     }

     defer sourcefile.Close()

     destfile, err := os.Create(dest)
     if err != nil {
         return err
     }

     defer destfile.Close()

     _, err = io.Copy(destfile, sourcefile)
     if err == nil {
         sourceinfo, err := os.Stat(source)
         if err != nil {
             err = os.Chmod(dest, sourceinfo.Mode())
         }

     }

     return
 }

 func CopyDir(source string, dest string) (err error) {

     // get properties of source dir
     sourceinfo, err := os.Stat(source)
     if err != nil {
         return err
     }

     // create dest dir

     err = os.MkdirAll(dest, sourceinfo.Mode())
     if err != nil {
         return err
     }

     directory, _ := os.Open(source)

     objects, err := directory.Readdir(-1)

     for _, obj := range objects {

         sourcefilepointer := source + "/" + obj.Name()

         destinationfilepointer := dest + "/" + obj.Name()


         if obj.IsDir() {
             // create sub-directories - recursively
             err = CopyDir(sourcefilepointer, destinationfilepointer)
             if err != nil {
                 fmt.Println(err)
             }
         } else {
             // perform copy
             err = CopyFile(sourcefilepointer, destinationfilepointer)
             if err != nil {
                 fmt.Println(err)
             }
         }

     }
     return
 }




 func main() {
   	flag.Parse() // get the source and destination directory

	source_dir := flag.Arg(0) // get the source directory from 1st argument

	dest_dir := flag.Arg(1) // get the destination directory from the 2nd argument

        os.MkdirAll("E:\\go\\copyDirectory\\myFile.zip",0777)
	zipFilePath := "E:\\go\\copyDirectory\\myFile.zip"
	tempWrkDir := "E:\\go\\copyDirectory\\"

	//Read zip file and get path handle.
	fileHandleReader, err := zip.OpenReader(zipFilePath)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	//open zip file and read all the folder and files inside
	for _, fileReadHandler := range fileHandleReader.Reader.File {
		//read the file or folder handle inside zip
		fileOpenHandle, err := fileReadHandler.Open()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		defer fileOpenHandle.Close()
	targetUnZipPath := filepath.Join(tempWrkDir, fileReadHandler.Name)
	if fileReadHandler.FileInfo().IsDir() {
			os.MkdirAll(targetUnZipPath, fileReadHandler.Mode())
			//fmt.Println("Creating directory", path)
		}else {
			// create new dummy file to copy original file.
			newTempFileHandle, err := os.OpenFile(targetUnZipPath, os.O_WRONLY|os.O_CREATE, fileReadHandler.Mode())

			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

			defer newTempFileHandle.Close()
			//copying original file to dummy file.
			if _, err = io.Copy(newTempFileHandle, fileOpenHandle); err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		}
	}
      time.Sleep(1000*time.Millisecond)

      fmt.Println("Source :" + source_dir)

      // check if the source dir exist
      src, err := os.Stat(source_dir)
     if err != nil {
       panic(err)
    }

     if !src.IsDir() {
       fmt.Println("Source is not a directory")
       os.Exit(1)
    }

   // create the destination directory
   fmt.Println("Destination :"+ dest_dir)

   /*_, err = os.Open(dest_dir)
   if !os.IsNotExist(err) {
     fmt.Println("Destination directory already exists. Abort!")
     os.Exit(1)
   }*/

   err = CopyDir(source_dir, dest_dir)
   if err != nil {
      fmt.Println(err)
   } else {
      fmt.Println("Directory copied")
   }
	err = RemoveContents("./myFiles")
	   if err != nil {
	    fmt.Println("ERRR:::",err)
	   }
	//time.Sleep(10000*time.Millisecond)
 }

The problem is that everything works fine except for deleting the folder. The folder has only one file in it. The location of the file is as follows:

E:\go\copyDirectory\myfile\mytextfile.txt

The Location of the zip file is as follows:

 E:\go\copyDirectory\myfile.zip

The zip file has only one text file. The File inside the zip file is as follows:

E:\go\copyDirectory\myfile.zip\myfile\mytextfile.txt

The error I get is:

ERRR::: remove myfile\mytextfile.txt: The process cannot
access the file because it is being used by another process.

Thanks in advance.

答案1

得分: 2

你没有关闭文件。这段代码:

defer newTempFileHandle.Close()

在主函数结束后执行,也就是在以下代码之后:

err = RemoveContents("./myFiles")

你可以将这段代码放在一个无名函数中:

	func() {
		// 在 zip 文件中读取文件或文件夹句柄
		fileOpenHandle, err := fileReadHandler.Open()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		defer fileOpenHandle.Close()
		targetUnZipPath := filepath.Join(tempWrkDir, fileReadHandler.Name)
		if fileReadHandler.FileInfo().IsDir() {
			os.MkdirAll(targetUnZipPath, fileReadHandler.Mode())
			//fmt.Println("Creating directory", path)
		} else {
			// 创建一个新的虚拟文件来复制原始文件
			newTempFileHandle, err := os.OpenFile(targetUnZipPath, os.O_WRONLY|os.O_CREATE, fileReadHandler.Mode())

			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

			defer newTempFileHandle.Close()
			// 将原始文件复制到虚拟文件中
			if _, err = io.Copy(newTempFileHandle, fileOpenHandle); err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		}
	}()

这样,你的 defer 语句将在尝试删除文件之前执行。不过我建议将这部分代码提取到一个有名字的函数中。

英文:

You aren't closing the file. This:

defer newTempFileHandle.Close()

Is run when main finishes, which is after:

err = RemoveContents("./myFiles")

You can wrap that bit of code in an unnamed function:

	func() {
		//read the file or folder handle inside zip
		fileOpenHandle, err := fileReadHandler.Open()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		defer fileOpenHandle.Close()
		targetUnZipPath := filepath.Join(tempWrkDir, fileReadHandler.Name)
		if fileReadHandler.FileInfo().IsDir() {
			os.MkdirAll(targetUnZipPath, fileReadHandler.Mode())
			//fmt.Println("Creating directory", path)
		} else {
			// create new dummy file to copy original file.
			newTempFileHandle, err := os.OpenFile(targetUnZipPath, os.O_WRONLY|os.O_CREATE, fileReadHandler.Mode())

			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}

			defer newTempFileHandle.Close()
			//copying original file to dummy file.
			if _, err = io.Copy(newTempFileHandle, fileOpenHandle); err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		}
	}()

And then your defer will happen before you try and remove the files. I would recommend pulling this out into a named function though.

huangapple
  • 本文由 发表于 2016年1月14日 18:51:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/34787709.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定