go语言的文件操作

118 阅读6分钟

1 打开文件

1.1 os.OpenFile()

函数定义: func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

flag:

  • os.O_CREATE : 不存在就创建文件
  • os.O_RDWR : 赋予读写权限
  • os.O_APPEND : 新数据以追加的方式写入文件(即写入到最后一行)

perm:

  • 0777:创建了一个普通文件,所有人拥有所有的读、写、执行权限
  • 0666:创建了一个普通文件,所有人拥有对该文件的读、写权限,但是都不可执行
  • 0644:创建了一个普通文件,文件所有者对该文件有读写权限,用户组和其他人只有读权限,没有执行权限

1.2 os.Open()

函数定义:func Open(name string) (*File, error)

注意:os.Open其实是os.OpenFile()的只读模式,自然就没有flag和perm参数

2 关闭文件

2.1 file.Close()

函数定义:func (f *File) Close() error

3 创建文件

3.1 os.Create()

函数定义: func Create(name string) (file *File, err Error)

4 读文件

4.1 os.ReadFile()

函数定义:func ReadFile(name string) ([]byte, error)

使用注意:os.ReadFile()是读取整个文件,一般用于小文件

代码示例:

package main
import(
    "fmt"
    "os"
    "strings"
)
func check(err error){
    if err!=nil{
        panic(err)
    }
}
func main(){
    content,err:=os.ReadFile("tmp/dat.txt")
    //"tmp/dat.txt"是我在project文件夹下创建的文件
    check(err)
    fmt.Println(string(content))
    //将[]type类型的content强转为string类型
    
}

4.2 ioutil.ReadFile()

注意:从 Go 1.16 开始,ioutil.ReadFile 就等价于 os.ReadFile,二者是完全一致的

4.3 ioutil.ReadAll()

函数定义:func ReadAll(r io.Reader) ([]byte, error)

其实io.Reader还是file*类型

4.4 读取文件综合代码示例

package main  
  
import (  
"bufio"  
"fmt"  
"io"  
"io/ioutil"  
"os"  
"strings"  
)  
  
func check(e error) {  
if e != nil {  
panic(e)  
}  
}  
func main() {  
//1读取整个文件  
//1.1直接指定文件名读取  
//os.ReadFile//返回的是字节数组  
content, err := os.ReadFile("tmp/dat.txt")  
check(err)  
fmt.Println(string(content))  
  
//ioutil.ReadFile  
content, err = ioutil.ReadFile("tmp/dat.txt")  
check(err)  
fmt.Println(string(content))  
  
//在 Go 1.16 开始,ioutil.ReadFile 就等价于 os.ReadFile,二者是完全一致的  
  
//1.2先创建 句柄(文件指针/流) 在读取  
  
//仅是读取的话,可以使用高级函数os.Open()*file{}  
file, err := os.Open("./tmp/dat.txt") //返回了一个文件指针(流)  
check(err)  
defer file.Close()  
content, err = ioutil.ReadAll(file) //ioutil.ReadFile()里形参为文件指针  
fmt.Println(string(content)) //强转  
//ioutil.ReadFile(*file)  
  
//os.Open()是只读模式的os.OpenFile()  
//所以可以直接使用os.OpenFile()  
file, err = os.OpenFile("./tmp/dat.txt", os.O_RDONLY, 0)  
check(err)  
//我只能说尽量用os.OpenFile(name,)  
  
//2每次只读取一行,解决内存占用过大的问题  
//bufio.ReadBytes("\n")和bufio.ReadString("\n")  
//2.1bufio.ReadBytes("\n")  
file, err = os.Open("tmp/dat.txt") //先打开文件并创建句柄  
check(err)  
r := bufio.NewReader(file) //利用句柄和bufio.NewReader创建reader  
for {  
lineBytes, err := r.ReadBytes('\n') //读取一行  
////读取错误返回nil,读取delim之前遇到错误返回io.EOF  
// If ReadBytes encounters an error before finding a delimiter, it returns the data read before the error and the error itself (often io.EOF).  
//[]byte,err:=reader.ReadBytes(delim byte)  
line := strings.TrimSpace(string(lineBytes)) //需要强转在剪切  
//str1:=string.TrimSpace(str2 string)//string.TrimSpace()会将str2的\n\t\r全部剪去,只剩下可输出的字符串  
if err != nil && err != io.EOF {  
panic(err)  
}  
if err == io.EOF {  
break  
} //错误处理  
fmt.Println(line) //输出  
}  
//2.2bufio.ReadString()  
file, err = os.Open("tmp/dat.txt") //os.open()创建句柄  
check(err)  
r = bufio.NewReader(file) //bufio.NewReader()将句柄生成reader  
for {  
line, err := r.ReadString('\n') //reader.ReadString()读取一行  
line = strings.TrimSpace(line) //修剪line  
if err != nil && err != io.EOF {  
panic(err)  
}  
if err == io.EOF {  
break  
} //错误处理  
fmt.Println(line) //输出  
}  
//reader.ReadBytes()返回的是[]byte,而reader.ReadString()返回的是string  
//3每次读取固定字节数  
//不是所有的文件都有换行符\n  
//那么对于不换行的大文件来说怎么处理呢  
//3.1使用os库  
//具体做法:1 使用os.Open()创建句柄,2 使用bufio.NewReader()创建Reader,3 在for循环内调用Reader的Read函数,每次仅读取固定字节数量的数据  
file, err = os.Open("tmp/dat.txt")  
check(err)  
r = bufio.NewReader(file)  
buf := make([]byte, 1024) //临时存储每次得到的字节(1024个)  
for {  
n, err := r.Read(buf) //返回的n是每次读取到的字节数目,可能小于len(buf)  
if err != io.EOF && err != nil {  
panic(err)  
}  
if n == 0 {  
break  
} //读完了  
fmt.Println(buf[:n]) //读多少输出多少,不把buf后面的默认值也输出出来  
}  
//在使用os库每次读取特定字节时,我们不用将buf[]byte数组转化为string  
  
//3.2使用syscall库  
//os库本质上也是在调用syscall库,使用syscall过于底层,一般不使用  
  
b3 := make([]byte, 2)  
n3, err := io.ReadAtLeast(file, b3, 2)  
check(err)  
fmt.Println("size =", n3, ",b3 =", b3)  
_, err = file.Seek(0, io.SeekStart) //回转  
check(err)  
  
}

