Go语言之IO操作

幸运草 2020年4月13日18:55:18前端框架评论阅读模式
文件信息

1、FileInfo接口属性

1// A FileInfo describes a file and is returned by Stat and Lstat.
2type FileInfo interface {
3   Name() string       // base name of the file
4   Size() int64        // length in bytes for regular files; system-dependent for others
5   Mode() FileMode     // file mode bits
6   ModTime() time.Time // modification time
7   IsDir() bool        // abbreviation for Mode().IsDir()
8   Sys() interface{}   // underlying data source (can return nil)
9}

[备注]Mode,文件模式,一共10个字符。第一个字符表示类型,如果是-表示文件,如果是d表示目录。

文件的权限一共有9个字符表示,分成三组,分别表示文件所属用户owner的权限,文件所属用户组group的权限,其他人others的权限。

r表示读权限,w表示写权限,x表示执行权限。并且此文件所属用户拥有读、写、执行三项权限,其余的用户组,其它的用户不用有任何权限(全部是-)。

例如,-rwxrwxrwx,表示是个文件,用户权限、用户组权限、其他人权限都是可读、可写、可执行。

可以使用8进制表示法:

r  4

w  2

x  1

-  0

如-rwxrwxrwx 权限用8进制表示为 0777

参考网站:http://permissions-calculator.org/

2、fileStat结构体,实现了FileInfo接口

 1// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
 2type fileStat struct {
 3   name string
 4
 5   // from ByHandleFileInformation, Win32FileAttributeData and Win32finddata
 6   FileAttributes uint32
 7   CreationTime   syscall.Filetime
 8   LastAccessTime syscall.Filetime
 9   LastWriteTime  syscall.Filetime
10   FileSizeHigh   uint32
11   FileSizeLow    uint32
12
13   // from Win32finddata
14   Reserved0 uint32
15
16   // what syscall.GetFileType returns
17   filetype uint32
18
19   // used to implement SameFile
20   sync.Mutex
21   path             string
22   vol              uint32
23   idxhi            uint32
24   idxlo            uint32
25   appendNameToPath bool
26}

3、fileStat结构体的常用方法

 1func (fs *fileStat) Name() string {...}
 2func (fs *fileStat) IsDir() bool  {...}
 3func (fs *fileStat) Size() int64 {...}
 4
 5func (fs *fileStat) Mode() (m FileMode) {...}
 6
 7func (fs *fileStat) ModTime() time.Time {...}
 8
 9// Sys returns syscall.Win32FileAttributeData for file fs.
10func (fs *fileStat) Sys() interface{} {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "log"
 6   "os"
 7)
 8
 9func main() {
10
11   //获取FileInfo结构体
12   fileInfo, err := os.Stat("./ioFile/fileInfo.doc")
13
14   if err != nil {
15
16      log.Fatal(err.Error())
17
18   } else {
19
20      //打印fileInfo的类型
21      fmt.Printf("%T n", fileInfo) //*os.fileStat
22
23      //打印fileInfo的值
24      fmt.Printf("%v n", fileInfo) //&{fileInfo.doc 32 {111942775 30729325} {992823158 30729325} {993223181 30729325} 0 11469 0 0 {0 0} E:GoWorksrchelloioFilefileInfo.doc 0 0 0 false}
25
26      //文件名
27      fmt.Println(fileInfo.Name()) //fileInfo.doc
28
29      //文件大小
30      fmt.Println(fileInfo.Size()) //11469
31
32      //是否是目录
33      fmt.Println(fileInfo.IsDir()) //false
34
35      //文件模式
36      fmt.Println(fileInfo.Mode()) //-rw-rw-rw-
37
38      //文件最新修改时间
39      fmt.Println(fileInfo.ModTime()) //2019-03-27 15:18:09.6378381 +0800 CST
40
41      //底层数据源
42      fmt.Println(fileInfo.Sys()) //&{32 {111942775 30729325} {992823158 30729325} {993223181 30729325} 0 11469}
43   }
44}

文件的常规操作os包

1、创建目录,包含两种创建方式,一个是创建一层目录、另一个是创建多层目录,如果目录存在,则创建失败。

源码展示:使用一个明确的路径和文件模式来创建目录

 1// Mkdir creates a new directory with the specified name and FileMode 
 2
 3// A FileMode represents a file's mode and permission bits.
 4// The bits have the same definition on all systems, so that
 5// information about files can be moved from one system
 6// to another portably. Not all bits apply to all systems.
 7// The only required bit is ModeDir for directories.
 8
 9// If there is an error returned, it will be of type *PathError.
