调用Peek方法后,原始数据已更改

时间:2018-12-07 09:41:50

标签: go

package main

import (
    "bufio"
    "io"
    "golang.org/x/net/html/charset"
    "golang.org/x/text/encoding"
    "net/http"
    "fmt"
    "golang.org/x/text/transform"
    "io/ioutil"
)
// main 
func main() {
    resp, err := http.Get("http://www.baidu.com")
    if err != nil {
        panic(err)
    }

    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        fmt.Println("Error: status code", resp.StatusCode)
        return
    }

    e := determineEncoding(resp.Body)
    utf8Reader := transform.NewReader(resp.Body, e.NewDecoder())

    all, err := ioutil.ReadAll(utf8Reader)
    if err != nil {
        panic(err)
    }

    fmt.Printf("%s\n", all)
}

// determine
func determineEncoding(r io.Reader) encoding.Encoding {
    reader := bufio.NewReader(r)
    // The start position was not correct
    bytes, err := reader.Peek(1024)
    if err != nil {
        panic(err)
    }

    e, _, _ := charset.DetermineEncoding(bytes, "")

    return e
}

结果不是正确的数据。起始位置不为零。


如文档所述,“ Peek返回下n个字节,而不会提高阅读器。字节在下一个读取调用时停止有效。如果Peek返回的字节数少于n个字节,则它还会返回一个错误,解释为什么读取短。如果n大于b的缓冲区大小,则错误为ErrBufferFull。'

1 个答案:

答案 0 :(得分:1)

  

Peek返回下一个n个字节,而不会使阅读器前进。

这是指*bufio.Reader,而不是基础读者。如有必要,缓冲的读取器 将从基础读取器中读取。否则它将如何返回字节?

在您的情况下,您必须在调用determineEncoding之后直接停止使用响应正文,而改用* bufio.Reader。

例如:

func determineEncoding(r *bufio.Reader) encoding.Encoding {
    bytes, err := r.Peek(1024)

    // as before
}

func main() {
    // as before

    defer resp.Body.Close()

    r := bufio.NewReader(resp.Body)
    e := determineEncoding(r)
    utf8Reader := transform.NewReader(r, e.NewDecoder())

    // as before
}