2016-10-11 79 views
0

练习7.5练习:
io包中的LimitReader函数接受一个io.Readerr和字节数n的,并返回另一个Readerr读取,但报告的结束文件状况在n字节之后。实施它。如何实现中去编程语言

func LimitReader(r io.Reader, n int64) io.Reader 

如何实现它?


下面是我的代码,我知道它不对。

type MyReader struct { 
    bytes []byte 
    length int 
} 

func (myReader *MyReader) Read (p []byte) (int, error) { 
    fmt.Println("be invoked") 
    myReader.bytes = p 
    myReader.length = len(p) 
    fmt.Printf("lenght: %d\n" , myReader.length) 
    return len(p), nil 
} 
func LimitReader(r io.Reader, n int64) io.Reader { 
    filecontent, _:= ioutil.ReadFile("./testfile.txt") 
    r.Read(filecontent[:n]) 
    return r 
} 

func main() { 
    myReader := &MyReader{} 
    r := LimitReader(myReader, 100) 
    filecontent, _:= ioutil.ReadFile("./testfile.txt") 
    fmt.Println(r.Read(filecontent)) 
} 
+1

你有一个具体的问题,我们可以帮助您? – jcbwlkr

+2

也许看看[io.Reader]的文档(https://golang.org/pkg/io/#Reader) – jcbwlkr

+0

我认为最好是编写自己的代码(尽管不完整或不工作),并要求http://codereview.stackexchange.com/的评论。 – philipjkim

回答

2

看来你不清楚你需要做什么的概念。

您需要创建一个函数具有以下签名:

func LimitReader(r io.Reader, n int64) io.Reader 

也就是说,rio.Readern数传递给它,你必须返回一个新的io.Reader。当有人从返回阅读器读取,读取的数据必须来自通过r阅读器,它应该自动计数读取字节;并且如果读取字节超过n号码,则其不得r读取更多字节,但返回io.EOF,其用于指示到达流的末尾。可能是因为r阅读器有更多的字节(意味着可以从中读取更多的字节),但不应读取和返回:这就是LimitedReader的用途。

如果您认为您现在已经了解该问题,请立即停止阅读答案,并尝试自行实施。以下是一个示例解决方案。


这个确切的功能已经存在于io包,并通过同名云:io.LimitReader()

// LimitReader returns a Reader that reads from r 
// but stops with EOF after n bytes. 
// The underlying implementation is a *LimitedReader. 
func LimitReader(r Reader, n int64) Reader { return &LimitedReader{r, n} } 

它返回的*io.LimitedReader的值,它的实现是这样的:

// A LimitedReader reads from R but limits the amount of 
// data returned to just N bytes. Each call to Read 
// updates N to reflect the new amount remaining. 
type LimitedReader struct { 
    R Reader // underlying reader 
    N int64 // max bytes remaining 
} 

func (l *LimitedReader) Read(p []byte) (n int, err error) { 
    if l.N <= 0 { 
     return 0, EOF 
    } 
    if int64(len(p)) > l.N { 
     p = p[0:l.N] 
    } 
    n, err = l.R.Read(p) 
    l.N -= int64(n) 
    return 
} 

需要一分钟或2至尝试自己理解代码。如果你被卡住或者没有一切都清楚,请继续阅读。

解释的代码:

io.LimitedReader是一个结构,其中包含源读者它从读取,并且可以仍然不必报告io.EOF读取的字节数。因此,LimitReader()只是简单地返回此结构的值,其中参数rn被分配给结构的字段RN。更具体地说,返回该结构的地址,因为LimitedReader.Read()具有指针接收器,因此只有指向它的指针实现io.Reader。它有一个指针接收器,因为Read()方法(可能)修改结构的字段,所以需要一个指针才能做到这一点(否则只有一个副本会被修改,在Read()方法返回后将被丢弃)。

LimitedReader.Read()首先检查N领域,它告诉我们多少字节可以退货,如果没有更多的“允许”,是一个乖巧有限公司阅读器,它返回io.EOF immedately不读从更多的数据来源:

if l.N <= 0 { 
    return 0, EOF 
} 

如果N为正,这意味着一些字节可以读取和返回,但不超过N,所以如果p片传递给Read()具有更大的长度,我们重新切片这么给源阅读器的调用将无法读取超过了我们应该允许:

if int64(len(p)) > l.N { 
    p = p[0:l.N] 
} 

而最后一部分是什么更多的,真正做阅读,从源头读者:

n, err = l.R.Read(p) 

它返回实际读取的字节数和一个可选错误(无论读取是否遇到一些错误)。由于我们即将返回这些,我们有管理的字节这个量现在回来了,我们必须从允许的剩余字节减去此:

l.N -= int64(n) 
return