[
](https://www.cnblogs.com/-beyond/p/9203272.html)
利用io/ioutil包一次性读取一个文件的所有内容—ReadFile
package mainimport ("fmt""os")func main() {//func ReadFile(filename string) ([]byte, error)data, err := os.ReadFile("./connect.go")if err != nil {fmt.Println(err)} else {fmt.Println(string(data))}}
分多次读,每次读取指定长度的文件内容—Read
package mainimport ("fmt""os")func main() {//func Open(name string) (*File, error)f, err := os.Open("./connect.go")defer f.Close() //注意要关闭文件if err != nil {panic(err)} else {buffer := make([]byte, 20)//func (f *File) Read(b []byte) (n int, err error)//使用Read方法,将文件内容读入buffer切片中length, err := f.Read(buffer)if err != nil {panic(err)} else {fmt.Println("读取了", length, "字节内容")fmt.Println(string(buffer))}//第二次读取,会接着上一次的位置继续读length, err = f.Read(buffer)if err != nil {panic(err)} else {fmt.Println("读取了", length, "字节内容")fmt.Println(string(buffer))}}}
注意,使用os的Read时,
1、如果文件的内容长度大于buffer切片的长度,那么,只会读取文件buffer切片长度的内容,返回的长度就是切片的长度。
2、如果文件内容小于切片的长度,那么会读出文件的所有内容,返回的长度就是读入buffer的实际长度。
3、如果执行多次从文件中读取,那么后面一次读取都会在前面一次读取结束的位置那里接着继续读。
4、如果
从指定位置开始读—Seek、ReadAt
//设置游标//func (f *File) Seek(offset int64, whence int) (ret int64, err error)length, err := f.Seek(3, 1)
先说第二个参数,可以使0,1,2:
0表示相对于文件的原点,从文件的开头往后offset个字符的位置处开始读。
1 表示相对于当前偏移量,即已经读过至少一次了,游标此时不在文件原点,而在其他地方,从那个地方往后offset字符的位置处开始读。
2 表示相对于末尾,将文件的末尾作为原点,offset一般为负数,表示从文件末尾往前数offset个字符开始读。
//从文件的起始位置开始的往后offset位置开始读//func (f *File) ReadAt(b []byte, off int64) (n int, err error)length, err := f.ReadAt(buffer, 5)
使用os和io包实现io/ioutil包的ReadFile
func ReadFile(filename string) {f, err := os.Open(filename)defer f.Close() //注意要关闭文件if err != nil {panic(err)} else {buffer := make([]byte, 20)//循环读取for {length, err := f.Read(buffer)//如果错误信息是其他类型的,则直接panicif err != nil && err != io.EOF {panic(err)}//fmt.Println("读取了", length, "字节内容")if length == 20 {fmt.Print(string(buffer))} else {fmt.Print(string(buffer[0:]))}//注意,错误信息是以io包的EOF时,表示读取到文件末尾if err == io.EOF {fmt.Println("读取完毕")break}}}}
使用bufio包输出每一行的内容,并统计行数
f, err := os.Open("connect.go")defer f.Close()if err != nil {panic(err)}//func NewReader(rd io.Reader) *Readerreader := bufio.NewReader(f)totLine := 0for {//func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)content, isPrefix, err := reader.ReadLine()fmt.Println(string(content), isPrefix, err)//当单行的内容超过缓冲区时,isPrefix会被置为真;否则为false;if !isPrefix {totLine++}if err == io.EOF {fmt.Println("一共有", totLine, "行内容")break}}
创建文件—Create
//创建文件//func Create(name string) (*File, error)newFile, err := os.Create("demo.txt")defer newFile.Close()if err != nil {panic(err)}
获取文件的信息—Stat
//获取文件信息//func Stat(name string) (FileInfo, error)info, err := os.Stat("test.txt")if err != nil {//func IsNotExist(err error) boolif os.IsNotExist(err) {panic("文件不存在")} else {panic(err) //其实err信息中就能看出来上一个判断是否成立,只是提示有这种判断方法而已}}fmt.Println(info.Name(), info.Size(), info.Mode())
创建并写入内容—WriteFile
path := "./demo.txt"content := "准备写入的内容"//func WriteFile(filename string, data []byte, perm os.FileMode) errorerr := ioutil.WriteFile(path, []byte(content), 0666)if err != nil {panic(err)}//读取内容data, err := ioutil.ReadFile(path)if err != nil {panic(err)}fmt.Println(string(data))
在文件指定位置出写入内容—WriteAt
path := "test.txt"f, err := os.Create(path)defer f.Close()if err != nil {panic(err)}//func (f *File) WriteAt(b []byte, off int64) (n int, err error)length, err := f.WriteAt([]byte("abcdefgh"), 0)if err != nil {panic(err)}fmt.Println(length) //8//abcdefgh//第二次写入length, err = f.WriteAt([]byte("xyz"), 3)if err != nil {panic(err)}fmt.Println(length) //3//abcxyzgh
通过buffer writer来写入文件内容
path := "test.txt"f, err := os.Create(path)defer f.Close()if err != nil {panic(err)}<br>//func NewWriter(w io.Writer) *WriterbufferWrite := bufio.NewWriter(f)if err != nil {panic(err)}demo := "1234567890"for _, v := range demo {//将数据写入缓冲区//func (b *Writer) WriteString(s string) (int, error)bufferWrite.WriteString(string(v))}data, _ := ioutil.ReadFile(path)fmt.Println(string(data)) //空的内容//将缓冲区的数据写入文件//func (b *Writer) Flush() errorbufferWrite.Flush()data, _ = ioutil.ReadFile(path)fmt.Println(string(data)) //1234567890