10//仅创建一层目录
11func Mkdir(name string, perm FileMode) error {...}
12
13
14// MkdirAll creates a directory named path,
15// along with any necessary parents, and returns nil,
16// or else returns an error.
17// The permission bits perm (before umask) are used for all
18// directories that MkdirAll creates.
19// If path is already a directory, MkdirAll does nothing
20// and returns nil.
21//创建多层目录
22func MkdirAll(path string, perm FileMode) error {...}

简单示例:

 1package main
 2
 3import "os"
 4
 5func main() {
 6
 7   //创建一层目录
 8   fileNameA := "./testA"
 9
10   os.Mkdir(fileNameA, os.ModePerm) //os.ModePerm 0777
11
12   //创建多层目录
13   fileNameB := "./test/testB"
14
15   os.MkdirAll(fileNameB, os.ModePerm)
16}

2、创建文件,如果文件存在,会覆盖。

源码展示:使用问一个文件名创建文件,本质上调用os.OpenFile()函数

1// Create creates the named file with mode 0666 (before umask), truncating
2// it if it already exists. If successful, methods on the returned
3// File can be used for I/O; the associated file descriptor has mode
4// O_RDWR.
5// If there is an error, it will be of type *PathError.
6func Create(name string) (*File, error) {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "log"
 6   "os"
 7)
 8
 9func main() {
10
11   //声明一个文件名称,创建文件
12   filePath := "./ioFile/studentInfo.txt"
13
14   //创建文件
15   file, err := os.Create(filePath)
16
17   if err != nil {
18
19      log.Fatal(err.Error())
20
21   } else {
22
23      fmt.Println(file.Name()) //./ioFile/studentInfo.txt
24   }
25}

3、打开文件,建立程序与指定文件之间的连接。

源码展示:打开指定文件

 1// Open opens the named file for reading. If successful, methods on
 2// the returned file can be used for reading; the associated file
 3// descriptor has mode O_RDONLY.
 4// If there is an error, it will be of type *PathError.
 5func Open(name string) (*File, error) {...}
 6
 7
 8// OpenFile is the generalized open call; most users will use Open
 9// or Create instead. It opens the named file with specified flag
10// (O_RDONLY etc.) and perm (before umask), if applicable. If successful,
11// methods on the returned File can be used for I/O.
12// If there is an error, it will be of type *PathError.
13//第一个参数是文件名称
14//第二个参数是文件的打开方式
15//第三个参数是文件的权限,文件不存在创建文件,需要指定权限
16func OpenFile(name string, flag int, perm FileMode) (*File, error){...}
17
18
19//注意openFile(...)函数中的flag参数如下选项
20//根据各flag的功能配置flag,实现文件的创写模式、覆写模式、追加模式
21// Flags to OpenFile wrapping those of the underlying system. Not all
22// flags may be implemented on a given system.
23const (
24   // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
25   O_RDONLY int = syscall.O_RDONLY // open the file read-only.
26   O_WRONLY int = syscall.O_WRONLY // open the file write-only.
27   O_RDWR   int = syscall.O_RDWR   // open the file read-write.
28   // The remaining values may be or'ed in to control behavior.
29   O_APPEND int = syscall.O_APPEND // append data to the file when writing.
30   O_CREATE int = syscall.O_CREAT  // create a new file if none exists.
31   O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.
32   O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.
33   O_TRUNC  int = syscall.O_TRUNC  // if possible, truncate file when opened.
34)

4、关闭文件,断开程序与文件之间的连接

源码展示:关闭相应文件

1// Close closes the File, rendering it unusable for I/O.
2// On files that support SetDeadline, any pending I/O operations will
3// be canceled and return immediately with an error.
4func (file *File) Close() error {...}

5、读取文件

源码展示:将指定文件中的内容读取到内存中

1// read reads up to len(b) bytes from the File.
2// It returns the number of bytes read and an error, if any.
3func (f *File) read(b []byte) (n int, err error) {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "io"
 6   "log"
 7   "os"
 8)
 9
