关于*osFile.Read() 读取的问题

zhangsheng1992 · 2017-08-02 03:21:42 · 1084 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-08-02 03:21:42 的主题,其中的信息可能已经有所发展或是发生改变。

我有一个文件a.txt 里面的内容为 1,2,3,4,5,6,7 (每个数字单独一行)

然后读取文件的内容

func main() {
    readFile, err := os.Open("a.txt")
    buf := make([]byte, 10)
    for {
        n, _ := readFile.Read(buf)
        fmt.Println(string(buf), "读取子节:", n)
        if n == 0 {
            break
        }
    }
}

运行结果为:

1
2
3
4
5

读取子节:

10
6
7
3 // 问题在这
4
5

读取子节:

4
6
7
3
4
5
读取子节:0

1234567都读取完后 为什么会从345再读一遍呢 buf中剩余的6个子节不是应该填充默认值么

我理解的是假设读到文件的eof位置时,还会继续读取,但奇怪的是为什么不从12开始呢

刚入坑 有些地方不太理解 还请大神赐教


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1084 次点击  
加入收藏 微博
6 回复  |  直到 2017-08-02 06:48:14
sunanxiang
sunanxiang · #1 · 8年之前

没有再读一遍,只是上次读完残留的。第一次读五个数12345,下次还是这个buf,但是只读了两个数6和7,把buf里面的1和2给替换掉了,所以会出现67345。

sunanxiang
sunanxiang · #2 · 8年之前

func main() {
    readFile, err := os.Open("a.txt")

    for {
        buf := make([]byte, 12)

        n, _ := readFile.Read(buf)
        if n == 0 {
            break
        }
        fmt.Println(string(buf), "读取子节:", n)
    }
}

这样应该是满足你要求的。
specita
specita · #3 · 8年之前

读到文件EOF不会继续读取,你看到的345是你第一次读取到buf中的 不要忽略golang函数返回的err, n,err := readFile.Read(buf),然后判断err == EOF来判断是否读取结束,而不是用n==0来判断 其实你只需要看一下readFile.Read这个方法的注释你就全都明白了

littleFish
littleFish · #4 · 8年之前

先贴代码

package main

import (
    "fmt"
    "os"
    "log"
    "io"
)

func main() {
    rf, err := os.Open("a.txt")
    //os.OpenFile("a.txt", os.O_RDWR, 0)
    if err != nil {
        log.Println("文件读取失败, 原因为: ", err)
        os.Exit(1)
    }
    defer rf.Close()
    chunks := make([]byte,10)
    buf := make([]byte, 10)  // len(buf) = 10, cap(buf) = 10, 初始值为0  byte=unit8 0~255
    for {
        n, err := rf.Read(buf)
        if err != nil && err != io.EOF {
            log.Println("读取失败, 原因为: ", err)
            os.Exit(1)
        }else if err == io.EOF {
            break
        }
        if n == 0 {
            break
        }

        chunks = append(chunks, buf[:n]...)
    }
    fmt.Println(string(chunks))
}

func make(Type, size IntegerType) Type这个函数是会指定默认初始值。但是, 你的问题是当slice的长度大于容量时, 此时将动态分配新的数组空间, 指向这个指针地址。 而新开辟的数组空间为当前slice的默认值。 1_2_3_45 当字节到达指定cap时, 开辟新空间 1_2_3_45 第二次赋值仅仅将6_7替换掉

littleFish
littleFish · #5 · 8年之前

先贴代码


package main

import (
    "fmt"
    "os"
    "log"
    "io"
)

func main() {
    rf, err := os.Open("a.txt")
    //os.OpenFile("a.txt", os.O_RDWR, 0)
    if err != nil {
        log.Println("文件读取失败, 原因为: ", err)
        os.Exit(1)
    }
    defer rf.Close()
    chunks := make([]byte,10)
    buf := make([]byte, 10)  // len(buf) = 10, cap(buf) = 10, 初始值为0  byte=unit8 0~255
    for {
        n, err := rf.Read(buf)
        if err != nil && err != io.EOF {
            log.Println("读取失败, 原因为: ", err)
            os.Exit(1)
        }else if err == io.EOF {
            break
        }
        if n == 0 {
            break
        }

        chunks = append(chunks, buf[:n]...)
    }
    fmt.Println(string(chunks))
}

func make(Type, size IntegerType) Type这个函数是会指定默认初始值。但是, 你的问题是当slice的长度大于容量时, 此时将动态分配新的数组空间, 指向这个指针地址。 而新开辟的数组空间为当前slice的默认值。 1_2_3_45 当字节到达指定cap时, 开辟新空间 1_2_3_45 第二次赋值仅仅将6_7替换掉

littleFish
littleFish · #6 · 8年之前

如果你把buf := make([]byte, 10) 替换为 buf := make([]byte, 11) 类似如上逻辑, 空_代替换行符

1_2_3_4_5_6
1_2_3_4_5_6
_72_3_4_5_6

则会出现

1
2
3
4
5
6
72
3
4
5
6
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传