英文:
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() 并返回遇到的任何错误。
>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)
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论