10const CAPACITY = 1024 * 8 //声明切片容量
11
12func main() {
13
14   //声明文件路径
15   filePath := "./ioFile/studentInfo.txt"
16
17   //打开文件
18   file, err := os.Open(filePath)
19
20   //延迟关闭文件
21   defer file.Close()
22
23   if err != nil {
24
25      log.Fatal(err.Error())
26
27   } else {
28
29      //读取文件信息
30      bytes := make([]byte, CAPACITY, CAPACITY)
31
32      var err error
33
34      n := -1
35
36      for {
37
38         n, err = file.Read(bytes) //At end of file, Read returns 0, io.EOF.
39
40         if n == 0 || err == io.EOF { //文件读取结束
41
42            break
43         }
44
45         fmt.Println(string(bytes[:n])) //Welcome to GopherZone
46      }
47   }
48}

6、写入文件

源码展示:将内存中的数据写入到指定文件中

1// write writes len(b) bytes to the File.
2// It returns the number of bytes written and an error, if any.
3func (f *File) write(b []byte) (n int, err error) {...}

简单示例:

 1package main
 2
 3import (
 4   "io"
 5   "os"
 6)
 7
 8const CAPACITY = 1024 * 8 //声明切片容量
 9
10func main() {
11
12   //声明源文件路径
13   filePathSrc := "./ioFile/studentInfo.txt"
14
15   //声明目标文件路径
16   filePathDest := "./ioFile/studentInfoCopy.txt"
17
18   //打开源文件
19   fileSrc, errSrc := os.Open(filePathSrc)
20
21   //打开目标文件
22   fileDest, errDest := os.OpenFile(filePathDest, os.O_RDWR|os.O_CREATE, os.ModePerm)
23
24   //延迟关闭文件,在以后的异常处理的学习中,详细学习defer关键字
25   defer func() {
26
27      fileSrc.Close()
28      fileDest.Close()
29
30   }()
31
32   if errSrc != nil || errDest != nil {
33
34      return
35
36   } else {
37
38      //存储读取的文件信息
39      bytes := make([]byte, CAPACITY, CAPACITY)
40
41      //声明一个错误变量
42      var err error
43
44      //声明一个读取的初始字节数
45      n := -1
46
47      for {
48
49         //从原文件中读取数据
50         n, err = fileSrc.Read(bytes) //At end of file, Read returns 0, io.EOF.
51
52         if n == 0 || err == io.EOF { //文件读取结束
53
54            break
55         }
56
57         if err != nil {
58
59            return
60
61         } else {
62
63            //向目标文件中写数据
64            fileDest.Write(bytes[:n])
65         }
66      }
67   }
68}

7、删除文件

源码展示:删除指定文件

1// Remove removes the named file or directory.
2// If there is an error, it will be of type *PathError.
3func Remove(name string) error {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "log"
 6   "os"
 7)
 8
 9func main() {
10
11   //声明文件路径
12   filePath := "./ioFile/studentInfoCopy.txt"
13
14   //删除文件和目录第一种方式
15   err := os.Remove(filePath)
16
17   if err != nil {
18
19      log.Fatal(err.Error())
20
21   } else {
22
23      fmt.Println("删除成功")
24   }
25
26   //删除文件和目录第二种方式
27   err = os.RemoveAll(filePath)
28
29   if err != nil {
30
31      log.Fatal(err.Error())
32
33   } else {
34
35      fmt.Println("删除成功")
36   }
37}

ioutil包

主要学习ioutil包下的的几个核心函数。

1、ReadFile(),读取文件中的所有数据,返回读取的字节数组。

源码展示:

1// ReadFile reads the file named by filename and returns the contents.
2// A successful call returns err == nil, not err == EOF. Because ReadFile
3// reads the whole file, it does not treat an EOF from Read as an error
4// to be reported.
5func ReadFile(filename string) ([]byte, error) {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "io/ioutil"
 6   "log"
 7)
 8
 9func main() {
10
11   //声明文件路径
12   filePath := "./ioFile/studentInfo.txt"
13
14   //读取文件
15   bytes, err := ioutil.ReadFile(filePath)
16
17   if err != nil {
18
19      log.Fatal(err.Error())
20      return
21   }
22
23   fmt.Println(string(bytes)) //Welcome to GopherZone
24}

2、WriteFile(),向指定文件写入数据,如果文件不存在,则创建文件,写入数据之前清空文件。

源码展示:

