英文:
Golang check if string is valid path
问题
Golang filepath模块(https://golang.org/pkg/path/filepath/)包含一些用于操作路径的函数,os.Stat
函数可以用于检查文件是否存在。是否有一种方法可以检查一个字符串是否实际上形成了一个有效的路径(无论该路径上是否存在文件)?
英文:
The Golang filepath module (https://golang.org/pkg/path/filepath/) contains a few functions for manipulating paths and os.Stat
can be used to check if a file exists. Is there a way to check if a string actually forms a valid path at all (regardless of whether there's a file at that path or not)?
答案1
得分: 24
这个问题听起来很简单,但实际上并不简单。我找到了两种可能的解决方案:
解决方案1 - 学术方法
这个思路是基于规则检查给定的文件路径。
问题:
- 操作系统(UNIX / Windows)
- 文件系统
- 保留关键字
操作系统:
第一个问题是最简单的。Go语言提供了各种用于特定操作系统的文件名/分隔符等工具。
在os包中的示例:
const (
PathSeparator = '/' // 特定操作系统的路径分隔符
PathListSeparator = ':' // 特定操作系统的路径列表分隔符
)
在filepath包中的另一个示例:
// VolumeName返回前导卷名。
// 给定"C:\foo\bar",在Windows上返回"C:"。
// 给定"\\host\share\foo",返回"\\host\share"。
// 在其他平台上返回""。
func VolumeName(path string) string {
return path[:volumeNameLen(path)]
}
文件系统:
文件系统有不同的限制。允许的最大长度或字符集可能会有所不同。不幸的是,你无法知道你的路径将穿越哪些文件系统(至少据我所知)。
保留关键字:
为给定的操作系统建立一个保留关键字的黑名单。
实现:
权衡之处在于它不能保证100%的文件路径有效。
解决方案2 - 经验法
尝试创建文件,然后立即删除它。
func IsValid(fp string) bool {
// 检查文件是否已经存在
if _, err := os.Stat(fp); err == nil {
return true
}
// 尝试创建文件
var d []byte
if err := ioutil.WriteFile(fp, d, 0644); err == nil {
os.Remove(fp) // 然后删除文件
return true
}
return false
}
这个解决方案的主要优点是简单直接,更准确。如果在给定路径上已经存在文件或者可以创建文件,那么它就是有效的。然而,由于受限访问权限,这个解决方案也可能将有效路径视为无效。
总结
第一个解决方案比第二个解决方案更不准确,尽管从纯粹主义的角度来看更正确。你应该根据自己的需求选择解决方案。你更喜欢假阳性还是假阴性?第一个解决方案可能会给出假阳性,而第二个解决方案可能会给出假阴性。
英文:
This problem sounds very simple, but it is actually not. Here is two possible solutions that I found :
Solution 1 - Academic
The idea here is to check a given filepath based on rules.
##Problems
- Operating system (UNIX / Windows)
- Filesystem
- Reserved keywords
Operating system
The first one is the easiest. Go provides various tools for OS-specific filenames/separators/...
Example in the os package:
const (
PathSeparator = '/' // OS-specific path separator
PathListSeparator = ':' // OS-specific path list separator
)
Another one in the filepath package:
// VolumeName returns leading volume name.
// Given "C:\foo\bar" it returns "C:" on Windows.
// Given "\\host\share\foo" it returns "\\host\share".
// On other platforms it returns "".
func VolumeName(path string) string {
return path[:volumeNameLen(path)]
}
Filesystem
Filesystems have different restrictions. The maximum length or the charset allowed may vary. Unfortunately, there is no way you can tell (not as far as I know at least) which filesystem(s) your path will traverse.
Reserved keywords
Have a blacklist of all reserved keywords for a given OS.
##Implementation
For this solution, I would build a lexer/parser.
The tradeoff is that it would not guarantee 100% that a filepath is valid.
Solution 2 - Empirical
Attempt to create the file and delete it right after.
func IsValid(fp string) bool {
// Check if file already exists
if _, err := os.Stat(fp); err == nil {
return true
}
// Attempt to create it
var d []byte
if err := ioutil.WriteFile(fp, d, 0644); err == nil {
os.Remove(fp) // And delete it
return true
}
return false
}
The main benefit of this solution is that it is straightforward and more accurate. If a file already exists or can be created at a given path, it means it is valid. However, this solution can also invalidate valid paths because of restricted access.
#Summary
The first solution will be less accurate than the second one, even though more correct from a puristic point of view. The solution you should pick up depends on your need. Do you prefer false positives or false negatives? The first solution can give you false positives, while the second one false negatives.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论