基础操作 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 import ( "log" "os" ) func main () { f, err := os.Create("asong.txt" ) if err != nil { log.Fatalf("create file failed err=%s\n" , err) } fileInfo, err := f.Stat() if err != nil { log.Fatalf("get file info failed err=%s\n" , err) } log.Printf("File Name is %s\n" , fileInfo.Name()) log.Printf("File Permissions is %s\n" , fileInfo.Mode()) log.Printf("File ModTime is %s\n" , fileInfo.ModTime()) err = f.Chmod(0777 ) if err != nil { log.Fatalf("chmod file failed err=%s\n" , err) } err = f.Chown(os.Getuid(), os.Getgid()) if err != nil { log.Fatalf("chown file failed err=%s\n" , err) } fileInfo, err = f.Stat() if err != nil { log.Fatalf("get file info second failed err=%s\n" , err) } log.Printf("File change Permissions is %s\n" , fileInfo.Mode()) err = f.Close() if err != nil { log.Fatalf("close file failed err=%s\n" , err) } err = os.Remove("asong.txt" ) if err != nil { log.Fatalf("remove file failed err=%s\n" , err) } }
写文件 快写文件 os/ioutil包都提供了WriteFile方法可以快速处理创建/打开文件/写数据/关闭文件,使用示例如下:
1 2 3 4 5 6 7 func writeAll (filename string ) error { err := os.WriteFile("asong.txt" , []byte ("Hi asong\n" ), 0666 ) if err != nil { return err } return nil }
按行写文件 os、buffo写数据都没有提供按行写入的方法,所以我们可以在调用os.WriteString、bufio.WriteString方法是在数据中加入换行符即可,来看示例:
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 import ( "bufio" "log" "os" ) func writeLine (filename string ) error { data := []string { "asong" , "test" , "123" , } f, err := os.OpenFile(filename, os.O_WRONLY, 0666 ) if err != nil { return err } for _, line := range data{ _,err := f.WriteString(line + "\n" ) if err != nil { return err } } f.Close() return nil } func writeLine2 (filename string ) error { file, err := os.OpenFile(filename, os.O_WRONLY, 0666 ) if err != nil { return err } bufferedWriter := bufio.NewWriter(file) for i:=0 ; i < 2 ; i++{ bytesWritten, err := bufferedWriter.WriteString("asong真帅\n" ,) if err != nil { return err } log.Printf("Bytes written: %d\n" , bytesWritten) } err = bufferedWriter.Flush() if err != nil { return err } file.Close() return nil }
偏移量写入 某些场景我们想根据给定的偏移量写入数据,可以使用os中的writeAt方法,例子如下:
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 import "os" func writeAt (filename string ) error { data := []byte { 0x41 , 0x73 , 0x20 , 0x20 , 0x67 ,} f, err := os.OpenFile(filename, os.O_WRONLY, 0666 ) if err != nil { return err } _, err = f.Write(data) if err != nil { return err } replaceSplace := []byte { 0x6F , 0x6E ,} _, err = f.WriteAt(replaceSplace, 2 ) if err != nil { return err } f.Close() return nil }
缓存区写入 os库中的方法对文件都是直接的IO操作,频繁的IO操作会增加CPU的中断频率,所以我们可以使用内存缓存区来减少IO操作,在写字节到硬盘前使用内存缓存,当内存缓存区的容量到达一定数值时在写内存数据buffer到硬盘,bufio就是这样示一个库,来个例子我们看一下怎么使用:
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 import ( "bufio" "log" "os" ) func writeBuffer (filename string ) error { file, err := os.OpenFile(filename, os.O_WRONLY, 0666 ) if err != nil { return err } bufferedWriter := bufio.NewWriter(file) bytesWritten, err := bufferedWriter.WriteString( "asong真帅\n" , ) if err != nil { return err } log.Printf("Bytes written: %d\n" , bytesWritten) unflushedBufferSize := bufferedWriter.Buffered() log.Printf("Bytes buffered: %d\n" , unflushedBufferSize) bytesAvailable := bufferedWriter.Available() if err != nil { return err } log.Printf("Available buffer: %d\n" , bytesAvailable) err = bufferedWriter.Flush() if err != nil { return err } file.Close() return nil }
读文件 读取全文件 有两种方式我们可以读取全文件:
os、io/ioutil中提供了readFile方法可以快速读取全文
io/ioutil中提供了ReadAll方法在打开文件句柄后可以读取全文;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 import ( "io/ioutil" "log" "os" ) func readAll (filename string ) error { data, err := os.ReadFile(filename) if err != nil { return err } log.Printf("read %s content is %s" , filename, data) return nil } func ReadAll2 (filename string ) error { file, err := os.Open("asong.txt" ) if err != nil { return err } content, err := ioutil.ReadAll(file) log.Printf("read %s content is %s\n" , filename, content) file.Close() return nil }
逐行读取 os库中提供了Read方法是按照字节长度读取,如果我们想要按行读取文件需要配合bufio一起使用,bufio中提供了三种方法ReadLine、ReadBytes(“\n”)、ReadString(“\n”)可以按行读取数据,下面我使用ReadBytes(“\n”)来写个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 func readLine (filename string ) error { file, err := os.OpenFile(filename, os.O_RDONLY, 0666 ) if err != nil { return err } bufferedReader := bufio.NewReader(file) for { lineBytes, err := bufferedReader.ReadBytes('\n' ) bufferedReader.ReadLine() line := strings.TrimSpace(string (lineBytes)) if err != nil && err != io.EOF { return err } if err == io.EOF { break } log.Printf("readline %s every line data is %s\n" , filename, line) } file.Close() return nil }
按块读取文件 有些场景我们想按照字节长度读取文件,这时我们可以如下方法:
os库的Read方法
os库配合bufio.NewReader调用Read方法
os库配合io库的ReadFull、ReadAtLeast方法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 func readByte (filename string ) error { file, err := os.OpenFile(filename, os.O_RDONLY, 0666 ) if err != nil { return err } r := bufio.NewReader(file) buf := make ([]byte , 2 ) for { n, err := r.Read(buf) if err != nil && err != io.EOF { return err } if n == 0 { break } log.Printf("writeByte %s every read 2 byte is %s\n" , filename, string (buf[:n])) } file.Close() return nil } func readByte2 (filename string ) error { file, err := os.OpenFile(filename, os.O_RDONLY, 0666 ) if err != nil { return err } buf := make ([]byte , 2 ) for { n, err := file.Read(buf) if err != nil && err != io.EOF { return err } if n == 0 { break } log.Printf("writeByte %s every read 2 byte is %s\n" , filename, string (buf[:n])) } file.Close() return nil } func readByte3 (filename string ) error { file, err := os.OpenFile(filename, os.O_RDONLY, 0666 ) if err != nil { return err } buf := make ([]byte , 2 ) for { n, err := io.ReadAtLeast(file, buf, 0 ) if err != nil && err != io.EOF { return err } if n == 0 { break } log.Printf("writeByte %s every read 2 byte is %s\n" , filename, string (buf[:n])) } file.Close() return nil }
分隔符读取 bufio包中提供了Scanner扫描器模块,它的主要作用是把数据流分割成一个个标记并除去它们之间的空格,他支持我们定制Split函数做为分隔函数,分隔符可以不是一个简单的字节或者字符,我们可以自定义分隔函数,在分隔函数实现分隔规则以及指针移动多少,返回什么数据,如果没有定制Split函数,那么就会使用默认ScanLines作为分隔函数,也就是使用换行作为分隔符,bufio中还提供了默认方法ScanRunes、ScanWrods,下面我们用SacnWrods方法写个例子,获取用空格分隔的文本:
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 func readScanner (filename string ) error { file, err := os.OpenFile(filename, os.O_RDONLY, 0666 ) if err != nil { return err } scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanWords) for { success := scanner.Scan() if success == false { err = scanner.Err() if err == nil { log.Println("Scan completed and reached EOF" ) break } else { return err } } log.Printf("readScanner get data is %s" , scanner.Text()) } file.Close() return nil }
打包/解包 Go语言的archive包中提供了tar、zip两种打包/解包方法,这里以zip的打包/解包为例子: zip解包示例:
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 import ( "archive/zip" "fmt" "io" "log" "os" ) func main () { r, err := zip.OpenReader("asong.zip" ) if err != nil { log.Fatal(err) } defer r.Close() for _, f := range r.File { fmt.Printf("Contents of %s:\n" , f.Name) rc, err := f.Open() if err != nil { log.Fatal(err) } _, err = io.CopyN(os.Stdout, rc, 68 ) if err != nil { log.Fatal(err) } rc.Close() } }