Golang的文本文件处理-文件操作常见的API
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.打开文件相关操作
1>.如果文件不存在就创建文件,如果文件存在就清空文件内容并打开(Create方法)
package main import ( "errors" "fmt" "os" ) func main() { /** 创建文件的API函数签名如下所示: func Create(name string) (*File, error) 下面是对API的参数解释说明: name: 指的是文件名称,可以是相对路径,也可以是绝对路径。 *File: 指的是文件指针,我们使用完文件后要记得释放该文件指针资源 error: 指的是创建文件的报错信息,比如指定的文件父目录不存在就会报错"The system cannot find the path specified." 温馨提示: 根据提供的文件名创建新的文件,返回一个文件对象,返回的文件对象是可读写的。 创建文件时,如果存在重名的文件就会覆盖掉原来的文件。换句话说,如果文件存在就清空文件内容并打开新文件,如果文件不存在则创建新文件并打开。 */ f, err := os.Create("E:\yinzhengjie\input\kafka.txt") /** 一旦文件报错就执行return语句,下面的defer语句就不会被执行到哟~ 温馨提示: 我们不要将下面的defer语句和判断错误的语句互换位置,因为判断错误的语句是来确保文件是否创建成功; 如果有错误意味着文件没有被成功创建,换句话说,如果文件创建失败,那么文件指针为空,此时如果执行关闭文件会报错哟; 如果没有错误就意味着文件创建成功,即在执行关闭文件的操作是确保不会报错 */ if err != nil { fmt.Println(errors.New("报错提示:" + err.Error())) return } else { fmt.Println("文件创建成功....") } /** 文件成功创建之后,一直处于打开状态,因此我们使用完之后一定要关闭文件,当然关闭文件之前一定要确保为文件已经创建成功。 */ defer f.Close() }
2>.以只读方式打开文件(Open方法)
package main import ( "errors" "fmt" "os" ) func main() { /** 打开文件的API函数实现如下所示,很明显它是基于OpenFile实现的 func Open(name string) (*File, error) { return OpenFile(name, O_RDONLY, 0) } 下面是对API的参数解释说明: name: 指的是文件名称,可以是相对路径,也可以是绝对路径。 *File: 指的是文件指针,我们使用完文件后要记得释放该文件指针资源 error: 指的是创建文件的报错信息,比如指定的文件不存在就会报错"The system cannot find the file specified." 温馨提示: Open()是以只读权限打开文件名为name的文件,得到的文件指针file,只能用来对文件进行"读"操作。 如果我们有"写"文件的需求,就需要借助"Openfile"函数来打开了。 */ f, err := os.Open("E:\yinzhengjie\input\kafka.txt") /** 一旦文件报错就执行return语句,下面的defer语句就不会被执行到哟~ 温馨提示: 我们不要将下面的defer语句和判断错误的语句互换位置,因为判断错误的语句是来确保文件是否创建成功; 如果有错误意味着文件没有被成功创建,换句话说,如果文件创建失败,那么文件指针为空,此时如果执行关闭文件会报错哟; 如果没有错误就意味着文件创建成功,即在执行关闭文件的操作是确保不会报错 */ if err != nil { fmt.Println(errors.New("报错提示:" + err.Error())) return } else { fmt.Println("文件打开成功....") } /** 文件成功创建之后,一直处于打开状态,因此我们使用完之后一定要关闭文件,当然关闭文件之前一定要确保为文件已经创建成功。 */ defer f.Close() }
3>.自定义文件的打开方式(OpenFile方法)
package main import ( "errors" "fmt" "os" ) func main() { /** 创建文件的API函数签名如下所示: func OpenFile(name string, flag int, perm FileMode) (*File, error) 下面是对API的参数解释说明: name: 指的是文件名称,可以是相对路径,也可以是绝对路径。 flag: 表示读写模式,常见的模式有:O_RDONLY(只读模式), O_WRONLY(只写模式), O_RDWR(可读可写模式)。 perm: 表示打开权限。来源于Linux系统调用中的open函数,参2为:O_CREATE时,可创建新文件。 权限取值范围是八进制,即"0-7".表示如下: 0:没有任何权限 1:执行权限(如果是可执行文件,是可以运行的) 2:写权限 3: 写权限与执行权限 4:读权限 5: 读权限与执行权限 6: 读权限与写权限 7: 读权限,写权限,执行权限 *File: 指的是文件指针,我们使用完文件后要记得释放该文件指针资源 error: 指的是创建文件的报错信息,比如指定的文件父目录不存在就会报错"The system cannot find the path specified." 温馨提示: 使用OpenFile打开的文件,默认写的时候是聪文件开头开始写入数据,这样会将原来的数据覆盖掉; 如果不想覆盖的方式写入,使用追加的方式写入,具体代码如下所示(当然你也可以使用Seek函数实现哟~)。 */ f, err := os.OpenFile("E:\yinzhengjie\input\kafka.txt", os.O_RDWR|os.O_APPEND, 0666) /** 一旦文件报错就执行return语句,下面的defer语句就不会被执行到哟~ 温馨提示: 我们不要将下面的defer语句和判断错误的语句互换位置,因为判断错误的语句是来确保文件是否创建成功; 如果有错误意味着文件没有被成功创建,换句话说,如果文件创建失败,那么文件指针为空,此时如果执行关闭文件会报错哟; 如果没有错误就意味着文件创建成功,即在执行关闭文件的操作是确保不会报错 */ if err != nil { fmt.Println(errors.New("报错提示:" + err.Error())) return } else { fmt.Println("文件创建成功....") } /** 文件成功创建之后,一直处于打开状态,因此我们使用完之后一定要关闭文件,当然关闭文件之前一定要确保为文件已经创建成功。 */ defer f.Close() }
二.写文件相关操作
1>.Write方法
package main import ( "errors" "fmt" "os" ) func main() { f, err := os.Create("E:\yinzhengjie\input\kafka.txt") if err != nil { fmt.Println(errors.New("报错提示:" + err.Error())) return } else { fmt.Println("文件创建成功....") } /** 文件成功创建之后,一直处于打开状态,因此我们使用完之后一定要关闭文件,当然关闭文件之前一定要确保为文件已经创建成功。 */ defer f.Close() /** 写入字节切片到文件中,Write的函数签名如下所示: func (f *File) Write(b []byte) (n int, err error) 如上所示,我们只需要传入需要写入的字节切片即可将内容写到操作系统中对应的文件。 */ f.Write([]byte("Kafka是一个吞吐量高的消息队列 ")) }
2>.WriteString方法
package main import ( "errors" "fmt" "os" ) func main() { f, err := os.Create("E:\yinzhengjie\input\kafka.txt") if err != nil { fmt.Println(errors.New("报错提示:" + err.Error())) return } else { fmt.Println("文件创建成功....") } /** 文件成功创建之后,一直处于打开状态,因此我们使用完之后一定要关闭文件,当然关闭文件之前一定要确保为文件已经创建成功。 */ defer f.Close() /** 写入字符串到文件,其函数实现如下,很明显,WriteString底层调用的依旧是Write方法。 func (f *File) WriteString(s string) (n int, err error) { return f.Write([]byte(s)) } 如上所示,我们只需要传入需要写入的字符串即可将内容写到操作系统中对应的文件。 */ f.WriteString("Kafka是一个消息队列") }
3>.WriteAt方法
package main import ( "errors" "fmt" "os" ) func main() { f, err := os.Create("E:\yinzhengjie\input\kafka.txt") if err != nil { fmt.Println(errors.New("报错提示:" + err.Error())) return } else { fmt.Println("文件创建成功....") } /** 文件成功创建之后,一直处于打开状态,因此我们使用完之后一定要关闭文件,当然关闭文件之前一定要确保为文件已经创建成功。 */ defer f.Close() /** WriteAt是带偏移量的写入数据,偏移量是从文件起始位置开始,WriteAt的函数签名如下所示: func (f *File) WriteAt(b []byte, off int64) (n int, err error) 以下是对函数签名相关参数说明: b: 待写入的数据内容 off: 偏移量(通常是Seek函数返回值) */ f.WriteAt([]byte("Kafka"), 10) }
4>.Seek方法
package main import ( "fmt" "os" "syscall" ) const ( // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. O_RDONLY int = syscall.O_RDONLY // open the file read-only. O_WRONLY int = syscall.O_WRONLY // open the file write-only. O_RDWR int = syscall.O_RDWR // open the file read-write. // The remaining values may be or'ed in to control behavior. O_APPEND int = syscall.O_APPEND // append data to the file when writing. O_CREATE int = syscall.O_CREAT // create a new file if none exists. O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist. O_SYNC int = syscall.O_SYNC // open for synchronous I/O. O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened. ) func main() { f, err := os.OpenFile("E:\yinzhengjie\input\flume.txt", O_RDWR|O_CREATE|O_TRUNC, 0666) if err != nil { fmt.Println("err = ", err) return } defer f.Close() f.Write([]byte("Flume 是一个文本日志收集工具。 ")) f.WriteString("Flume是一种分布式,可靠且可用的服务,用于有效地收集,聚合和移动大量日志数据。") f.WriteAt([]byte("Flume具有基于流数据流的简单灵活的体系结构。"), 60) //可以指定偏移量写入 /** Seek的函数签名如下所示: func (f *File) Seek(offset int64, whence int) (ret int64, err error) 以下是对函数签名相关参数说明: offset: 指定偏移量,如果是正数,则表示向文件尾偏;如果是负数,则表示向文件头偏. whence: 指定偏移量的起始位置. io.SeekStart: 文件起始位置,对应常量整型0. io.SeekCurrent: 文件当前位置,对应常量整型1. io.SeekEnd: 文件结尾位置,对应常量整型2. 返回值: 表示从文件起始位置,到当前文件读写指针位置的偏移量。 */ f.Seek(10, 2) f.WriteString("Flume具有可调整的可靠性机制以及许多故障转移和恢复机制,具有强大的功能和容错能力。") }
三.读文件相关操作
Flume是一种分布式,可靠且可用的服务,用于有效地收集,聚合和移动大量日志数据。
它具有基于流数据流的简单灵活的体系结构。
它具有可调整的可靠性机制以及许多故障转移和恢复机制,具有强大的功能和容错能力。
它使用一个简单的可扩展数据模型,允许在线分析应用程序。
1>.Read方法
package main import ( "fmt" "os" ) func main() { f, err := os.OpenFile("E:\yinzhengjie\input\flume.txt", os.O_RDWR|os.O_APPEND, 0666) if err != nil { fmt.Println("文件打开失败: ", err) return } defer f.Close() /** 切片在使用前要申请内存空间,如果不知道文件的大小,尽量多给点空间最好是4K的倍数 如果在读取大文件的情况下,我们应该循环读取,当然,我的笔记里有读取大文件的实战案例。 */ temp := make([]byte, 1024*4) f.Read(temp) fmt.Println(string(temp)) }
2>.ReadAt方法
package main import ( "fmt" "os" ) func main() { f, err := os.OpenFile("E:\yinzhengjie\input\flume.txt", os.O_RDWR|os.O_APPEND, 0666) if err != nil { fmt.Println("文件打开失败: ", err) return } defer f.Close() temp := make([]byte, 1024*4) f.ReadAt(temp, 5) //带偏移量的获取数据,是从文件头开始的,当然我们使用Seek函数也能实现该功能 fmt.Println(string(temp)) }
3>.按行读取案例
package main import ( "bufio" "bytes" "fmt" "os" ) func main() { f, err := os.OpenFile("E:\yinzhengjie\input\flume.txt", os.O_RDWR|os.O_APPEND, 0666) if err != nil { fmt.Println("文件打开失败: ", err) return } defer f.Close() buf := make([]byte, 1024*4) f.Read(buf) //一定要将数据读到切片中,否则执行下面的操作会读取不到数据哟~ reader := bufio.NewReader(bytes.NewReader(buf)) //初始化一个阅读器 line, _ := reader.ReadString(' ') //为阅读器指定分隔符为换行符(" "),即每次只读取一行. fmt.Println(line) }
四.删除文件
package main import ( "os" ) func main() { os.Remove("E:\yinzhengjie\input\kafka.txt") //删除文件 }
五.大文件拷贝案例
package main import ( "fmt" "io" "os" ) func main() { args := os.Args //获取命令行参数, 并判断输入是否合法 if args == nil || len(args) != 3 { fmt.Println("useage : xxx srcFile dstFile") return } srcPath := args[1] //获取源文件路径 dstPath := args[2] //获取目标文件路径 fmt.Printf("srcPath = %s, dstPath = %s ", srcPath, dstPath) if srcPath == dstPath { fmt.Println("error:源文件名与目的文件名相同") return } srcFile, err1 := os.Open(srcPath) // 打开源文件 if err1 != nil { fmt.Println(err1) return } dstFile, err2 := os.Create(dstPath) //创建目标文件 if err2 != nil { fmt.Println(err2) return } buf := make([]byte, 1024) //切片缓冲区 for { //从源文件读取内容,n为读取文件内容的长度 n, err := srcFile.Read(buf) if err != nil && err != io.EOF { fmt.Println(err) break } if n == 0 { fmt.Println("文件处理完毕") break } //切片截取 tmp := buf[:n] //把读取的内容写入到目的文件 dstFile.Write(tmp) } //关闭文件 srcFile.Close() dstFile.Close() }