【问题标题】:Read file and display its contents in Go读取文件并在 Go 中显示其内容
【发布时间】:2017-10-21 12:35:59
【问题描述】:

我是 Go 新手,我想做一个简单的程序,从用户读取文件名并将其内容显示给用户。这是我目前所拥有的:

fname := "D:\myfolder\file.txt"

f, err := os.Open(fname)
if err != nil {
    fmt.Println(err)
}

var buff []byte
defer f.Close()
buff = make([]byte, 1024)
for {
    n, err := f.Read(buff)

    if n > 0 {
        fmt.Println(string(buff[:n]))
    }
    if err == io.EOF {
        break
    }
}

但我得到错误:

文件名、目录名或卷标语法不正确。

【问题讨论】:

  • 大概如果你 cd 到 myfolder 并将路径更改为 file.txt 它可以工作吗?

标签: go


【解决方案1】:

我怀疑fname 中的反斜杠是原因。尝试使用双反斜杠 (\\)。

【讨论】:

    【解决方案2】:

    将文件名放在反引号中。这使它成为原始字符串文字。对于原始字符串文字,不会处理诸如\f 之类的转义序列。

    fname := `D:\myfolder\file.txt`
    

    【讨论】:

      【解决方案3】:

      您也可以改用 unix '/' 路径分隔符。 做这项工作。

      fname := "D:/myfolder/file.txt"
      

      【讨论】:

        【解决方案4】:

        恭喜你学习围棋!虽然问题是关于示例中的特定错误,但让我们逐行分解并了解一些可能遇到的其他问题:

        fname := "D:\myfolder\file.txt"
        

        与 C 和许多其他语言一样,Go 使用反斜杠字符作为“转义序列”。也就是说,某些以反斜杠开头的字符会被翻译成其他难以看到的其他字符(例如,\t 变成制表符,否则可能无法与空格区分开来)。

        解决方法是使用未处理转义序列的原始字符串文字(使用反引号而不是引号):

        fname := `D:\myfolder\file.txt`
        

        这通过删除无效的\m\f 转义序列来修复您看到的初始错误。阅读 Go 规范的 String Literals 部分可以找到完整的转义序列列表和更多解释。

        f, err := os.Open(fname)
        if err != nil {
            fmt.Println(err)
        }
        

        这个chunk的第一行很好,但可以改进。如果发生错误,我们的程序没有理由继续执行,因为我们甚至无法打开文件,所以我们应该打印它(可能是标准错误)并退出,最好使用非零退出状态来指示发生了不好的事情。另外,作为一个好习惯,如果打开文件成功,我们可能希望在函数结束时关闭文件。将它放在 Open 调用的正下方是常规的,并且在其他人阅读您的代码时更容易。我将其重写为:

        f, err := os.Open(fname)
        if err != nil {
            fmt.Fprintln(os.Stderr, err)
            os.Exit(2)
            // It is also common to replace these two lines with a call to log.Fatal
        }
        defer f.Close()
        

        最后一个块有点复杂,我们可以用多种方式重写它。现在它看起来像这样:

        var buff []byte
        defer f.Close()
        buff = make([]byte, 1024)
        for {
            n, err := f.Read(buff)
        
            if n > 0 {
                fmt.Println(string(buff[:n]))
            }
            if err == io.EOF {
                break
            }
        }
        

        但是我们不需要定义我们自己的缓冲,因为标准库为我们提供了bufiobytes 包,它们可以为我们做到这一点。不过,在这种情况下,我们可能不需要它们,因为我们也可以通过调用 io.Copy 来替换迭代,它自己进行内部缓冲。如果我们想使用自己的缓冲区,我们也可以使用其他副本变体之一,例如 io.CopyBuffer。它还缺少一些错误处理,所以我们将添加它。现在整个块变成:

        _, err := io.Copy(os.Stdout, f)
        if err != nil {
            fmt.Fprintf(os.Stderr, "Error reading from file: `%s'\n", err)
            os.Exit(2)
        }
        // We're done!
        

        【讨论】:

        • 非常感谢您的详细解释,这解决了我的问题,但是当我接受用户的路径时,它会出现同样的错误,func main(){ fmt.Println("Enter path : ") dirpath := bufio.NewReader(os.Stdin) 实际路径,_ := dirpath.ReadString('\n') fmt.Println("输入的路径",actualpath) 实际路径 = strings.TrimRight(actualpath,"\r\n") s:= []string{"",strings.TrimSpace(actualpath),""} newpath := strings.Join(s,"") fmt.Println(strings.Compare(D:\LMNTRIX\maillink.txt,newpath)) fmt.Println(newpath) comapre 返回 -1即使在清除 \r\n 后进入相同的路径
        • 这应该可以正常工作(并且在类 Unix 系统上对我来说也可以正常工作)。我会打印确切的字节(例如,使用像fmt.Fprintf("% x", newpath) 这样的格式字符串)并查看它们的不同之处。然后也许你可以弄清楚发生了什么。
        猜你喜欢
        • 2012-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-01
        • 2013-01-08
        • 2018-05-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多