path
在path包中封装了一些路径相关的操作,在开始接触文件操作之前,我们先看看路径的相关函数。在Linux中,路径的格式为/user/bin路径中分隔符是/;Windows中的路径格式为c:\Windows路径中的分隔符是\。而在go中只认/。所以在windows中,需要把path中的\替换为/。
func Base
func Base(path string) string Base函数返回路径的最后一个元素。在提取元素前会求掉末尾的斜杠。 如果路径是"",会返回"."; 如果路径是只有一个斜杆构成,会返回"/"
func Clean
func Clean(path string) string Clean函数通过单纯的词法操作返回和path代表同一地址的最短路径。
它会不断的依次应用如下的规则,直到不能再进行任何处理:
将连续的多个斜杠替换为单个斜杠 剔除每一个.路径名元素(代表当前目录) 剔除每一个路径内的..路径名元素(代表父目录)和它前面的非..路径名元素 剔除开始一个根路径的..路径名元素,即将路径开始处的"/.."替换为"/" 只有路径代表根地址"/"时才会以斜杠结尾。如果处理的结果是空字符串,Clean会返回"."。
func Dir
func Dir(path string) stringDir 返回路径除去最后一个路径元素的部分,即该路径最后一个元素所在的目录。在使用Split去掉最后一个元素后,会简化路径并去掉末尾的斜杠。如果路径是空字符串,会返回".";如果路径由1到多个斜杠后跟0到多个非斜杠字符组成,会返回"/";其他任何情况下都不会返回以斜杠结尾的路径。
func Ext
func Ext(path string) string Ext函数返回path文件扩展名。返回值是路径最后一个斜杠分隔出的路径元素的最后一个'.'起始的后缀(包括'.')。如果该元素没有'.'会返回空字符串。
func IsAbs
func IsAbs(path string) bool IsAbs返回路径是否是一个绝对路径。
func Split
func Split(path string) (dir, file string) Split函数将路径从最后一个斜杠后面位置分隔为两个部分(dir和file)并返回。如果路径中没有斜杠,函数返回值dir会设为空字符串,file会设为path。两个返回值满足path == dir+file。
func Join
func Join(elem ...string) string Join函数可以将任意数量的路径元素放入一个单一路径里,会根据需要添加斜杠。结果是经过简化的,所有的空字符串元素会被忽略。
示例
package main
import ( "path" "fmt" )
func main(){ fmt.Println("path.Base: ",path.Base("C:/Users/zzc/go/src/channelDemo")) fmt.Println("path.Clean: ",path.Clean("C:/Users/zzc/./go///src/../../channelDemo/")) fmt.Println("path.Ext: ",path.Ext("C:/Users/zzc/go/src/channelDemo/main.go")) fmt.Println("path.Dir: ",path.Dir("C:/Users/zzc/go/src/channelDemo/main.go")) fmt.Println("path.IsAbs: ",path.IsAbs("C:/Users/zzc/go/src/channelDemo/main.go")) dir, file := path.Split("C:/Users/zzc/go/src/channelDemo/main.go") fmt.Println("path.Split: ",dir, file) fmt.Println("path.Join: ",path.Join("c:/Users", "zzc", "go", "src")) } 运行结果 文件读写
在os包中提供了一下文件操作的函数。
创建文件
Create func Create(name string) (file File, err error) Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。如果出错,错误底层类型是PathError。 例如:
file, err := os.Create("d:/my.txt") 打开文件
open
func Open(name string) (file File, err error) Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是PathError。
OpenFile
func OpenFile(name string, flag int, perm FileMode) (file File, err error) OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是PathError。 name : 要打开或要创建的文件名 flag : 是打开文件的方式,可以取以下值:
O_RDONLY:以只读的方式打开 O_WRONLY:以只写的方式打开 O_RDWR:以读写的方式打开 O_APPEND:以追加方式打开文件,写入的数据将追加到文件尾 O_CREATE:当文件不存在时创建文件 O_EXCL:与O_CREATE一起使用,当文件存在时Open失败 O_SYNC:以同步方式打开文件。每次write系统调用后等等待实际的物理I/O完成后才返回,默认(不使用该标记)是使用缓冲的,也就是说每次的写操作是写到系统内核缓冲区中,等系统缓冲区满后才写到实际存储设备中。 O_TRUNC:如果文件已存在,打开是会清空文件内容。必须于O_WRONLY或O_RDWR配合使用。截断文件,需要有写的权限。 FileMode: 是文件的权限,只有在文件不存在,新建文件时该参数才有效。用来指定新建的文件的权限。必须跟O_CREATE配合使用。
写文件
Write
func (f *File) Write(b []byte) (n int, err error) Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
WriteString
func (f *File) WriteString(s string) (ret int, err error) WriteString类似Write,但接受一个字符串参数。
WriteAt
func (f *File) WriteAt(b []byte, off int64) (n int, err error) WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
读文件
Read
func (f *File) Read(b []byte) (n int, err error) Read方法从f中读取最多len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。文件终止标志是读取0个字节且返回值err为io.EOF。
ReadAt
func (f *File) ReadAt(b []byte, off int64) (n int, err error) ReadAt从指定的位置(相对于文件开始位置)读取len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。当n<len(b)时,本方法总是会返回错误;如果是因为到达文件结尾,返回值err会是io.EOF。
其他
Close
func (f *File) Close() error Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。
Seek
func (f *File) Seek(offset int64, whence int) (ret int64, err error) Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。 whence在系统中定义的有常量: SEEK_SET:0 SEEK_CUR:1 SEEK_END:2
例子
package main
import ( "io" "fmt" "os" )
func main(){ testio() }
func testio(){ //若文件不存在则创建文件,以append方式打开 file, err := os.OpenFile("d:/test.txt", os.O_CREATE|os.O_APPEND, 0666) if err != nil{ fmt.Println(err) return } defer file.Close() //关闭文件 file.WriteString("i am chain ") //写入文件 buf := make([]byte, 1024) var str string file.Seek(0, os.SEEK_SET) //重置文件指针 //读取文件 for { n, ferr := file.Read(buf) if ferr != nil && ferr != io.EOF{ fmt.Println(ferr.Error()) break } if n == 0{ break } str += string(buf[0:n]) } fmt.Println("file content: ", str) } 执行两次之后的结果如下图
运行结果 ioutil
在ioutil中封装了一些函数,让IO操作更简单方便
ReadAll
func ReadAll(r io.Reader) ([]byte, error) ReadAll从r读取数据直到EOF或遇到error,返回读取的数据和遇到的错误。成功的调用返回的err为nil而非EOF。因为本函数定义为读取r直到EOF,它不会将读取返回的EOF视为应报告的错误。
ReadFile
func ReadFile(filename string) ([]byte, error) ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件,它不会将读取返回的EOF视为应报告的错误。
WriteFile
func WriteFile(filename string, data []byte, perm os.FileMode) error函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。
例子
package main
import ( "io" "io/ioutil" "fmt" "os" )
func main(){ testioutil() }
func testioutil(){ str := "i am chain, i am a good boy. " //写入数据 err := ioutil.WriteFile("d:/a.txt",[]byte(str), 0666) if err != nil{ fmt.Println(err.Error()) }else{ fmt.Println("write success!") } //通过readfile函数读取数据 buf1, err1 := ioutil.ReadFile("d:/a.txt") if err1 != nil{ fmt.Println(err1.Error()) }else{ fmt.Println("Read File: ", string(buf1)) } //通过readall读取数据 f, err2 := os.OpenFile("d:/a.txt", os.O_RDONLY, 0666) if err2 != nil{ fmt.Println(err2.Error()) return } defer f.Close() buf2, err3 := ioutil.ReadAll(f) if err3 != nil{ fmt.Println(err3.Error()) }else{ fmt.Println("read all: ", string(buf2)) } } 运行结果 目录操作
os/Readdir
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构成的切片和该错误。
package main
import ( "fmt" "os" )
func main(){ f, err := os.OpenFile("D:/code/", os.O_RDONLY, 0666) if err != nil{ fmt.Println(err.Error()) return } arrFiles, err1:=f.Readdir(0) if err1 != nil{ fmt.Println(err1.Error()) return } for k, v := range arrFiles{ fmt.Println(k, "\t", v, "\t", v.IsDir()) } } 运行结果 ioutil/ReadDir
func ReadDir(dirname string) ([]os.FileInfo, error) 返回dirname指定的目录的目录信息的有序列表。
package main
import ( "io" "io/ioutil" "fmt" )
func main(){ arrFiles, err1 := ioutil.ReadDir("D:/code/") if err1 != nil{ fmt.Println(err1.Error()) return } for k, v := range arrFiles{ fmt.Println(k, "\t", v, "\t", v.IsDir()) } } 运行结果 gob序列化
序列化就是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。之后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
gob是go中特有的序列化技术,它支持除interface,function,channel外的所有go数据类型。序列化用Encoder,反序列化用Decoder。
package main
import ( "encoding/gob" "os" "fmt" )
type Student struct{ Name string Age int }
func main(){ stu := &Student{"chain", 23} f, err := os.Create("d:/stu.txt") if err != nil{ fmt.Println(err.Error()) return } defer f.Close() //创建Encoder对象 encode := gob.NewEncoder(f) //将stu序列化到f中 encode.Encode(stu) //重置文件指针 f.Seek(0, os.SEEK_SET) //创建decoder对象 decoder := gob.NewDecoder(f) var s1 Student //反序列化对象 decoder.Decode(&s1) fmt.Println(s1) } gob序列化示例 完
作者:ChainZhang 链接:https://www.jianshu.com/p/8d3c73c66564 來源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。