golang对文件的支持是在os package里。我无意将本文写成官方文档的模样,我只是想讨论如何利用这些接口操作文件。
OPEN
熟悉文件系统的人都知道,open是整个文件系统中最复杂的接口之一。熟悉C语言的都知道,C语言中有open和creat,接口如下:
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int open(const char *pathname, int flags);
- int open(const char *pathname, int flags, mode_t mode);
- int creat(const char *pathname, mode_t mode)
O_RDONLY
O_WRONLY
O_RDWR
O_DIRECT
O_APPEND
O_TRUNC
。。。。
- func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
- f,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR,0660)
- if(err != nil){
- panic(err)
- }
- const (
- O_RDONLY int = syscall.O_RDONLY // open the file read-only.
- O_WRONLY int = syscall.O_WRONLY // open the file write-only.
- O_RDWR int = syscall.O_RDWR // open the file read-write.
- O_APPEND int = syscall.O_APPEND // append data to the file when writing.
- O_CREATE int = syscall.O_CREAT // create a new file if none exists.
- O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist
- O_SYNC int = syscall.O_SYNC // open for synchronous I/O.
- O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.
- )
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- int creat (const char *name, mode_t mode)
- func Create(name string) (file *File, err error)
golang中的Open和C中的open就不能相比了(和C中的open PK那是OpenFile的事儿)接口如下:
- func Open(name string) (file *File, err error)
CLOSE
这个接口无甚好说。接口如下
- func (f *File) Close() error
我们写C的人,经常遇到了这种代码
- fd = open(...)
- if(fd < 0 )
- {
- ...
- }
- if (failed_1)
- {
- ...
- close(fd);
- ....
- }
- if(faile_2)
- {
- ...
- close(fd);
- ...
- }
- ....
go提供了defer解决这种困境,后面不用时刻惦记close,函数退出前,会执行close。
- f,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR,0660)
- if(err != nil){
- panic("open file failed")
- }
- defer f.Close()
- ...
read和write是比较重要的文件操作了,这是C的接口。
- #include <unistd.h>
- ssize_t write(int fd, const void *buf, size_t count);
- ssize_t read(int fd, void *buf, size_t count)
- func (f *File) Read(b []byte) (n int, err error)
- func (f *File) ReadAt(b []byte, off int64) (n int, err error)
- func (f *File) Write(b []byte) (n int, err error)
- func (f *File) WriteAt(b []byte, off int64) (n int, err error)
- func (f *File) WriteString(s string) (ret int, err error)
- read_buf := make([]byte,32)
- var pos int64 = 0
- for{
- n,err := f.ReadAt(read_buf,pos)
- if err != nil && err != io.EOF{
- panic(err)
- }
- if n == 0{
- fmt.Printf("\nfinish read\n")
- break
- }
- fmt.Printf("%s",string(read_buf[:n]))
- pos = pos +(int64)(n)
- }
- var buff = make([]byte,1024)
- for{
- n,err := fi.Read(buff)
- if err != nil && err != io.EOF{
- panic(err)
- }
-
- if n == 0{
- break
- }
- if _,err := fo.Write(buff[:n]); err != nil{
- panic(err)
- }
- }
- manu@manu-hacks:~/code/go/self$ cat mycp.go
- package main
- import "fmt"
- import "os"
- import "io"
- func usage(){
- fmt.Printf("%s %s %s\n",os.Args[0],"filename" , "newfile")
- }
- func main(){
-
- if len(os.Args) != 3{
- usage()
- return
- }
- filename_in := os.Args[1]
- fi,err := os.Open(filename_in)
- if err != nil{
- panic(err)
- }
- defer fi.Close()
- filename_out := os.Args[2]
- fo,err := os.Create(filename_out)
- if err != nil{
- panic(err)
- }
- defer fo.Close()
- var buff = make([]byte,1024)
- for{
- n,err := fi.Read(buff)
- if err != nil && err != io.EOF{
- panic(err)
- }
-
- if n == 0{
- break
- }
- if _,err := fo.Write(buff[:n]); err != nil{
- panic(err)
- }
- }
- }
- manu@manu-hacks:~/code/go/self$ ./mycp test.txt test.bak
- manu@manu-hacks:~/code/go/self$ diff test.txt test.bak
- manu@manu-hacks:~/code/go/self$ cat test.txt
- this is test file created by go
- if not existed ,please create this file
- if existed, Please write append
- hello world,hello go
- this is test file created by go
- if not existed ,please create this file
- if existed, Please write append
- hello world,hello go
参考文献
1 Linux system program
2 golang os package
3 StackOverflow How to read/write from/to file?