golang编程之文件操作

操作文件是任何编程语言都绕不过,要掌握一门语言,知道如何操作文件是必不可少的,今天学习了下golang对文件操作的支持。
   golang对文件的支持是在os package里。我无意将本文写成官方文档的模样,我只是想讨论如何利用这些接口操作文件。
   OPEN
    熟悉文件系统的人都知道,open是整个文件系统中最复杂的接口之一。熟悉C语言的都知道,C语言中有open和creat,接口如下:

view sourceprint?

1.#include <sys/types.h>

2.#include <sys/stat.h>

3.#include <fcntl.h>

4.

5.int open(const char *pathname, int flags);

6.int open(const char *pathname, int flags, mode_t mode);

7.

8.int creat(const char *pathname, mode_t mode)

对C的open而言,如果flag里面有了O_CREAT,那么必须带上mode参数,制定创建文件时的perm,如果文件已经存在了,这个O_CREAT标志就无效了(除非O_EXCL标志被指定。 除了O_CREAT,还有很多的标志

view sourceprint?

01.O_RDONLY

02.

03.O_WRONLY

04.

05.O_RDWR

06.

07.O_DIRECT

08.

09.O_APPEND

10.

11.O_TRUNC

12.。。。。

这些标志位基本是顾名思义,对于open这种很复杂很综合的文件操作,golang中对应的是OpenFile

view sourceprint?

1.func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

我们看到了也有flag,也有FileMode.比如说我要读写打开一个文件,如果不存在就创建,如果存在,就追加写,如何写go 代码?

view sourceprint?

1.f,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR,0660)

2.if(err != nil){

3.    panic(err)

4.}

我们看到了,golang中也有这些标志(注意O_CREATE,在C语言中,是O_CREAT),我在上面代码片段中用了几个标志

view sourceprint?

01.const (

02.        O_RDONLY int = syscall.O_RDONLY // open the file read-only.

03.        O_WRONLY int = syscall.O_WRONLY // open the file write-only.

04.        O_RDWR int = syscall.O_RDWR // open the file read-write.

05.        O_APPEND int = syscall.O_APPEND // append data to the file when writing.

06.        O_CREATE int = syscall.O_CREAT // create a new file if none exists.

07.        O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist

08.        O_SYNC int = syscall.O_SYNC // open for synchronous I/O.

09.        O_TRUNC int = syscall.O_TRUNC // if possible, truncate file when opened.

10.      )

C语言中有creat,没有则创建,有则截断写,本质等于O_WRONLY | O_CREAT | O_TRUNC

view sourceprint?

1.#include <sys/types.h>

2.#include <sys/stat.h>

3.#include <fcntl.h>

4.int creat (const char *name, mode_t mode)

Ken Thompson大神曾经戏言,漏掉creat系统调用中的e字母是他设计Unix最后悔的事情,呵呵看起来老爷子接收了教训,没有犯同样的拼写错误,golang中对应的接口是Create(大神这一次没有拼写错)

view sourceprint?

1.func Create(name string) (file *File, err error)

和C的creat系统调用相比,少了mode入参,默认是0x666(before umask),同时标志不再是O_WRONLY,而是O_RDWR,仍然带创建标志位,仍然带截断标志。
   golang中的Open和C中的open就不能相比了(和C中的open PK那是OpenFile的事儿)接口如下:

view sourceprint?

1.func Open(name string) (file *File, err error)

直白说,就是带O_RDONLY的open,太菜了。

CLOSE
   这个接口无甚好说。接口如下

view sourceprint?

1.func (f *File) Close() error

但说接口没啥说的,但是golang提供了defer,这是一个我认为很赞的特点,就是将不得不做的cleanup放到defer去做。
   我们写C的人,经常遇到了这种代码

view sourceprint?

01.fd = open(...)

02.if(fd < 0 )

03.{

04.    ...

05.}

06.

07.if (failed_1)

08.{

09.   ...

10.   close(fd);

11.   ....

12.}

13.

14.if(faile_2)

15.{

16.    ...

17.    close(fd);

18.    ...

19.}

20.....

只要打开了文件,每次异常处理都要想着close,否则句柄泄漏,太烦。所以C语言是一门你要小心伺候的语言。
   go提供了defer解决这种困境,后面不用时刻惦记close,函数退出前,会执行close。

