文件读取

os.File

封装了文件相关操作

type File
File代表一个打开的文件对象

func Create(name string) (file *File, err error)
  • Create采用模式0666(任何人都可以读写,不可执行)创建一个名为name的文件,
  • 如果文件已存在会截断它(为空文件).
  • 如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。
  • 如果出错,错误底层类型是*PathError。
func Open(name string) (file *File, err error)

Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;
对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
  • OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。
  • 它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。
  • 如果操作成功,返回的文件对象可用于I/O。
  • 如果出错,错误底层类型是*PathError。
func NewFile(fd uintptr, name string) *File

NewFile使用给出的Unix文件描述符和名称创建一个文件

func Pipe() (r *File, w *File, err error)

Pipe返回一对关联的文件对象。从r的读取将返回写入w的数据。
本函数会返回两个文件对象和可能的错误。

func (f *File) Name() string

Name方法返回(提供给Open/Create等方法的) 文件名称。

func (f *File) Stat() (fi FileInfo, err errror)

Stat返回描述文件f的FileInfo类型值。如果出错,错误底怪类型是*PathError。

func (f *File) Fd() uintptr

Fd返回与文件f对应的整数类型的Unix文件描述符。

func (f *File) Chdir() error

Chdir将当前工作目录修改为f,f必须是一个目录。如果出错,错误底层类型是*PathError

func (f *File) Chmod(mode FileMode) error

Chmod修改文件的模式。如果出错,错误底层类型是*PathError

func (f *File) Chown(uid, git int) error

Chown修改文件的用户ID和组ID。如果出错,错误底怪类型是*PathError。

func (f *File) Readdir(n int) (fi []FileInfo, err error)
  • Readdir读取目录f的内容,返回一个有n个成员的[]FileInfo,这些FileInfo是被Lstat返回的,采用目录顺序。
  • 对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。
  • 如果n>0,Readdir函数会返回一个最多n个成员的切片。
  • 这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。
  • 如果到达了目录f的结尾,返回值err会是io.EOF.
  • 如果n<=0, Readdir函数返回目录中剩余所有文件对象的FileInfo构成的切片。
  • 此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。
  • 如果在到达结尾前遇到错误,会返回之前成功读取的FileInfo构成的切片和该错误。
func (f *File) Readdirnames(n int) (names []string, err error)
  • Readdir读取目录f的内容,返回一个有n个成员的[]string,切片成员为目录中文件对象的名字,采用目录顺序。
  • 对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息.
  • 如果n>0,Readdir函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。
  • 如果到达了目录f的结尾,返回值err会不io.EOF。
  • 如果n<=0,Readdir函数返回目录中剩余所有文件对象的名字构成的切片。此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。
  • 如果在到达结尾前遇到错误,会返回之前成功读取的名字构成的切片和该错误。
func (f *File) Truncate(size int64) error

Truncate改变文件的大小,它不会改变I/O的当前位置。如果截断文件,多出的部分就会被丢弃。如果出错,错误底层类型是*PathError。

func (f *File) Read(b []byte) (n int, err error)

Read方法从f中读取最多len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。文件终止标志是读取0个字节且返回值err为io.EOF。

func (f *File) ReadAt(b []byte, off int64) (n int, err error)

ReadAt从指定的位置(相对于文件开始位置) 读取len(b)字节数据并写入b。
它返回读取的字节数和可能遇到的任何错误。当n<len(b)时,本方法总是会返回错误;如果是因为到达文件结尾,返回值err会是io.EOF.

func (f *File) Write(b []byte) (n int, err error)

Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n != len(b), 本方法会返回一个非nil的错误。

func (f *File) WriteString(s string) (ret int, err error)

WriteString类似Write,但接受一个字符串参数.

func (f *File) WriteAt (b []byte, off int64) (n int,err error)

WriteAt在指定的位置(相对于文件开始位置) 写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n != len(b),本方法会返回一个非nil的错误。

func (f *File) Seek(offset int64, whence int) (ret int64,err error)

Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置: 0为相对文件开头,1为相对当前位置,2为相对文件结尾。
它返回新的偏移量(相对开头)和可能的错误.

func (f *File) Sync() (err error)

Sync递交文件的当前内容进行稳定的存储。一般来说,这表示将文件系统的最近写入的数据在内存中的拷贝刷新到硬盘中稳定保存。

func (f *File) Close() error

Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。

读写参数

文件打开模式:

