dongnuan7956 2016-04-27 20:23
浏览 81
已采纳

检测重命名失败的原因

I use some code similar to the lines below. The rename can fail if the directory is blocked because some application has a file open in it.

err := os.Rename("C:/temp/inUse", "c:/temp/Renamed")

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

I am able to detect this fact when I check err for this content:

rename C:/temp/inUse c:/temp/Renamed: Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.

(which translates to "The process is unable to access the file because it is used by a different process") But this message varies depending on the OS language.

Is it possible to detect the problem by a unique "error code" ? I wouldn't mind if the solution is specific to Windows and doesn't work on other operating systems supported by Go.

Ideally I could do something like if err.Err == 32 { fmt.Println( "Your directory is in use please ...

  • 写回答

1条回答 默认 最新

  • duanshangying5102 2016-04-27 21:57
    关注

    The error returned by os.Rename is of type *os.LinkError which gives you access to the underlying error from the operating system. You should be able to use that to distinguish the particular error you are encountering.

    You'll need to convert the error to *os.LinkError first.

    For instance, trying to rename a folder (/Users/t/pprof) to another name that is write-protected (/Users/t/pprof2):

    func TestRename(t *testing.T) {
        err := os.Rename("/Users/t/pprof", "/Users/t/pprof2")
        if err != nil {
            e := err.(*os.LinkError)
            t.Logf("Op: ", e.Op)
            t.Logf("Old: ", e.Old)
            t.Logf("New: ", e.New)
            t.Logf("Err: ", e.Err)
        }
    }
    

    Provides the following output:

    Op: %!(EXTRA string=rename)
    Old: %!(EXTRA string=/Users/t/pprof)
    New: %!(EXTRA string=/Users/t/pprof2)
    Err: %!(EXTRA syscall.Errno=operation not permitted)
    

    The OS error code is accessible as the Err member, but will be different depending on the OS you are running.

    The Err member is of type syscall.Errno. To further inspect the actual error, you need to convert it to that type first:

    oserr := e.Err.(syscall.Errno)
    

    Now oserr can be compared with the values for Errno declared in the syscall package. You'll find them if you search for ENOENT on that page.

    For instance, you can check for your particular error by doing:

    switch oserr {
        case syscall.ENOENT:
            // Handle this error
        default:
            // Handle other errors
        }
    }
    

    In general, it's very convenient to use fmt.Printf when debugging these sort of issues. In the example above:

    fmt.Println(err)
    

    prints

    rename /Users/t/pprof /Users/t/pprof2: operation not permitted
    

    where-as

    fmt.Printf("%#v
    ", err)
    

    prints

    &os.LinkError{Op:"rename", Old:"/Users/t/pprof", New:"/Users/t/pprof2", Err:0x1}
    

    giving details on the actual error, and not just its string representation.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料