1// WriteFile writes data to a file named by filename.
2// If the file does not exist, WriteFile creates it with permissions perm;
3// otherwise WriteFile truncates it before writing.
4func WriteFile(filename string, data []byte, perm os.FileMode) error {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "io/ioutil"
 6   "log"
 7)
 8
 9func main() {
10
11   //声明文件路径,注意该文件路径必须存在,否则抛异常
12   filePath := "D:/ioFile"
13
14   //创建临时文件
15   file, errA := ioutil.TempFile(filePath, "temp")
16
17   //延迟关闭文件
18   defer file.Close()
19
20   if errA != nil {
21
22      log.Fatal(errA.Error())
23      return
24   }
25
26   //向文件中写数据,注意该写入方法是清空文件内容,再写入新内容
27   data := "Welcome to GopherZone"
28   errB := ioutil.WriteFile(file.Name(), []byte(data), 0777)
29
30   if errB != nil {
31
32      log.Fatal(errB.Error())
33      return
34   }
35
36   //从文件中读取数据
37   bytes, errC := ioutil.ReadFile(file.Name())
38
39   if errC != nil {
40
41      log.Fatal(errC.Error())
42      return
43   }
44
45   //打印数据
46   fmt.Println(string(bytes)) //Welcome to GopherZone
47}

3、ReadDir,读取一个目录下的字内容,子文件和子目录,可以包含多层级。

源码展示:

1// ReadDir reads the directory named by dirname and returns
2// a list of directory entries sorted by filename.
3func ReadDir(dirname string) ([]os.FileInfo, error) {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "io/ioutil"
 6   "log"
 7)
 8
 9func main() {
10
11   //声明文件路径
12   filePath := "./ioFile/studentInfo.txt"
13
14   //读取文件
15   infos, err := ioutil.ReadDir(filePath)
16
17   if err != nil {
18
19      log.Fatal(err.Error())
20      return
21   }
22
23   for _, fileInfo := range infos {
24
25      fmt.Println("文件名称", fileInfo.Name())
26      fmt.Println("文件大小", fileInfo.Size())
27      fmt.Println("文件权限", fileInfo.Mode())
28      fmt.Println("修改时间", fileInfo.ModTime())
29      fmt.Println("是否是目录", fileInfo.IsDir())
30      fmt.Println("源数据", fileInfo.Sys())
31   }
32}

4、TempDir(),在当前目录下,创建一个以指定字符串为前缀的临时文件夹,并返回文件夹路径。

源码展示:

1// TempDir creates a new temporary directory in the directory dir
2// with a name beginning with prefix and returns the path of the
3// new directory. If dir is the empty string, TempDir uses the
4// default directory for temporary files (see os.TempDir).
5// Multiple programs calling TempDir simultaneously
6// will not choose the same directory. It is the caller's responsibility
7// to remove the directory when no longer needed.
8func TempDir(dir, prefix string) (name string, err error) {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "io/ioutil"
 6   "log"
 7)
 8
 9func main() {
10
11   //声明文件路径,注意该文件路径必须存在,否则抛异常
12   filePath := "D:/ioFile"
13
14   //创建目录
15   dir, err := ioutil.TempDir(filePath, "temp")
16
17   if err != nil {
18
19      log.Fatal(err.Error())
20      return
21   }
22
23   //打印目录信息
24   fmt.Println(dir) //D:ioFiletemp940075267
25}

5、TempFile(),在当前目录下,创建一个以指定字符串为前缀的文件,并以读写模式打开文件,并返回os.File只针对象

源码展示:

 1// TempFile creates a new temporary file in the directory dir,
 2// opens the file for reading and writing, and returns the resulting *os.File.
 3// The filename is generated by taking pattern and adding a random
 4// string to the end. If pattern includes a "*", the random string
 5// replaces the last "*".
 6// If dir is the empty string, TempFile uses the default directory
 7// for temporary files (see os.TempDir).
 8// Multiple programs calling TempFile simultaneously
 9// will not choose the same file. The caller can use f.Name()
10// to find the pathname of the file. It is the caller's responsibility
11// to remove the file when no longer needed.
12func TempFile(dir, pattern string) (f *os.File, err error) {...}