const (
	O_RDONLY int = syscall.O_RDONLY    // 只读模式打开文件
	O_WRONLY int = syscall.O_WRONLY    // 只写模式打开文件
	O_RDWR   int = syscal.O_RDWR       // 读写模式打开文件
	O_APPEND int = syscall.O_APPEND    // 写操作时将数据附加到文件尾部
	O_CREATE int = syscall.O_CREAT     // 如果不存在将创建一个新文件
	O_EXCL   int = syscall.O_EXCL      // 打开文件用于同步I/O
	O_SYNC   int = syscall.O_SYNC      // 打开文件用于同步I/O
	O_TRUNC  int = syscall.O_TRUNC     // 如果可能,打开时清空文件
)

读取例子

os.Open || os.OpenFile

pacakge main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	// file, err := os.Open("/tmp/test")
	file, err := os.OpenFile("/tmp/test",os.O_CREATE|os.O_WRONLY,0666)
	if err != nil {
		fmt.Println("Open file error:",err)
		return
	}
	defer file.Close()    // 关闭文件
	
	reader := bufio.NewReader(file)   //带缓冲区的读写
	for {
		str, err := reader.ReadString('\n')  //循环读取一行
		if err != nil {
			fmt.Println("read string failed, err: ",err)
			return
		}
		fmt.Println("read string is %s: ",str)
	}
}

readline

一行一行的读取文件内容

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	file, err := os.Open("/tmp/test.log")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	var line []byte
	for {
		data, prefix, err := reader.ReadLine()
		if err == io.EOF {
			break
		}
		line = append(line, data...)
		if !prefix {
			fmt.Printf("data:%s\n",string(line))
			line = line[:]
		}
	}
}

读取整个文件例子

"io/ioutil"包实现了读取整个文件功能

package main

import (
	"fmt"
	"os"
	"io/ioutil"
)

func main() {
	fileName := "/tmp/test"
	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_RDWR, 0666)
	if err != nil {
		fmt.Println("Open file error: ",err)
		return
	}
	defer file.Close()
	buf, err := ioutil.ReadAll(file)
	// buf, err := ioutil.ReadFile(fileName)
	if err != nil {
		fmt.Fprintf(os.Stderr, "File Error: %s\n",err)
		return
	}
	fmt.Printf("%s\n",string(buf))
}


读取压缩文件

"compress/*" 包实现压缩文件功能
"compress/gzip" 包实现了gzip格式压缩文件的读写

package main

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"os"
)

func main() {
	fileName := "/tmp/test.log.gz"
	var r *bufio.Reader
	fi, err := os.Open(fileName)
	if err != nil {
		fmt.Println("error",err)
		os.Exit(1)
	}
	
	fz, err := gzip.NewReader(fi)
	if err != nil {
		fmt.Println("error",err)
		return
	}
	
	r = bufio.NewReader(fz)
	for {
		line, err := r.ReadString('\n')
		if err != nil {
			fmt.Println("Done reading file")
			return
		}
		fmt.Println(line)
	}
}

文件写入

file.WriteString || file.Write

package main

import (
	"fmt"
	"os"
)

func main() {
	fileName := "/tmp/test_write"
	
	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println("error",err)
		os.Exit(1)
	}
	defer file.Close()
	fileString := "Today very happy."
	file.Seek(0,2)  // 最后增加
	file.WriteString(fileString)
	// file.Write([]byte(fileString))
}

bufio.Writer.WriteString

带缓冲的写,最后要将缓冲中的数据写入下层的io.Writer接口(Flush方法)

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	fileName := "/tmp/test_write"
	file, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0755)
	if err != nil {
		fmt.Println("error",err)
		os.Exit(1)
	}
	defer file.Close()
	
	fileWrite := bufio.NewWriter(file)
	fileString := "good.\n"
	for i := 0; i < 10; i++ {
		fileWrite.WriteString(fileString)
	}
	fileWrite.Flush()
}

拷贝文件

从一个文件拷贝到另一个文件

package main

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

func CopyFile(dstName, srcName string) (writeen int64,err error) {
	src, err := os.Open(dstName)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer src.Close()
	
	dst, err := os.OpenFile(srcName, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer dst.Close()
	return io.Copy(dst, src)
}

func main() {
	CopyFile("/tmp/test","/tmp/test_copy1")
	fmt.Println("copy done.")
}

判断文件或文件夹是否存在

func PathExists(path string) (bool, error) {
	/*
	判断文件或目录是否存在
	如果返回的错误为nil,说明文件或目录存在
	如果返回的错误类型使用os.IsNotExits()判断为true,说明文件或文件夹不存在
	如果返回的错误为其它类型,则不确定是否存在
	*/
	_, err := os.Stat(path)
	if err == nil {
		return true,nil
	}
	if os.InNotExist(err) {
		return false,nil
	}
	return false, err
}