go语言文件操作

Posted qhdsavoki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了go语言文件操作相关的知识,希望对你有一定的参考价值。

文件操作

字符串处理函数

字符串在开发中使用频率较高,我们经常需要对字符串进行拆分、判断等操作,可以借助Go标准库中的strings包快速达到处理字符串的目录。除ContainsJoinTrimReplace等我们学过的字符串处理函数之外,以下函数也常常会被用到。

字符串分割

func Split(s, sep string) []string
//功能:把s字符串按照sep分割,返回slice
参1:s,表示待拆分的字符串
参2:sep,表示分割符,该参数为string 类型
返回值:切片,存储拆分好的子串

示例代码:

fmt.Printf("%q
", strings.Split("a,b,c", ","))
    fmt.Printf("%q
", strings.Split("a man a plan a canal panama", "a "))
    fmt.Printf("%q
", strings.Split(" xyz ", ""))
    fmt.Printf("%q
", strings.Split("", "Bernardo O‘Higgins"))
    //运行结果:
    //["a" "b" "c"]
    //["" "man " "plan " "canal panama"]
    //[" " "x" "y" "z" " "]
    //[""]

按空格拆分字符串

func Fields(s string) []string
//功能:去除s字符串的空格符,并且按照空格分割,返回slice
参1:s,表示待拆分的字符串
返回值:切片,存储拆分好的子串

示例代码:

 fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz   "))
  //运行结果:Fields are: ["foo" "bar" "baz"]

判断字符串后缀

func HasSuffix(s, suffix string) bool
功能:判断s字符串是否有后缀子串suffix
参1:s,表示待判定字符串
参2:suffix,表示前缀子串
返回值:true or false

示例代码:

fmt.Printf("%v
", strings.HasSuffix("World Cup.png", ".png"))
    //运行结果:true

判断字符串前缀

func HasPrefix(s, prefix string) bool
功能:判断s字符串是否有前缀子串suffix
参1:s,表示待判定字符串
参2:prefix,表示前缀子串
返回值:true or false

示例代码:

 fmt.Printf("%v
", strings.HasPrefix("World Cup.png", "world"))
    //运行结果:false

 

文件操作常用API

建立与打开文件

新建文件可以通过如下两个方法:

func Create(name string) (file *File, err Error)
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
技术分享图片
func main()  {
    f, err := os.Create("C:/itcast/test.txt")
    if err != nil {
        fmt.Println("Create err:", err)
        return
    }
    defer f.Close()

    fmt.Println("create successful")
}
View Code

通过如下两个方法来打开文件:

func Open(name string) (file *File, err Error)
技术分享图片
func main()  {

    f, err := os.Open("C:/itcast/test.txt")
    if err != nil {
        fmt.Println("open err: ", err)
        return
    }
    defer f.Close()

    _, err = f.WriteString("hello world")
    if err != nil {
        fmt.Println("WriteString err: ", err)
        return
    }
    fmt.Println("open successful")
}
View Code

 

Open()是以只读权限打开文件名为name的文件,得到的文件指针file,只能用来对文件进行“读”操作。如果我们有“写”文件的需求,就需要借助Openfile函数来打开了。

 

func OpenFile(name string, flag int, perm uint32) (file *File, err Error)

OpenFile()可以选择打开name文件的读写权限。这个函数有三个默认参数:

1name,表示打开文件的路径。可使用相对路径 绝对路径

参2flg,表示读写模式,常见的模式有:

O_RDONLY(只读模式), O_WRONLY(只写模式), O_RDWR(可读可写模式), O_APPEND(追加模式)。|  O_CREATE (当有此参数,必须指定 参数3)  重要的是如果读取目录的话只能指定O_RDONLY模式!!!!

3perm,表权限取值范围(0-7),表示如下:

0:没有任何权限

1:执行权限(如果是可执行文件,是可以运行的)

2:写权限

3: 权限与执行权限

4:读权限

5: 读权限与执行权限

6: 读权限与写权限

7: 读权限,写权限,执行权限

 

技术分享图片
func main()  {
    f, err := os.OpenFile("C:/itcast/test.txt", os.O_RDWR | os.O_CREATE, 0600)  // 777--rwx rwx rwx
    if err != nil {
        fmt.Println("OpenFile err: ", err)
        return
    }
    defer f.Close()
    f.WriteString("hello world12345...")

    fmt.Println("open successful")
}
View Code

 

关闭文件函数:

func (f *File) Close() error

写文件

1.按照字符串写:

func (file *File) WriteString(s string) (ret int, err Error)
写入string信息到文件
f.
WriteString
返回实际写出的字节数

windows: 回车、换行。

Linux: 回车、换行。


2.指定位置写入

1)Seek():  获取文件读写位置。
       func (f *File) Seek(offset int64, whence int) (ret int64, err error) 
            offset: 矢量。 正数,向文件末尾偏移。负数,向文件开头偏移
            whence: 偏移的起始位置。
                io.SeekStart : 文件起始位置。
                io.SeekCurrent : 文件当前位置。    
                io.SeekEnd: 文件末尾位置。
            返回值 ret: 从文件起始位置到,读写位置的偏移量。                        

2)WriteAt(): 在指定位置写入数据。, 通常搭配 Seek()用
        func (f *File) WriteAt(b []byte, off int64) (n int, err error)
            b: 待写入的数据内容
            off:写入的位置。(通常是 Seek函数的 返回值)    

例子:

技术分享图片
package main

import (
    "os"
    "fmt"
    "io"
)

func main()  {

    f, err := os.Create("./test.txt")
    if err != nil {
        fmt.Println("Create err:", err)
        return
    }
    defer f.Close()

    n, err := f.WriteString("hello world
")
    if err != nil {
        fmt.Println("WriteString err:", err)
        return
    }
    fmt.Println("n = ", n)

    //off, err := f.Seek(5, io.SeekStart)
    off, err := f.Seek(-5, io.SeekEnd)
    if err != nil {
        fmt.Println("Seek err:", err)
        return
    }
    fmt.Println("off:", off)

    n, err = f.WriteAt([]byte("1111"), off)
    if err != nil {
        fmt.Println("WriteAt err:", err)
        return
    }

    fmt.Println("write successful")
}
View Code

 

3.按字节写--按字节读 :重要!!!!! ---- 按字节处理文件。既可以处理文本也可以处理二进制文件(.jpg/mp3/avi....)

func (file *File) Read(b []byte) (n int, err Error)

   b: 用来存储读到的数据的 缓冲区。

   返回n:实际读到的 字节数。

 func (file *File) Write(b []byte) (n int, err Error)

   b: 存储数据的缓冲区,其中的数据即将被写入文件。。

   返回n:实际写出的 字节数。

 
技术分享图片
 1 func main01()  {
 2     f, err := os.OpenFile("test.txt", os.O_RDWR, 0600)
 3     if err != nil {
 4         fmt.Println("Open err:", err)
 5         return
 6     }
 7     defer f.Close()
 8 
 9     buf := make([]byte, 4096)    // 4k
10 
11     n, err := f.Read(buf)
12     if err != nil {
13         fmt.Println("Read err:", err)
14         return
15     }
16     fmt.Printf("read data:%s", buf[:n])
17 }
18 
19 func main02()  {
20     f, err := os.OpenFile("test.txt", os.O_RDWR, 0600)
21     if err != nil {
22         fmt.Println("Open err:", err)
23         return
24     }
25     defer f.Close()
26 
27     n, err := f.Write([]byte("AAA"))
28     if err != nil {
29         fmt.Println("Write err:", err)
30         return
31     }
32     fmt.Println("n = ", n)
33 }
按照字节读写

 

读文件:bufio

按行读。----- 处理文本文件。
        1) 获取一个 reader(自带缓冲区)
            func NewReader(rd io.Reader) *Reader 
                rd: 成功打开的文件指针。 f
                返回值:Reader (阅读器,自带缓冲区)
        2)从 reader 的缓冲区中获取 指定数据 ReadBytes( 
 )
            func (b *Reader) ReadBytes(delim byte) ([]byte, error)
                delim :读取数据的拆分依据。
                返回值:成功获取到的数据内容。
        通常,会使用 for 来循环调用  ReadBytes, 一直读到 err == io.EOF 的时候,结束信息。代表文件读取完毕。
技术分享图片
 1 package main
 2 
 3 import (
 4     "os"
 5     "fmt"
 6     "bufio"
 7     "io"
 8 )
 9 
10 func main()  {
11     f, err := os.Open("test.txt")
12     if err != nil {
13         fmt.Println("Open err:", err)
14         return
15     }
16     defer f.Close()
17 
18     // 获取阅读器 reader, 自带缓冲区(用户缓冲)。
19     reader := bufio.NewReader(f)
20 
21     for {            // 循环读取文件, 当 err == io.EOF 结束循环
22         // 使用 带分割符的 函数,读取指定数据 ‘
’获取一行
23         buf, err := reader.ReadBytes(
)
24         // 成功读取到的一行数据 保存在 buf中
25         fmt.Printf("buf:%s", buf)
26         if err != nil && err == io.EOF {
27             break
28         }
29     }
30     fmt.Println("文件读取完毕")
31 }
按行读文件

读目录:

1) 打开目录  OpenFile
        func OpenFile(name string, flag int, perm FileMode) (*File, error) 
            flag: 只能指定 O_RDONLY
            perm : os.ModeDir        ---> 操作目录文件
            返回: 操作目录文件的 指针    
2) 读取目录项  Readdir
        func (f *File) Readdir(n int) ([]FileInfo, error)
            n:读取目录项的个数。 -1 表全部
            返回值:每一个目录项 描述信息的(FileInfo) 切片
[]FileInfo 切片
       type FileInfo interface {
        Name() string       // base name of the file
        Size() int64        // length in bytes for regular files; system-dependent for others
        。。。
        IsDir() bool        // abbreviation for Mode().IsDir()
        。。。
      }            
技术分享图片
 1 package main
 2 
 3 import (
 4     "os"
 5     "fmt"
 6 )
 7 
 8 func main()  {
 9     var dir string
10     fmt.Print("请输入一个待判定的目录:")
11     fmt.Scan(&dir)
12 
13     // 打开目录
14     f, err := os.OpenFile(dir, os.O_RDONLY, os.ModeDir)
15     if err != nil {
16         fmt.Println("OpenFile err:", err)
17         return
18     }
19     defer f.Close()
20 
21     // 读取目录项 -- 将一个目录下的所有内容, 存入[]FileInfo
22     fileInfo, err := f.Readdir(-1)
23     if err != nil {
24         fmt.Println("Readdir err:", err)
25         return
26     }
27 
28     // 依次取出目录项
29     for _, dirInfo := range fileInfo {
30         if dirInfo.IsDir() {
31             fmt.Printf("%s 是一个 目录
", dirInfo.Name())
32         } else {
33             fmt.Printf("%s is not 目录
", dirInfo.Name())
34         }
35     }
36 
37 }
读取目录

 

练习例子

大文件拷贝实现:
1
. 只读打开文件 os.Open --> fr defer close() 2. 创建新文件 os.Create --> fw defer close() 3. for 循环安字节读取 fr 中的所有数据, 存入 buf 4. 读多少,写多少,将buf 中数据写入 fw 5. 判断 err == io.EOF 来确认读到文件末尾。
技术分享图片
package main

import (
    "os"
    "fmt"
    "io"
)

func main()  {
    // 创建 待读取的文件,和 待写入的文件
    f_r, err := os.Open("C:/itcast/01-结构体的定义和初始化.avi")
    if err != nil {
        fmt.Println("open err:", err)
        return
    }
    defer f_r.Close()

    f_w, err := os.Create("./test.avi")
    if err != nil {
        fmt.Println("Create err:", err)
        return
    }
    defer f_w.Close()

    buf := make([]byte, 4096)    //创建缓冲区,存储读到的数据

    // 循环从 f_r 对应文件中读取数据,
    for {
        n, err := f_r.Read(buf)
        if err == io.EOF {
            fmt.Println("读取文件完成")
            break
        }
        if err != nil {
            fmt.Println("Read err:", err)
            return
        }
        // 原封不动写到 f_w 文件中, 读多少,写多少
        n, err = f_w.Write(buf[:n])
        if err != nil {
            fmt.Println("Write err:", err)
            return
        }
    }

    os.OpenFile()
}
View Code

练习1  初级练习

技术分享图片
func main() {
    //从用户给出的目录中,找出所有的 .jpg 文件
     var path string
     fmt.Scan(&path)
     f,err:=os.OpenFile(path,os.O_RDONLY,os.ModeDir)
     if err!=nil{
         fmt.Println(err)
         return
     }
     fileinfo,err:=f.Readdir(-1)
     if err!=nil{
        fmt.Println("err",err)
        return
    }
     for _,i:=range fileinfo{
        if strings.HasSuffix(i.Name(),"jpg"){
            fmt.Println(i.Name())
        }
    }
从用户给出的目录中,找出所有的 .jpg 文件

练习2 中级练习

技术分享图片
package main

import (
    "fmt"
    "os"
    "strings"
    "io"
)

func copyMp3ToDir(fileName, path string)  {
    pathName := path + "/" + fileName
    fr, err := os.Open(pathName)                // 打开 源文件
    if err != nil {
        fmt.Println("Open err:", err)
        return
    }
    defer fr.Close()

    fw, err :=os.Create("./" + fileName)        // 打开拷贝的文件
    if err != nil {
        fmt.Println("Create err:", err)
        return
    }
    defer fw.Close()

    // 创建一个用于read 存储数据的 buf
    buf := make([]byte, 4096)

    // 循环从 fr 中读取数据, 原封不动 写到 fw中
    for {
        n, err := fr.Read(buf)
        if n == 0 {
            fmt.Println("文件拷贝完毕")
            break
        }
        if err != nil && err != io.EOF {
            fmt.Println("err:", err)
        }
        fw.Write(buf[:n])      // 读多少,写多少
    }

}

func main()  {
    // 请用户指定 目录
    var path string
    fmt.Print("请输入目录位置:")
    fmt.Scan(&path)

    // 打开指定目录位置
    dir_fp, err := os.OpenFile(path, os.O_RDONLY, os.ModeDir)
    if err != nil {
        fmt.Println("Openfile err:", err)
        return
    }
    defer dir_fp.Close()

    // 读取目录项
    dirsInfo, err := dir_fp.Readdir(-1)
    if err != nil {
        fmt.Println("Readdir err:", err)
        return
    }
    // 从目录项[] 中提取每一个目录项
    for _, dir := range dirsInfo {
        fileName := dir.Name()
        // 根据后缀名,筛选文件
        if strings.HasSuffix(fileName, ".mp3") {

            // 将该文件 copy 至指定目录
            copyMp3ToDir(fileName, path)
            //fmt.Println("mp3文件有:", fileName)
        }
    }
}
从用户给出的目录中,拷贝 .mp3文件到指定目录中。
技术分享图片
    //2.从用户给出的目录中,拷贝 .mp3文件到指定目录中。
    args:=os.Args
    f1,err:=os.OpenFile(args[1],os.O_RDONLY,os.ModeDir)
    if err!=nil{
        fmt.Println(err)
        return
    }
    fmt.Println(args[1],args[2])
    fileinfo,err:=f1.Readdir(-1)
    if err!=nil {
        fmt.Println(err)
    }
    for _,name:=range fileinfo{
        //fmt.Println(name)
        if strings.HasSuffix(name.Name(),".mp3"){
            fmt.Println(name.Name())
            copyfile(args[1]+"/"+name.Name(),args[2]+"/"+name.Name())
        }
    }
    defer f1.Close()
}
func copyfile(dst,src string){
    buf:=make([]byte,4096)
    f1, err := os.OpenFile(dst, os.O_RDONLY, 0666)
    if err != nil {
        fmt.Println(err)
        return
    }
    fw, err := os.Create(src)
    if err != nil {
        fmt.Println(err)
        return
    }
    for {
        n, err := f1.Read(buf)
        if err != nil || err ==io.EOF{
            fmt.Println(err)
            break
        }
        fw.Write(buf[:n])
    }
        defer fw.Close()
自己写的

练习3  高级练习

技术分享图片
 1 package main
 2 
 3 import (
 4     "os"
 5     "fmt"
 6     "strings"
 7     "bufio"
 8     "io"
 9 )
10 
11 func countLove(fileName, path string) int {
12     // 打开文件,txt
13     f, err := os.Open(path + "/" + fileName)
14     if err != nil {
15         fmt.Println("Open err:", err)
16         return -1
17     }
18     defer f.Close()
19 
20     // 1 创建 reader
21     reader := bufio.NewReader(f)
22     var counter int = 0
23 
24     // for 循环 按行读取文件,--- this is a  test for love  --》[]string
25     for {
26         // 2 指定分隔符,按行提取数据
27         buf, err := reader.ReadBytes(
)            // buf中保存读到的一行数据
28         if err != nil && err == io.EOF {
29             break
30         }
31         if err != nil {
32             fmt.Println("ReadBytes err:", err)
33             return -1
34         }
35         // 将一行数据中的所有单词 拆分
36         words := strings.Fields(string(buf))
37         for _, word := range words {
38             if word == "love" {
39                 counter++    // 统计 个数。
40             }
41         }
42     }
43     fmt.Println("counter:", counter)
44 
45     return counter
46 }
47 
48 func main()  {
49 
50     // 测试统计 函数是否生效
51     //countLove("test.txt", "C:/itcast/test2")
52 
53     // 请用户指定 目录
54     var path string
55     fmt.Print("请输入目录位置:")
56     fmt.Scan(&path)
57 
58     // 打开指定目录位置
59     dir_fp, err := os.OpenFile(path, os.O_RDONLY, os.ModeDir)
60     if err != nil {
61         fmt.Println("Openfile err:", err)
62         return
63     }
64     defer dir_fp.Close()
65 
66     // 统计目录下所有 txt 文件的 love 个数
67     var allLove int = 0
68 
69     // 读取目录项
70     dirsInfo, err := dir_fp.Readdir(-1)
71     if err != nil {
72         fmt.Println("Readdir err:", err)
73         return
74     }
75     // 从目录项[] 中提取每一个目录项
76     for _, dir := range dirsInfo {
77         fileName := dir.Name()
78         // 根据后缀名,筛选文件
79         if strings.HasSuffix(fileName, ".txt") {
80             // 打开文件, 统计 该文件中有多少个 “love”
81             allLove += countLove(fileName, path)
82         }
83     }
84     fmt.Println("指定的目录中,一共包含 love 个数:", allLove)
85 }
统计指定目录下,所有.txt文件中,“Love”这个单词 出现的次数
技术分享图片
 1 package main
 2 
 3 import (
 4     "os"
 5     "fmt"
 6     "strings"
 7     "bufio"
 8     "io"
 9 )
10 
11 func main() {
12     //统计指定目录下,所有.txt文件中,“Love”这个单词 出现的次数。
13     args:=os.Args
14     fdir,err:=os.OpenFile(args[1],os.O_RDONLY,os.ModeDir)
15     if err!=nil{
16         fmt.Println(err)
17         return
18     }
19     fileinof,err:=fdir.Readdir(-1)
20     var txt []string
21     for _,info:=range fileinof{
22 
23         if strings.HasSuffix(info.Name(),".txt"){
24             fmt.Println(info.Name())
25             txt=append(txt, info.Name())
26         }
27     }
28     for _,v:=range txt{
29         prisetxt("love","D:/111/"+v)
30     }
31 }
32 //func dir(){}
33 func prisetxt(s string,txt string){
34 
35     f1,err:=os.Open(txt)
36     if err!=nil{
37         fmt.Println(err)
38     }
39     reader:=bufio.NewReader(f1)
40     //conster :=0
41     for {
42         bytess, err := reader.ReadBytes(
)
43         fmt.Println(string(bytess))
44         con:=strings.Split(string(bytess),"love")
45         fmt.Println(len(con)-1)
46         if err != nil || err == io.EOF {
47             fmt.Println(err)
48             break
49         }
50 
51     }
52     defer f1.Close()
53     //fmt.Println(conster)
54 
55 }
自己写的思想

 

 

以上是关于go语言文件操作的主要内容,如果未能解决你的问题,请参考以下文章

go语言-关于文件的操作和解释

超赞的 Go 语言 INI 文件操作

[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础

Day05 Go语言文件操作,结构体,构造函数,方法接收器,json序列化

go 语言的一个赋值操作

Go语言文件操作