view sourceprint?

1.f,err := os.OpenFile("test.txt",os.O_CREATE|os.O_APPEND|os.O_RDWR,0660)

2.if(err != nil){

3.    panic("open file failed")

4.}

5.defer f.Close()

6....

READ和WRITE
   read和write是比较重要的文件操作了,这是C的接口。

view sourceprint?

1.#include <unistd.h>

2.

3.ssize_t write(int fd, const void *buf, size_t count);

4.ssize_t read(int fd, void *buf, size_t count)

对于golang,接口如下:

view sourceprint?

1.func (f *File) Read(b []byte) (n int, err error)

2.func (f *File) ReadAt(b []byte, off int64) (n int, err error)

3.

4.func (f *File) Write(b []byte) (n int, err error)

5.func (f *File) WriteAt(b []byte, off int64) (n int, err error)

6.func (f *File) WriteString(s string) (ret int, err error)

看到代码片段,学习使用读写接口:

view sourceprint?

01.read_buf := make([]byte,32)

02.var pos int64 = 0

03.for{

04.

05.    n,err := f.ReadAt(read_buf,pos)

06.    if err != nil && err != io.EOF{

07.        panic(err)

08.    }

09.    if n == 0{

10.        fmt.Printf("\nfinish read\n")

11.        break

12.    }

13.    fmt.Printf("%s",string(read_buf[:n]))

14.    pos = pos +(int64)(n)

15.}

在看一个代码片段:

view sourceprint?

01.var buff = make([]byte,1024)

02.for{

03.    n,err := fi.Read(buff)

04.    if err != nil && err != io.EOF{

05.        panic(err)

06.    }

07.    

08.    if n == 0{

09.        break

10.    }

11.

12.    if _,err := fo.Write(buff[:n]); err != nil{

13.        panic(err)

14.    }

15.

16.}

最后,我写了一个完整的代码,完成简单cp功能,就叫mycp

view sourceprint?

01.[email protected]:~/code/go/self$ cat mycp.go

02.package main

03.import "fmt"

04.import "os"

05.import "io"

06.

07.func usage(){

08.    fmt.Printf("%s %s %s\n",os.Args[0],"filename" , "newfile")

09.}

10.

11.

12.func main(){

13.    

14.    if len(os.Args) != 3{

15.        usage()

16.        return

17.    }

18.

19.    filename_in := os.Args[1]

20.    fi,err := os.Open(filename_in)

21.    if err != nil{

22.        panic(err)

23.    }

24.    defer fi.Close()

25.

26.    filename_out := os.Args[2]

27.    fo,err := os.Create(filename_out)

28.    if err != nil{

29.        panic(err)

30.    }

31.    defer fo.Close()

32.

33.

34.    var buff = make([]byte,1024)

35.    for{

36.        n,err := fi.Read(buff)

37.        if err != nil && err != io.EOF{

38.            panic(err)

39.        }

40.        

41.        if n == 0{

42.            break

43.        }

44.

45.        if _,err := fo.Write(buff[:n]); err != nil{

46.            panic(err)

47.        }

48.

49.    }

50.}

执行结果:

view sourceprint?

01.[email protected]:~/code/go/self$ ./mycp test.txt test.bak

02.[email protected]:~/code/go/self$ diff test.txt test.bak

03.[email protected]:~/code/go/self$ cat test.txt

04.this is test file created by go

05.if not existed ,please create this file

06.if existed, Please write append

07.hello world,hello go

08.this is test file created by go

09.if not existed ,please create this file

10.if existed, Please write append

11.hello world,hello go

时间: 2024-07-28 12:50:01

golang编程之文件操作的相关文章

Linux下C编程-----IO/文件操作 模拟linux ls程序显示文件系统树形结构(2)