简单示例:

 1package main
 2
 3import (
 4   "fmt"
 5   "io/ioutil"
 6   "log"
 7)
 8
 9func main() {
10
11   //声明文件路径,注意该文件路径必须存在,否则抛异常
12   filePath := "D:/ioFile"
13
14   //创建临时文件
15   file, err := ioutil.TempFile(filePath, "temp")
16
17   //延迟关闭文件
18   defer file.Close()
19
20   if err != nil {
21
22      log.Fatal(err.Error())
23      return
24   }
25
26   //向文件中写数据
27   file.WriteString("Welcome to GopherZone")
28
29   //从文件中读取数据
30   bytes, err := ioutil.ReadFile(file.Name())
31
32   if err != nil {
33
34      log.Fatal(err.Error())
35      return
36   }
37
38   //打印数据
39   fmt.Println(string(bytes)) //Welcome to GopherZone
40}

bufio包

bufio和io包中很多操作都是相似的,唯一不同的地方是bufio提供了一些缓冲的操作,如果对文件I/O操作比较频繁的,使用bufio还是能增加一些性能的。

1、bufio、strings、bytes包下的NewReader()

源码展示:

1// NewReader returns a new Reader whose buffer has the default size.
2func NewReader(rd io.Reader) *Reader {...}
1// NewReader returns a new Reader reading from s.
2// It is similar to bytes.NewBufferString but more efficient and read-only.
3func NewReader(s string) *Reader { return &Reader{s, 0, -1} }
1// NewReader returns a new Reader reading from b.
2func NewReader(b []byte) *Reader { return &Reader{b, 0, -1} }

简单示例:

 1package main
 2
 3import (
 4   "bufio"
 5   "fmt"
 6   "io"
 7   "log"
 8   "os"
 9)
10
11func main() {
12
13   //声明文件路径,注意该文件路径必须存在,否则抛异常
14   filePath := "./ioFile/studentInfo.txt"
15
16   //创建临时文件
17   file, errA := os.Open(filePath)
18
19   //延迟关闭文件
20   defer file.Close()
21
22   if errA != nil {
23
24      log.Fatal(errA.Error())
25      return
26   }
27
28   //存储数据的切片
29   dataSlice := make([]string, 0)
30
31   //向文件中写数据
32   reader := bufio.NewReader(file)
33
34   byteSlice := make([]byte, 1024*1) //1024的倍数
35
36   var errB error
37
38   n := -1
39
40   for {
41
42      n, errB = reader.Read(byteSlice)
43
44      if n == 0 || errB == io.EOF {
45
46         break
47      }
48
49      dataSlice = append(dataSlice, string(byteSlice[:n]))
50   }
51
52   //打印切片
53   for _, value := range dataSlice {
54
55      fmt.Println(value)
56   }
57}

2、bufio.NewWriter()

源码展示:

1// NewWriter returns a new Writer whose buffer has the default size.
2func NewWriter(w io.Writer) *Writer {...}

简单示例:

 1package main
 2
 3import (
 4   "bufio"
 5   "log"
 6   "os"
 7)
 8
 9func main() {
10
11   //初始化数据
12   data := "Welcome to GopherZone"
13
14   //声明文件路径,注意该文件路径必须存在,否则抛异常
15   filePath := "./ioFile/studentInfoCopy.txt"
16
17   //打开文件os.O_APPEND,往文件后追加内容
18   file, errA := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
19
20   //延迟关闭文件
21   defer file.Close()
22
23   if errA != nil {
24
25      log.Fatal(errA.Error())
26      return
27   }
28
29   //bufio中的WriteString方法向文件中写数据
30   writer := bufio.NewWriter(file)
31
32   if _, errB := writer.WriteString(data); errB == nil {
33
34      writer.Flush() //bufio中的写操作需要使用Flush方法将缓冲区的数据刷到磁盘
35   }
36}

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

  • 赞助本站
  • 微信扫一扫
  • weinxin
  • 加入Q群
  • QQ扫一扫
  • weinxin
幸运草
Go语言接口规则 前端框架

Go语言接口规则

Go语言接口规则 接口是一个或多个方法签名的集合。任何类型的方法集中只要拥有该接口对应的全部方法签名。就表示它 "实现" 了该接口,无须在该类型上显式声明实现了哪个接口。对应方法,是指有相同名称、参数...
Go语言中处理 HTTP 服务器 前端框架

Go语言中处理 HTTP 服务器

1 概述 包 net/http 提供了HTTP服务器端和客户端的实现。本文说明关于服务器端的部分。 快速开始: package main import (   "log"   "net/http" )...

发表评论