目录操作
创建名称为name的目录,权限设置是perm,例如0777
func Mkdir(name string, perm FileMode) error
根据path创建多级子目录,例如test/test1/test2。
func MkdirAll(path string, perm FileMode) error
删除名称为name的目录,当目录下有文件或者其他目录时会出错
func Remove(name string) error
根据path删除多级子目录,如果path是单个名称,那么该目录下的子目录全部删除。
func RemoveAll(path string) error
eg:
package mainimport ("fmt""os")func main() {os.Mkdir("test", 0777)os.MkdirAll("test/test1/test2", 0777)err := os.Remove("test")if err != nil {fmt.Println(err)}os.RemoveAll("test")}
创建文件
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
func Create(name string) (file *File, err Error)
根据文件描述符创建相应的文件,返回一个文件对象
func NewFile(fd uintptr, name string) *File
读取文件
open
该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile。
func Open(name string) (file *File, err Error)
为了防止文件忘记关闭,我们通常使用defer注册文件关闭语句。eg:
package mainimport ("fmt""os")func main() {// 只读方式打开程序同级目录下的word.txtfile, err := os.Open("word.txt")if err != nil {fmt.Println( err)return}// 关闭文件defer file.Close()}
OpenFile
函数签名如下
func OpenFile(name string, flag int, perm FileMode) (*File, error)
OpenFile函数的第二个参数是文件的打开模式:
const (// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.O_RDONLY int = syscall.O_RDONLY // 只读模式O_WRONLY int = syscall.O_WRONLY //只写模式O_RDWR int = syscall.O_RDWR // 读写混合模式// The remaining values may be or'ed in to control behavior.O_APPEND int = syscall.O_APPEND // 写模式的时候将数据附加到文件末尾O_CREATE int = syscall.O_CREAT // 文件如果不存在就新建O_EXCL int = syscall.O_EXCL // 和 O_CREATE模式一起使用, 文件必须不存在O_SYNC int = syscall.O_SYNC //打开文件用于同步 I/O.O_TRUNC int = syscall.O_TRUNC // 打开文件时清空文件)
前面三种是文件打开模式,后面五种是打开文件之后相应的操作模式;前面三个你只能选择一个,后面可以多选,中间用”|”隔开。
OpenFile函数的第三个参数perm是文件的权限,跟linux文件权限一致,一个八进制数。r(读)04,w(写)02,x(执行)01。
r ——> 004w ——> 002x ——> 001
// Open opens the named file for reading. If successful, methods on// the returned file can be used for reading; the associated file// descriptor has mode O_RDONLY.// If there is an error, it will be of type *PathError.func Open(name string) (*File, error) {return OpenFile(name, O_RDONLY, 0)}// Create creates or truncates the named file. If the file already exists,// it is truncated. If the file does not exist, it is created with mode 0666// (before umask). If successful, methods on the returned File can// be used for I/O; the associated file descriptor has mode O_RDWR.// If there is an error, it will be of type *PathError.func Create(name string) (*File, error) {return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)}
open 函数和Create 底层都是调用的OpenFile函数
// OpenFile is the generalized open call; most users will use Open// or Create instead. It opens the named file with specified flag// (O_RDONLY etc.). If the file does not exist, and the O_CREATE flag// is passed, it is created with mode perm (before umask). If successful,// methods on the returned File can be used for I/O.// If there is an error, it will be of type *PathError.func OpenFile(name string, flag int, perm FileMode) (*File, error)
Read
读取数据到b中,最大可以读取一个1G 文件
func (file *File) Read(b []byte) (n int, err Error)
eg:
package mainimport ("fmt""os")func main() {fileName := "testFile"currFile,err:=os.Create(fileName)if err!= nil {fmt.Println(err,currFile);}currFile.WriteString("hello world\n")currFile.Write([]byte("hello go\n"))currFile,err = os.Open(fileName);defer currFile.Close()buf := make([]byte,1024)for {n,_:=currFile.Read(buf)if 0==n {break}os.Stdout.Write(buf[:n])}}
从off开始读取数据到b中
func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
准备测试文件word.txt
白日依山尽黄河入海流欲穷千里目更上一层楼
package mainimport ("fmt""os")func main() {file, err := os.Open("word.txt")if err != nil {fmt.Println(err)}defer file.Close()buf := make([]byte, 1024)offset := 0for {n, err := file.ReadAt(buf, int64(offset))if len(buf) > 0 {fmt.Println(string(buf))}if err != nil {fmt.Println(err)break}offset = offset + n}}
字节推荐选择2的n次方数数值,不然在中文混合中偏移量就是个坑
bufio.NewReader
package mainimport ("bufio""fmt""io""os")func main() {file, err := os.Open("word.txt")if err != nil {fmt.Println(err)return}defer file.Close()reader := bufio.NewReader(file)for {line, err := reader.ReadString('\n') //按行读取if err == io.EOF {fmt.Println("文件读完了")break}if err != nil {fmt.Println("read file failed, err:", err)break}fmt.Print(line)}}
也可以直接调用ReadLine()函数
package mainimport ("bufio""fmt""io""os")func main() {file, err := os.Open("word.txt")if err != nil {fmt.Println(err)}defer file.Close()reader := bufio.NewReader(file)for {line, _, err := reader.ReadLine()if err == io.EOF {break}if err != nil {fmt.Println(err)break}fmt.Println(string(line))}}
ioutil.Readxxx
io/ioutil包的ReadFile方法能够读取完整的文件,只需要将文件名作为参数传入。
package mainimport ("fmt""io/ioutil")func main() {content, err := ioutil.ReadFile("word.txt")if err != nil {fmt.Println("read file failed, err:", err)return}fmt.Println(string(content))}
ReadAll 文件输入流
package mainimport ("fmt""io/ioutil""os")func main() {file, err := os.Open("word.txt")if err != nil {fmt.Println("read file failed, err:", err)return}defer file.Close()content, err := ioutil.ReadAll(file)if err != nil {fmt.Println("read content failed, err:", err)return}fmt.Println(string(content))}
文件写入
OpenFile()
os.OpenFile()函数不仅可以指定模式打开文件读文件,也可以指定响应的写模式从而实现文件写入功能。
os.O_RDWR|os.O_CREATE : 文件不存在会新建文件,文件如果存在,会从文件开始处用新内容覆盖原始内容,(如果新内容只有5个字符,原始内容有10个,那么只有开始5个是新内容,后面5个还是以前的内容)
os.O_RDWR|os.O_APPEND : 本次写入的值会在文件末尾进行append操作,不会覆盖以前的内容。
os.O_RDWR|os.O_TRUNC : 打开文件的时候先清空文件。
Writexx
Write
写入byte类型的信息到文件
func (file *File) Write(b []byte) (n int, err Error)
WriteAt
在指定位置开始写入byte类型的信息
func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
WriteString
写入string信息到文件
func (file *File) WriteString(s string) (ret int, err Error)
bufio.NewWriter
package mainimport ("bufio""fmt""os""strconv")func main() {file, err := os.OpenFile("word.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)if err != nil {fmt.Println("open file failed, err:", err)return}defer file.Close()writer := bufio.NewWriter(file)for i := 0; i < 10; i++ {writer.WriteString("hello"+strconv.Itoa(i)+"\n") //将数据先写入缓存}writer.Flush() //将缓存中的内容写入文件}
ioutil.WriteFile
创建文件,如果存在删除 重新写入
package mainimport ("fmt""io/ioutil")func main() {str := "hello word"err := ioutil.WriteFile("word.txt", []byte(str), 0644)if err != nil {fmt.Println("write file failed, err:", err)return}}
删除文件
Go语言里面删除文件和删除文件夹是同一个函数, 调用该函数就可以删除文件名为name的文件
func Remove(name string) Error
// Discard 是一个 io.Writer 接口,调用它的 Write 方法将不做任何事情// 并且始终成功返回。var Discard io.Writer = devNull(0)// ReadAll 读取 r 中的所有数据,返回读取的数据和遇到的错误。// 如果读取成功,则 err 返回 nil,而不是 EOF,因为 ReadAll 定义为读取// 所有数据,所以不会把 EOF 当做错误处理。func ReadAll(r io.Reader) ([]byte, error)// ReadFile 读取文件中的所有数据,返回读取的数据和遇到的错误。// 如果读取成功,则 err 返回 nil,而不是 EOFfunc ReadFile(filename string) ([]byte, error)// WriteFile 向文件中写入数据,写入前会清空文件。// 如果文件不存在,则会以指定的权限创建该文件。// 返回遇到的错误。func WriteFile(filename string, data []byte, perm os.FileMode) error// ReadDir 读取指定目录中的所有目录和文件(不包括子目录)。// 返回读取到的文件信息列表和遇到的错误,列表是经过排序的。func ReadDir(dirname string) ([]os.FileInfo, error)// NopCloser 将 r 包装为一个 ReadCloser 类型,但 Close 方法不做任何事情。func NopCloser(r io.Reader) io.ReadCloser// TempFile 在 dir 目录中创建一个以 prefix 为前缀的临时文件,并将其以读// 写模式打开。返回创建的文件对象和遇到的错误。// 如果 dir 为空,则在默认的临时目录中创建文件(参见 os.TempDir),多次// 调用会创建不同的临时文件,调用者可以通过 f.Name() 获取文件的完整路径。// 调用本函数所创建的临时文件,应该由调用者自己删除。func TempFile(dir, prefix string) (f *os.File, err error)// TempDir 功能同 TempFile,只不过创建的是目录,返回目录的完整路径。func TempDir(dir, prefix string) (name string, err error)
文件压缩
package mainimport ("archive/zip""fmt""io""log""os")type file struct {Name, Body string}func main() {// List of Files to Zipvar files = []file{{"readme.txt", "This archive contains some text files."},{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},{"todo.txt", "Get animal handling licence.\nWrite more examples."},}for _, file := range files {f, err := os.Create(file.Name)if err != nil {log.Fatal(err)}_, err = f.Write([]byte(file.Body))if err != nil {log.Fatal(err)}}output := "dome.zip"if err := ZipFiles(output, files); err != nil {panic(err)}fmt.Println("Zipped File:", output)}// ZipFiles compresses one or many files into a single zip archive file.// Param 1: filename is the output zip file's name.// Param 2: files is a list of files to add to the zip.func ZipFiles(filename string, files []file) error {newZipFile, err := os.Create(filename)if err != nil {return err}defer newZipFile.Close()zipWriter := zip.NewWriter(newZipFile)defer zipWriter.Close()// Add files to zipfor _, file := range files {if err = AddFileToZip(zipWriter, file.Name); err != nil {return err}}return nil}func AddFileToZip(zipWriter *zip.Writer, filename string) error {fileToZip, err := os.Open(filename)if err != nil {return err}defer fileToZip.Close()// Get the file informationinfo, err := fileToZip.Stat()if err != nil {return err}header, err := zip.FileInfoHeader(info)if err != nil {return err}// Using FileInfoHeader() above only uses the basename of the file. If we want// to preserve the folder structure we can overwrite this with the full path.header.Name = filename// Change to deflate to gain better compression// see http://golang.org/pkg/archive/zip/#pkg-constantsheader.Method = zip.Deflatewriter, err := zipWriter.CreateHeader(header)if err != nil {return err}_, err = io.Copy(writer, fileToZip)return err}