Linux下的IO/文件操作练习,知识虽然简单 但是往往基础容易被忽略,偶尔的练习是有必要的. 练习printf /************************************************************************* > File Name: printf.c > Author: > Mail: > Created Time: Wed 11 Feb 2015 01:08:15 AM PST ***********************

PoEdu - Windows阶段班 【Po学校】Windows编程 Lesson004_003-2 文件操作

001_函数的不同版本 HANDLE : CreateFile()函数返回一个内核对象的句柄 WINAPI : 一种调用约定,调用方式. _In_ 与 _In_opt_ : 本身没有意义,一个说明宏,来标明这个参数的性质. _In_ 说明此参数是"输入型"参数 _In_Opt_ 说明此参数是"输入指针型"参数 _Out_ 说明此参数是"输出型"参数 输出参数要保障:输出型参数,具有可操作的空间 VS2015中,CreateFile()是一个宏:W

python编程:excel文件操作,redis数据库,接口开发

1.操作mysql import pymysql # 1.连上数据库 账号.密码 ip 端口号 数据库 #2.建立游标 #3.执行sql #4 .获取结果 # 5.关闭游标 #6.连接关闭 coon = pymysql.connect( host='数据库ip',user='jxz',passwd='123456', port=3306,db='jxz',charset='utf8' #port必须写int类型, #charset这里必须写utf8 ) cur = coon.cursor() #

Linux下C编程-----IO/文件操作/内存映射 实现简单记录存储(3)

利用linux下的文件内存映射可以实现进程共享数据,我们可以把一个文件映射到虚拟内存中使多个进程进行共享, 到这里我们大概能想到他能应用到的领域 是很广泛的 主要涉及到 mmap  munmap   msync 三个函数的应用 下面贴代码 下面一段代码是为文件建立一个简单的记录存储,并且通过内存映射修改文件内容 /************************************************************************* > File Name: memdb

POJ C++程序设计 编程题#2 编程作业—文件操作与模板

编程题#2: 实数的输出格式 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 1000kB 描述 利用流操纵算子实现: 输入一个实数,先以非科学计数法输出,小数点后面保留5位有效数字:再以科学计数法输出,小数点后面保留7位有效数字. 注意:在不同系统.编译器上的输出格式略有不同,但保证在程序中采用默认格式设置一定能在OJ平台上得到正确结果. 输入 以非科学计数法表示的一个正实数,保证可以用dou

POJ C++程序设计 编程题#3 编程作业—文件操作与模板

编程题#3: 整数的输出格式 来源: POJ(Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 1000kB 描述 利用流操纵算子实现: 输入一个整数,先将该整数以十六进制输出,然后再将该整数以10个字符的宽度输出,宽度不足时在左边补0. 注意:在不同系统.编译器上的输出格式略有不同,但保证在程序中采用默认格式设置一定能在OJ平台上得到正确结果. 输入 一个正整数,保证可以用int类型存储. 输出 第一行:以十六进

go语言文件操作,这期资料比较详细( 欢迎加入go语言群: 218160862 )

go语言文件操作,这期资料比较详细 欢迎加入go语言群: go语言深圳群 golang深圳 218160862 文件操作 func Open(name string) (file *File, err error),*File 是实现了 io.Reader这个接口byte[] 转化为 bytes.Buffer:bytes.NewBuffer([]byte). 一.建立与打开 建立文件函数:func Create(name string) (file *File, err Error)func N

Win8.1应用开发之文件操作

在操作文件之前,先相应用的应用功能声明进行设定.用户通过C#(非UI)对win8.1上的文件进行訪问,仅仅能局限于图片,音乐,视频和文档四个目录. 而通过文件选取器则能訪问到整个系统的文件. (一)应用功能声明 对于win8应用商店应用,打开Package.appxmanifest文件.点击"功能"选项卡,勾选"音乐库","图片库"和"视频库",这样你就能够通过代码对这里面的文件和目录进行操作: 音乐 musicLibrary

Python学习笔记八:文件操作(续),文件编码与解码,函数,递归,函数式编程介绍,高阶函数

文件操作(续) 获得文件句柄位置,f.tell(),从0开始,按字符数计数 f.read(5),读取5个字符 返回文件句柄到某位置,f.seek(0) 文件在编辑过程中改变编码,f.detech() 获取文件编码,f.encoding() 获取文件在内存中的编号,f.fileno() 获取文件终端类型(tty.打印机等),f.isatty() 获取文件名,f.name() 判断文件句柄是否可移动(tty等不可移动),f.seekable() 判断文件是否可读,f.readable() 判断文件是