golang file,文件操作

文件大小

1
2
3
4
5
6
7
func main() {
    fi,err:=os.Stat("water")
    if err ==nil {
        fmt.Println("file size is ",fi.Size(),err)
    }
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package main

import (
    "bufio"
    "fmt"
    "io"
    "io/ioutil"
    "os"
)

func main() {
    dir := "/tmp/foo/bar"
    fileName := "file0.txt"
    writeTxtFile(dir, fileName, "foo")
    out := readTxtFile(dir, fileName)
    fmt.Println("read result: " + out)
}
func writeTxtFile0(dir, fileName, content string) {
    if !isExist(dir) {
        err := os.MkdirAll(dir, 0777)
        if err != nil {
            fmt.Printf("%s\n", err)
        } else {
            fmt.Println("Create Directory OK!")
        }
    }

    fullFileName := dir + string(os.PathSeparator) + fileName
    file, e := os.OpenFile(fullFileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0777)
    if e != nil {
        fmt.Println("open file: " + e.Error())
    }
    defer file.Close()

    n, err := file.WriteString(content)
    if err != nil {
        fmt.Println("write string: " + err.Error())
        return
    }
    fmt.Printf("write length: %v\n", n)
}
func writeTxtFile(dir, fileName, content string) {
    if !isExist(dir) {
        err := os.MkdirAll(dir, 0777)
        if err != nil {
            fmt.Printf("%s\n", err)
        } else {
            fmt.Println("Create Directory OK!")
        }
    }
    err := ioutil.WriteFile(dir+string(os.PathSeparator)+fileName, []byte(content), 0777)
    if err != nil {
        fmt.Printf("failed to write file, file name: %v, err: %v", fileName, err)
        return
    }
}

// read txt file
func readTxtFile(dir, fileName string) string {
    path := dir + string(os.PathSeparator) + fileName
    dat, err := ioutil.ReadFile(path)
    if err != nil {
        fmt.Println("failed to read file: " + fileName)
    }
    return string(dat)
}

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func isExist(fileName string) bool {
    _, err := os.Stat(fileName)
    if err == nil {
        fmt.Println("file exist: " + fileName)
        return true
    } else if os.IsNotExist(err) {
        fmt.Println("file not exist")
        return false

    } else {
        fmt.Println("file error")
    }
    return false
}

判断是文件还是目录

1
2
f, _ := os.Stat("a.txt")
f.IsDir()

move file

1
2
3
4
5
6
7
8
func main() {
    oldLocation := "/var/www/html/test.txt"
    newLocation := "/var/www/html/src/test.txt"
    err := os.Rename(oldLocation, newLocation)
    if err != nil {
        log.Fatal(err)
    }
}

判断文件是否存在

1
os.Stat(parentDir)
1
2
// 创建目录
os.Mkdir(parentDir, os.ModePerm)

删除文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
file := "test.txt"
err := os.Remove(file)

package main

import (
"fmt"
"os"
)

    // 判断文件夹是否存在
    func PathExists(path string) (bool, error) {
    _, err := os.Stat(path)
    if err == nil {
    return true, nil
    }
    if os.IsNotExist(err) {
    return false, nil
    }
    return false, err
    }
    
    func main() {
    _dir := "./gzFiles2"
    exist, err := PathExists(_dir)
    if err != nil {
    fmt.Printf("get dir error![%v]\n", err)
    return
    }

    if exist {
        fmt.Printf("has dir![%v]\n", _dir)
    } else {
        fmt.Printf("no dir![%v]\n", _dir)
        // 创建文件夹
        err := os.Mkdir(_dir, os.ModePerm)
        if err != nil {
            fmt.Printf("mkdir failed![%v]\n", err)
        } else {
            fmt.Printf("mkdir success!\n")
        }
    }

}

写文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/***************************** 第一种方式: 使用 io.WriteString 写入文件***/
if checkFileIsExist(filename) { //如果文件存在
f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件
fmt.Println("文件存在")
} else {
f, err1 = os.Create(filename) //创建文件
fmt.Println("文件不存在")
}
check(err1)
n, err1 := io.WriteString(f, wireteString) //写入文件(字符串)
check(err1)
fmt.Printf("写入 %d 个字节n", n)

    /*****************************  第二种方式: 使用 ioutil.WriteFile 写入文件****/
    var d1 = []byte(wireteString)
    err2 := ioutil.WriteFile("./output2.txt", d1, 0666) //写入文件(字节数组)
    check(err2)
    
    /*****************************  第三种方式:  使用 File(Write,WriteString) 写入文件***/
    f, err3 := os.Create("./output3.txt") //创建文件
    check(err3)
    defer f.Close()
    n2, err3 := f.Write(d1) //写入文件(字节数组)
    check(err3)
    fmt.Printf("写入 %d 个字节n", n2)
    n3, err3 := f.WriteString("writesn") //写入文件(字节数组)
    fmt.Printf("写入 %d 个字节n", n3)
    f.Sync()
    
    /***************************** 第四种方式:  使用 bufio.NewWriter 写入文件****/
    w := bufio.NewWriter(f) //创建新的 Writer 对象
    n4, err3 := w.WriteString("bufferedn")
    fmt.Printf("写入 %d 个字节n", n4)
    w.Flush()
    f.Close()

一般文件比较小的话可以将文件全部读入内存中,然后转换成string再按行分割一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func GetFileContentAsStringLines(filePath string) ([]string, error) {
logger.Infof("get file content as lines: %v", filePath)
result := []string{}
b, err := ioutil.ReadFile(filePath)
if err != nil {
logger.Errorf("read file: %v error: %v", filePath, err)
return result, err
}
s := string(b)
for _, lineStr := range strings.Split(s, "\\n") {
lineStr = strings.TrimSpace(lineStr)
if lineStr == "" {
continue
}
result = append(result, lineStr)
}
logger.Infof("get file content as lines: %v, size: %v", filePath, len(result))
return result, nil
}

Golang 超大文件读取的两个方案

第一个是使用流处理方式代码如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func ReadFile(filePath string, handle func(string)) error {
f, err := os.Open(filePath)
defer f.Close()
if err != nil {
return err
}
buf := bufio.NewReader(f)

    for {
        line, err := buf.ReadLine("\n")
        line = strings.TrimSpace(line)
        handle(line)
        if err != nil {
            if err == io.EOF{
                return nil
            }
            return err
        }
        return nil
    }

}

第二个方案就是分片处理, 当读取的是二进制文件,没有换行符的时候,使用下面的方案处理大文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
func ReadBigFile(fileName string, handle func([]byte)) error {
f, err := os.Open(fileName)
if err != nil {
fmt.Println("can't opened this file")
return err
}
defer f.Close()
s := make([]byte, 4096)
for {
switch nr, err := f.Read(s[:]); true {
case nr < 0:
fmt.Fprintf(os.Stderr, "cat: error reading: %s\n", err.Error())
os.Exit(1)
case nr == 0: // EOF
return nil
case nr > 0:
handle(s[0:nr])
}
}
return nil
}

https://learnku.com/articles/23559/two-schemes-for-reading-golang-super-large-files https://blog.csdn.net/xielingyun/article/details/50324423
https://blog.csdn.net/robertkun/article/details/78776585