如何检查 ioutil.ReadFile 返回的错误中的特定类型错误?

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

How do I check for specific types of error among those returned by ioutil.ReadFile?

问题

当我使用ioutil读取文件时,可能会返回一个错误。但是如果我想要过滤一些错误代码,我应该怎么做?

在上面的代码片段中,当文件没有权限时,fmt.Println(err.Error())会打印"open xxxxx: permission denied"
如果我想捕获这种错误,我如何知道文件读取失败是因为权限被拒绝?

我应该搜索err.Error()中的字符串permission denied - 这看起来不太优雅。有没有更好的方法?

提前感谢。

更新

在尝试了@Intermernet的解决方案后,我发现它不会触发case os.ErrPermission,它会触发default并打印"open xxx: Permission denied"

@Aedolon的解决方案是可以的,os.IsPermission(err)可以判断文件是否因为权限被拒绝而失败。

英文:

When I use ioutil to read a file, it may return an error. But if I want to filter some error code, what should I do?

res, err := ioutil.ReadFile("xxx")
if err != nil {
    fmt.Println(err.Error())  
}
...

In the code snippet above, when a file has no permission, fmt.Println(err.Error()) will print "open xxxxx: permission denied.
If I want to capture this kind error, how can I know that file read failed because permission was denied?

Should I search err.Error() for the string permission denied - this looks ungraceful. Is there any better way?

Thanks in advance.

Update

After trying @Intermernet solution, I found that it will not hit case os.ErrPermission, it will hit default and print "open xxx: Permission denied".

@Aedolon solution is ok, os.IsPermission(err) can tell that a file has failed with permission deny.

答案1

得分: 11

根据当前的API,ioutil.ReadFile除了在成功时返回err == nil之外,不保证任何特定的行为。即使是syscall包也不能保证具体的错误。

ioutil.ReadFile的当前实现使用了os.Open,当无法打开文件时,它会返回*os.PathError,而不是os.ErrPermission或其他任何错误。os.PathError包含一个名为Err的字段,它也是一个错误 - 在这种情况下,是一个syscall.Errno。字符串"permission denied"是从一个私有的错误消息表中生成的,它是与架构和实现相关的。在我的Windows机器上,它显示为"Access is denied"。

据我所知,正确的方法是使用os.IsPermission(err),当缺少权限时它会返回true

英文:

According to the current API, ioutil.ReadFile doesn't guarantee any specific behaviour except that it will return err == nil when successful. Even the syscall package doesn't actually guarantee a specific error.

The current implementation of ioutil.ReadFile uses os.Open, which will return *os.PathError when failing to open a file, not os.ErrPermission or anything else. os.PathError contains a field Err which is also an error - in this case, a syscall.Errno. The string "permission denied" is produced from a private table of error messages and it's both architecture and implementation-specific. In my Windows machine it says "Access is denied" instead.

AFAIK, the correct method is to use os.IsPermission(err), which will return true in case of lacking permissions.

答案2

得分: 4

根据文档,应该使用errors.Is函数来测试返回的错误。

var (
    // ErrInvalid 表示无效的参数。
    // 当接收者为nil时,File上的方法将返回此错误。
    ErrInvalid = errInvalid() // "invalid argument"

    ErrPermission = errPermission() // "permission denied"
    ErrExist      = errExist()      // "file already exists"
    ErrNotExist   = errNotExist()   // "file does not exist"
    ErrClosed     = errClosed()     // "file already closed"
    ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
)

示例代码如下:

f, err := ioutil.ReadFile("your_file")

if err != nil {
    if errors.Is(err, os.ErrNotExist) {
        // 处理文件不存在的情况
    } else if errors.Is(err, os.ErrPermission) {
        // 处理权限被拒绝的情况
    } else {
        panic(err)
    }
}
英文:

Per documentation, errors returned should be tested against these errors using errors.Is

var (
// ErrInvalid indicates an invalid argument.
// Methods on File will return this error when the receiver is nil.
ErrInvalid = errInvalid() // "invalid argument"

ErrPermission = errPermission() // "permission denied"
ErrExist      = errExist()      // "file already exists"
ErrNotExist   = errNotExist()   // "file does not exist"
ErrClosed     = errClosed()     // "file already closed"
ErrNoDeadline = errNoDeadline() // "file type does not support deadline"
)

As an example:

f, err := ioutil.ReadFile("your_file")

if err != nil {
	if errors.Is(err, os.ErrNotExist) {
		// your code
	} else if errors.Is(err, os.ErrPermission) {
		// your code
	} else {
		panic(err)
	}
}

答案3

得分: 2

ioutil.ReadFile() 调用 os.Open() 并返回遇到的任何错误。

os 定义了一些与文件相关的错误

>ErrInvalid = errors.New("无效的参数")
ErrPermission = errors.New("权限被拒绝")
ErrExist = errors.New("文件已存在")
ErrNotExist = errors.New("文件不存在")

你需要的是 os.ErrPermission

res, err := ioutil.ReadFile("xxx")
if err != nil {
	switch err {
	case os.ErrInvalid:
		//处理逻辑
	case os.ErrPermission:
		//处理逻辑
	case os.ErrNotExist:
		//处理逻辑
	default:
		fmt.Println(err)
	}
}
英文:

ioutil.ReadFile() calls os.Open() and returns any error encountered there.

The os package defines some file related errors.

>ErrInvalid = errors.New("invalid argument")
ErrPermission = errors.New("permission denied")
ErrExist = errors.New("file already exists")
ErrNotExist = errors.New("file does not exist")

The one you're after is os.ErrPermission.

res, err := ioutil.ReadFile("xxx")
if err != nil {
	switch err {
	case os.ErrInvalid:
		//Do stuff
	case os.ErrPermission:
		//Do stuff
	case os.ErrNotExist:
		//Do stuff
	default:
		fmt.Println(err)
	}
}

huangapple
  • 本文由 发表于 2014年5月4日 11:04:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/23452157.html
匿名

发表评论

匿名网友

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

确定