Go语言学习之路第9天(文件操作)
2020-12-13 05:38
标签:lock ali 核心 矢量 indent 查看 特性 用户 函数 新建文件可以通过如下方法,Create()方法: Create采用模式0666(任何人都可读写,不可执行,但实际文件权限是由你linux服务器上的umask值决定的)创建一个名为name的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具O_RDWR模式。如果出错,错误底层类型是*PathError。 参数:新创建的文件名;可以绝对路径;也可以相对路径( 相对.go 或 .exe文件。) 返回值: file:文件指针。本质:file对象(结构体) err:错误返回 特性: 文件不存在:创建新文件。 文件存在:覆盖源文件。(截断为0) 具体实例如下: 打开文件有两种方式: (1)以只读的方式打开文件,Open()方法 Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。 参数:打开的文件名:可以绝对路径;也可以相对路径(相对.go 或 .exe文件。) 返回值: file:文件指针。本质:file对象(结构体) err:错误返回 特性: 文件存在:只读打开 文件不存在:报错返回。 具体实例如下: 注意:用Open打开的文件只能用于读取,不能用于写入。 (2)以读写的方式打开文件,OpenFile()方法 OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。 参数一:打开的文件名:可以绝对路径;也可以相对路径(相对.go 或 .exe文件。) 参数二:打开文件的操作权限: os.O_RDONLY : 只读打开 os.O_WRONLY : 只写打开 os.O_RDWR : 读写打开 。 常用 os.O_APPEND: 追加写 os.O_CREATE:创建文件 这里的权限可以进行组合,用 | 分隔,如: os.O_RDWR | os.O_CREATE:创建文件并且以读写的方式打开文件 os.O_RDWR | os.O_APPEND:以读写的方式打开文件并且以追加的方式写(默认的写是覆盖写) 参数三: 通常传 0 当参数二为:O_CREATE时,该参数有实际作用:指定新建文件的属性 权限取值范围(0-7),表示如下: 0:没有任何权限 1:执行权限(如果是可执行文件,是可以运行的) 2:写权限 3: 写权限与执行权限 4:读权限 5: 读权限与执行权限 6: 读权限与写权限 7: 读权限,写权限,执行权限 返回值: file:文件指针。本质:file对象(结构体) err:错误返回: 具体案例如下: Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。 (1)按字符串写,WriteString()方法 这个方式是由以写的模式打开文件而生成的文件对象调用的。 参数:待写入文件的字符串 返回值: ret:写入文件的字节数 err:错误返回 具体实例如下: 执行之后,hello.txt文件中内容如下: (2)按位置写 先确定位置,Seek()方法: Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。 参数一:偏移量;矢量:正数向后,负数向前偏。 参数二: 0或者io.SeekStart : 从文件起始位置开始偏移。 1或者io.SeekCurrent: 从当前位置。 2或者io.SeekEnd: 从文件末尾位置开始偏移。 返回值: ret:较文件起始位置,偏过的字节数。 err:错误返回 然后根据的得到的偏移量来写文件,WriteAt()方法: WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。 参数一:待写入文件的数据内容,是字符切片类型。 参数二:偏移量;Seek函数的返回值ret。 返回值: n:写入文件的字节 err:错误返回 具体实例如下: 执行完后hello.txt中的内容是: (3)按字符写,Write()方法 Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。 参数:待写入文件的数据内容 返回值: n:写入的字节个数 err:错误处理 具体实例如下: 执行完后,hello.txt文件中内容如下: (1)按行读文件 可以通过两步来实现。 首先,创建一个带有缓冲区的Reader,使用bufio包下的NewReader()函数来实现。 NewReader创建一个具有默认大小缓冲、从r读取的*Reader。 参数:文件指针(open、Create、OpenFile 返回值) 返回值:带有缓冲区的阅读器 然后,从Reader 自带的缓冲区中,按指定的“分隔符(delim)”获取数据。我们通常使用ReadBytes(‘\n’) 来有效的提取一行数据。 ReadBytes读取直到第一次遇到delim字节,返回一个包含已读取的数据和delim字节的切片。如果ReadBytes方法在读取到delim之前遇到了错误,它会返回在错误之前读取的数据以及该错误(一般是io.EOF)。当且仅当ReadBytes方法返回的切片不以delim结尾时,会返回一个非nil的错误。 读到的数据成功保存在返回的[]byte 中。可以循环按行读取整个文件。 参数:分隔符,一般都是‘\n‘,Linux系统中的行结束标记。 返回值: line:实际读到的一行数据,是字符切片类型 err:错误处理 文件结尾:EOF —— end of file 当读到文件末尾时,err 会被置为 io.EOF 具体实例如下: 结果如下: (2)按字节读,Read()方法 Read读取数据写入p。本方法返回写入p的字节数。本方法一次调用最多会调用下层Reader接口一次Read方法,因此返回值n可能小于len(p)。读取到达结尾时,返回值n将为0而err将为io.EOF。 参数:空缓冲区(需要自己创建),用来存放read读到的数据内容。 返回值: n:实际读到的字节个数 err:错误处理 具体实例如下: 得到结果如下: 文件拷贝的核心思想就是读多少就写多少 我们读写的文件一般存放于目录中。因此,有时需要指定到某一个目录下,根据目录存储的状况再进行文件的特定操作。接下来我们看看目录的基本操作方法。 (1) 打开目录,OpenFile()方法 参数一:绝对或相对路径名 参数二:O_RDONLY 参数三:os.ModeDir 返回值: file:指向目录的文件指针 err:错误处理 (2)读目录内容,Readdir()方法 这与读文件有所不同。目录中存放的是文件名和子目录名。所以使用Readdir函数来完成。 Readdir读取目录f的内容,返回一个有n个成员的[]FileInfo,这些FileInfo是被Lstat返回的,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。 如果n>0,Readdir函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。如果到达了目录f的结尾,返回值err会是io.EOF。 如果n
参数:取的目录项个数, -1 表示所有。 返回值: fi:FileInfo类型的切片。其内部保存了文件名。 err:错误信息。 得到FileInfo类型切片后,我们可以range遍历切片元素,使用.Name()获取文件名。使用.Size()获取文件大小,使用.IsDir()判断文件是目录还是非目录文件。 如:我们可以提示用户提供一个目录位置,打开该目录,查看目录下的所有成员,并判别他们是文件还是目录。 示例如下: Go语言学习之路第9天(文件操作) 标签:lock ali 核心 矢量 indent 查看 特性 用户 函数 原文地址:https://www.cnblogs.com/dacaigouzi1993/p/11137545.html一.文件操作
1.1 创建文件
func Create(name string) (file *File, err error)
import (
"fmt"
"os"
)
func main() {
fw,err := os.Create("./hello.txt")
if err != nil {
fmt.Println("os.Create err:",err)
return
}
defer fw.Close()
}
1.2 打开文件
func Open(name string) (file *File, err error)
import (
"fmt"
"os"
)
func main() {
fr,err := os.Open("./hello.txt")
if err != nil{
fmt.Println("os.Open err:",err)
return
}
defer fr.Close()
}
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
import (
"fmt"
"os"
)
func main() {
//创建文件并且以读写的方式打开文件
frw,err := os.OpenFile("./hello.txt",os.O_RDWR | os.O_CREATE,0)
//以读写的方式打开文件并且以追加的方式写
//frw,err := os.OpenFile("./hello.txt",os.O_RDWR | os.O_APPEND,0)
if err != nil {
fmt.Println("os.OpenFile err:",err)
return
}
defer frw.Close()
}
1.3 关闭文件
func (f *File) Close() error
1.4 写文件
func (f *File) WriteString(s string) (ret int, err error)
func main() {
fw,err := os.Create("./hello.txt")
if err != nil{
fmt.Println("os.Create err:",err)
return
}
defer fw.Close()
n,err := fw.WriteString("Hello World\n")
if err != nil{
fmt.Println("fw.WriteString err:",err)
return
}
fmt.Println(n)
}
Hello World
func (f *File) Seek(offset int64, whence int) (ret int64, err error)
func (f *File) WriteAt(b []byte, off int64) (n int, err error)
func main() {
fw,err := os.OpenFile("./hello.txt",os.O_RDWR,0)
if err != nil{
fmt.Println("os.OpenFile err:",err)
return
}
defer fw.Close()
//位置偏移到末尾
ret,err := fw.Seek(0,io.SeekEnd)
if err != nil{
fmt.Println("fw.Seek err:",err)
return
}
n,err := fw.WriteAt([]byte("This is a Go Program\n"),ret)
if err != nil{
fmt.Println("fw.WriteAt err:",err)
return
}
fmt.Println(n)
}
Hello World
This is a Go Program
func (f *File) Write(b []byte) (n int, err error)
func main() {
//以读写方式打开文件并以追加的方式写
fw,err := os.OpenFile("./hello.txt",os.O_RDWR | os.O_APPEND,0)
if err != nil{
fmt.Println("os.OpenFile err:",err)
return
}
defer fw.Close()
n,err := fw.Write([]byte("Good Good Study,Day Day Up\n"))
if err != nil{
fmt.Println("fw.Write err:",err)
return
}
fmt.Println(n)
}
Hello World
This is a Go Program
Good Good Study,Day Day Up
1.5 读文件
func NewReader(rd io.Reader) *Reader
func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
fr,err := os.Open("./hello.txt")
if err != nil{
fmt.Println("os.Open err:",err)
return
}
defer fr.Close()
reader := bufio.NewReader(fr)
for{
line,err := reader.ReadBytes(‘\n‘)
if err != nil{
if err == io.EOF{
fmt.Println("文件已读完")
break
}else {
fmt.Println("reader.ReadBytes err:",err)
return
}
}
fmt.Print(string(line))
}
}
Hello World
This is a Go Program
Good Good Study,Day Day Up
文件已读完
func (b *Reader) Read(p []byte) (n int, err error)
func main() {
fr,err := os.Open("./hello.txt")
if err != nil{
fmt.Println("os.Open err:",err)
return
}
defer fr.Close()
//自定义缓冲区
slice := make([]byte,4096)
for{
n,err := fr.Read(slice)
if err != nil{
if err == io.EOF{
fmt.Println("文件已读完")
break
}else {
fmt.Println("fr.Read err:",err)
return
}
}
fmt.Print(string(slice[:n]))
}
}
Hello World
This is a Go Program
Good Good Study,Day Day Up
文件已读完
1.6 大文件拷贝
import (
"fmt"
"io"
"os"
)
func main() {
//以只读的方式打开待源文件
fr,err := os.Open("./01-复习.avi")
if err != nil{
fmt.Println("os.Open err:",err)
return
}
defer fr.Close()
//以写的方式打开目标文件
fw,err := os.Create("./复习.avi")
if err != nil{
fmt.Println("os.Create err:",err)
return
}
//创建缓冲区
buf := make([]byte,4096)
//循环读取源文件内容,然后读取多少就往目标文件写多少
for{
n,err := fr.Read(buf)
if err != nil{
if err == io.EOF{
fmt.Println("文件以拷贝完毕")
break
}else {
fmt.Println("fr.Read err:",err)
return
}
}
_,err = fw.Write(buf[:n])
if err != nil{
fmt.Println("fw.Write err:",err)
return
}
}
}
二.目录操作
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
func (f *File) Readdir(n int) (fi []FileInfo, err error)
type FileInfo interface {
Name() string // 文件的名字(不含扩展名)
Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同
Mode() FileMode // 文件的模式位
ModTime() time.Time // 文件的修改时间
IsDir() bool // 等价于Mode().IsDir()
Sys() interface{} // 底层数据来源(可以返回nil)
}
import (
"fmt"
"os"
)
func main() {
fmt.Print("请输入要找寻的目录:")
var path string
fmt.Scan(&path)
dir,err := os.OpenFile(path,os.O_RDONLY,os.ModeDir)
if err != nil{
fmt.Println("os.OpenFile err:",err)
return
}
s,err := dir.Readdir(-1)
if err != nil{
fmt.Println("dir.Readdir:",err)
return
}
for _,data := range s{
if data.IsDir(){
fmt.Println(data.Name(),"是一个目录。")
}else {
fmt.Println(data.Name(),"是一个文件。")
}
}
}