上述代码中出现了函数reader.ReadString()strings.TrimSpace()reader.Read(),解释如下:

函数定义:func (b *Reader) ReadString(delim byte) (string, error)

delim:读取的结束字符,一般为“\n”

功能:读取一行

函数定义:func TrimSpace(s string) string

功能:用空格替代\t\r\n

函数定义:func (b *Reader) Read(p []byte) (n int, err error)

功能:按p数组的len读取字符到p数组中,n为实际读到的字符数,返回io.EOF(读到文件结尾了)或nil(啥也没读到)

5 写文件

5.1 file.Write()

函数定义: func (f *File) Write(b []byte) (n int, err error)

使用注意:使用之前先要判断文件是否存在

具体判断代码:

func Exists(path string) bool {  
_, err := os.Stat(path) //os.Stat获取path下的文件信息  
// func Stat(name string) (FileInfo, error)  
  
if err == nil || (err != nil && os.IsExist(err)) {  
return true  
}  
return false  
}

5.2 io.WriteString()

函数定义:func WriteString(w Writer, s string) (n int, err error)

代码示例:

package main  
  
import (  
"fmt"  
"io"  
"os"  
)  
  
const strs = "\n \n 写文件ok思密达3"
//strs是待写入的字符串
func main() {  
//func WriteString(w Writer(对象), s string) (n int(写入的字节数), err error)  

fmt.Println("golang写文件")  
var (  
fileName = "./tmp/2.txt"
//./表示project的路径,是一种代替
content = strs  
file *os.File //创建句柄类型file变量  
err error  
) //变量集合  

//使用io.WriteString()之前先判断文件是否存在
if Exists(fileName) { //当文件存在  
file, err = os.OpenFile(fileName, os.O_APPEND, 0666)  
//os.Open()是只读模式的os.OpenFile()若要写文件则用os.OpenFile(),但要记得用defer file.Close()关闭文件以释放资源  
if err != nil {  
fmt.Println("打开文件错误:", err)  
return  
}  
fmt.Println("打开文件成功")  
} else { //文件不存在  
file, err = os.Create(fileName) //创建文件  
if err != nil {  
fmt.Println("创建文件失败:", err)  
return  
}  
fmt.Println("创建文件成功")  
}  
defer file.Close() //要记得fileinfo需在函数执行完后关闭  
//写文件  
n, err := io.WriteString(file, content)  
if err != nil {  
fmt.Println("写入文件错误:", err)  
return  
}  
fmt.Println("写入文件成功,n =", n)  
//读取文件 
filecontent, err := os.ReadFile(fileName)  
if err != nil {  
fmt.Println("读取错误:", err)  
return  
}  
fmt.Println(string(filecontent))  
}  
  
// 判断所给路径文件是否存在  
func Exists(path string) bool {  
_, err := os.Stat(path) //os.Stat获取path下的文件信息  
// func Stat(name string) (FileInfo, error)  
  
if err == nil || (err != nil && os.IsExist(err)) {  
return true  
}  
return false  
}

5.3 ioutil.WriteFile()

函数定义:func WriteFile(filename string, data []byte, perm fs.FileMode) error

使用注意:用之前先判断文件是否存在

代码示例:

//func WriteFile(filename string, data []byte, perm os.FileMode) error  
//perm 文件权限 data 要写入的内容  
//使用 ioutil.WriteFile写文件,在写入文件之前,我们不需要判断文件是否存在,如果文件不存在,会自动创建文件,如果文件存在,则会覆盖原来的内容  
  
package main  
  
import (  
"fmt"  
"io/ioutil"  
)  
  
const strs1 = "\n \n 完美世界 (石昊)"  
  
func main() {  
var (  
fileName = "./tmp/3.txt"  
content = strs1  
err error  
)  
//写入文件  
if err = ioutil.WriteFile(fileName, []byte(content), 0777); err != nil {  
fmt.Println("写入错误:", err)  
return  
}  
//读取文件  
fileContent, err := ioutil.ReadFile(fileName)  
if err != nil {  
fmt.Println("读取错误:", err)  
return  
}  
fmt.Println("读取成功,文件内容:", string(fileContent))  
  
}

5.4 file.WriteString()

函数定义:func (f *File) WriteString(s string) (n int, err error)

注意:使用前先判断文件是否存在

与io.WriteString()区别:

n,err =io.WriteString(file,content)  

n,err =file.WriteString(content)

6 其他有关文件的函数

6.1 os.Stat()

函数定义:func Stat(path string) (FileInfo, error)

6.2 bufio.NewReader()

函数定义:func NewReader(rd io.Reader) *Reader

函数功能:传入*file,返回*Reader


文末声明:时间有限,关于go语言文件的操作还不够详尽,日后可能会补充

有关go的各种包内的函数的详细解释请前往官网pkg.go.dev/搜索