阅读文件并在Go

时间:2017-10-21 12:36:00

标签: go

我是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
    }
}

但我收到错误:

  

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

4 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

你也可以使用unix' /'而是路径分隔符。 这份工作。

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

答案 3 :(得分:0)

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

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)
}

这个块的第一行很好,但可以改进。如果发生错误,我们的程序没有理由继续执行,因为我们甚至无法打开文件,因此我们应该打印它(可能是标准错误)并退出,最好是非零退出状态表明发生了一些不好的事情。另外,作为一个好习惯,我们可能希望在函数结束时关闭文件,如果打开它成功的话。将它放在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执行自己的内部缓冲。如果我们想使用自己的缓冲区,我们也可以使用其他副本变体,如{{3}}。它也缺少一些错误处理,所以我们将添加它。现在整个块变成了:

_, 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!