Golang 学习笔记(08)—— 文件操作

本文为转载,原文:Golang 学习笔记(08)—— 文件操作

Golang

path

在path包中封装了一些路径相关的操作,在开始接触文件操作之前,我们先看看路径的相关函数。在Linux中,路径的格式为/user/bin路径中分隔符是/;Windows中的路径格式为c:\Windows路径中的分隔符是\。而在go中只认/。所以在windows中,需要把path中的\替换为/。

func Base

func Base(path string) string

Base函数返回路径的最后一个元素。在提取元素前会求掉末尾的斜杠。 如果路径是"",会返回"."; 如果路径是只有一个斜杆构成,会返回"/"

func Clean

func Clean(path string) string

Clean函数通过单纯的词法操作返回和path代表同一地址的最短路径。

它会不断的依次应用如下的规则,直到不能再进行任何处理:

  1. 将连续的多个斜杠替换为单个斜杠
  2. 剔除每一个.路径名元素(代表当前目录)
  3. 剔除每一个路径内的..路径名元素(代表父目录)和它前面的非..路径名元素
  4. 剔除开始一个根路径的..路径名元素,即将路径开始处的"/.."替换为"/"

只有路径代表根地址"/"时才会以斜杠结尾。如果处理的结果是空字符串,Clean会返回"."。

func Dir

func Dir(path string) stringDir

返回路径除去最后一个路径元素的部分,即该路径最后一个元素所在的目录。在使用Split去掉最后一个元素后,会简化路径并去掉末尾的斜杠。如果路径是空字符串,会返回".";如果路径由1到多个斜杠后跟0到多个非斜杠字符组成,会返回"/";其他任何情况下都不会返回以斜杠结尾的路径。

func Ext

func Ext(path string) string

Ext函数返回path文件扩展名。返回值是路径最后一个斜杠分隔出的路径元素的最后一个'.'起始的后缀(包括'.')。如果该元素没有'.'会返回空字符串。

func IsAbs

func IsAbs(path string) bool

IsAbs返回路径是否是一个绝对路径。

func Split

func Split(path string) (dir, file string)

Split函数将路径从最后一个斜杠后面位置分隔为两个部分(dir和file)并返回。如果路径中没有斜杠,函数返回值dir会设为空字符串,file会设为path。两个返回值满足path == dir+file。

func Join

func Join(elem ...string) string

Join函数可以将任意数量的路径元素放入一个单一路径里,会根据需要添加斜杠。结果是经过简化的,所有的空字符串元素会被忽略。

示例

package main

import (
    "path"
    "fmt"
)

func main(){
    fmt.Println("path.Base: ",path.Base("C:/Users/zzc/go/src/channelDemo"))
    fmt.Println("path.Clean: ",path.Clean("C:/Users/zzc/./go///src/../../channelDemo/"))
    fmt.Println("path.Ext: ",path.Ext("C:/Users/zzc/go/src/channelDemo/main.go"))
    fmt.Println("path.Dir: ",path.Dir("C:/Users/zzc/go/src/channelDemo/main.go"))
    fmt.Println("path.IsAbs: ",path.IsAbs("C:/Users/zzc/go/src/channelDemo/main.go"))
    dir, file := path.Split("C:/Users/zzc/go/src/channelDemo/main.go")
    fmt.Println("path.Split: ",dir, file)
    fmt.Println("path.Join: ",path.Join("c:/Users", "zzc", "go", "src"))
}
运行结果

文件读写

在os包中提供了一下文件操作的函数。

创建文件

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

Create采用模式0666(任何人都可读写,不可执行)创建一个名为name的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。如果出错,错误底层类型是*PathError。
例如:

file, err := os.Create("d:/my.txt")

打开文件

open

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

Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有O_RDONLY模式。如果出错,错误底层类型是*PathError。

OpenFile

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

OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError
name : 要打开或要创建的文件名
flag : 是打开文件的方式,可以取以下值:

  1. O_RDONLY:以只读的方式打开
  2. O_WRONLY:以只写的方式打开
  3. O_RDWR:以读写的方式打开
  4. O_APPEND:以追加方式打开文件,写入的数据将追加到文件尾
  5. O_CREATE:当文件不存在时创建文件
  6. O_EXCL:与O_CREATE一起使用,当文件存在时Open失败
  7. O_SYNC:以同步方式打开文件。每次write系统调用后等等待实际的物理I/O完成后才返回,默认(不使用该标记)是使用缓冲的,也就是说每次的写操作是写到系统内核缓冲区中,等系统缓冲区满后才写到实际存储设备中。
  8. O_TRUNC:如果文件已存在,打开是会清空文件内容。必须于O_WRONLY或O_RDWR配合使用。截断文件,需要有写的权限。

FileMode: 是文件的权限,只有在文件不存在,新建文件时该参数才有效。用来指定新建的文件的权限。必须跟O_CREATE配合使用。

写文件

Write

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

Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。

WriteString

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

WriteString类似Write,但接受一个字符串参数。

WriteAt

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

WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。

读文件

Read

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

Read方法从f中读取最多len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。文件终止标志是读取0个字节且返回值err为io.EOF。

ReadAt

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

ReadAt从指定的位置(相对于文件开始位置)读取len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。当n<len(b)时,本方法总是会返回错误;如果是因为到达文件结尾,返回值err会是io.EOF。

其他

Close

func (f *File) Close() error

Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。

Seek

func (f *File) Seek(offset int64, whence int) (ret int64, err error)

Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。
whence在系统中定义的有常量:
SEEK_SET:0
SEEK_CUR:1
SEEK_END:2

例子

package main

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

func main(){
    testio()
}

func testio(){
    //若文件不存在则创建文件,以append方式打开
    file, err := os.OpenFile("d:/test.txt", os.O_CREATE|os.O_APPEND, 0666)
    if err != nil{
        fmt.Println(err)
        return
    }
    defer file.Close() //关闭文件
    file.WriteString("i am chain ") //写入文件
    buf := make([]byte, 1024)
    var str string
    file.Seek(0, os.SEEK_SET) //重置文件指针
    //读取文件
  for {
        n, ferr := file.Read(buf)
        if ferr != nil && ferr != io.EOF{
            fmt.Println(ferr.Error())
            break
        }
        if n == 0{
            break
        }
        str += string(buf[0:n])
    }
    fmt.Println("file content: ", str)
}

执行两次之后的结果如下图


运行结果

ioutil

在ioutil中封装了一些函数,让IO操作更简单方便

ReadAll

func ReadAll(r io.Reader) ([]byte, error)

ReadAll从r读取数据直到EOF或遇到error,返回读取的数据和遇到的错误。成功的调用返回的err为nil而非EOF。因为本函数定义为读取r直到EOF,它不会将读取返回的EOF视为应报告的错误。

ReadFile

func ReadFile(filename string) ([]byte, error)

ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件,它不会将读取返回的EOF视为应报告的错误。

WriteFile

func WriteFile(filename string, data []byte, perm os.FileMode)

error函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。

例子

package main

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

func main(){
    testioutil()
}

func testioutil(){
    str := "i am chain, i am a good boy. "
    //写入数据
    err := ioutil.WriteFile("d:/a.txt",[]byte(str), 0666)
    if err != nil{
        fmt.Println(err.Error())
    }else{
        fmt.Println("write success!")
    }
  //通过readfile函数读取数据
    buf1, err1 := ioutil.ReadFile("d:/a.txt")
    if err1 != nil{
        fmt.Println(err1.Error())
    }else{
        fmt.Println("Read File: ", string(buf1))
    }
  //通过readall读取数据
    f, err2 := os.OpenFile("d:/a.txt", os.O_RDONLY, 0666)
    if err2 != nil{
        fmt.Println(err2.Error())
        return
    }
    defer f.Close()
    buf2, err3 := ioutil.ReadAll(f)
    if err3 != nil{
        fmt.Println(err3.Error())
    }else{
        fmt.Println("read all: ", string(buf2))
    }
}
运行结果

目录操作

os/Readdir

func (f *File) Readdir(n int) (fi []FileInfo, err error)

Readdir读取目录f的内容,返回一个有n个成员的[]FileInfo,这些FileInfo是被Lstat返回的,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。

如果n>0,Readdir函数会返回一个最多n个成员的切片。这时,如果Readdir返回一个空切片,它会返回一个非nil的错误说明原因。如果到达了目录f的结尾,返回值err会是io.EOF。

如果n<=0,Readdir函数返回目录中剩余所有文件对象的FileInfo构成的切片。此时,如果Readdir调用成功(读取所有内容直到结尾),它会返回该切片和nil的错误值。如果在到达结尾前遇到错误,会返回之前成功读取的FileInfo构成的切片和该错误。

package main

import (
    "fmt"
    "os"
)

func main(){
    f, err := os.OpenFile("D:/code/", os.O_RDONLY, 0666)
    if err != nil{
        fmt.Println(err.Error())
        return
    }
    arrFiles, err1:=f.Readdir(0)
    if err1 != nil{
        fmt.Println(err1.Error())
        return
    }
    for k, v := range arrFiles{
        fmt.Println(k, "\t", v, "\t", v.IsDir())
    }
}
运行结果

ioutil/ReadDir

func ReadDir(dirname string) ([]os.FileInfo, error)

返回dirname指定的目录的目录信息的有序列表。

package main

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

func main(){
    arrFiles, err1 := ioutil.ReadDir("D:/code/")
    if err1 != nil{
        fmt.Println(err1.Error())
        return
    }
    for k, v := range arrFiles{
        fmt.Println(k, "\t", v, "\t", v.IsDir())
    }
}
运行结果

gob序列化

序列化就是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。之后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

gob是go中特有的序列化技术,它支持除interface,function,channel外的所有go数据类型。序列化用Encoder,反序列化用Decoder。

package main

import (
    "encoding/gob"
    "os"
    "fmt"
)

type Student struct{
    Name string
    Age int
}

func main(){
    stu := &Student{"chain", 23}
    f, err := os.Create("d:/stu.txt")
    if err != nil{
        fmt.Println(err.Error())
        return
    }
    defer f.Close()
    //创建Encoder对象
    encode := gob.NewEncoder(f)
    //将stu序列化到f中
    encode.Encode(stu)
    //重置文件指针
    f.Seek(0, os.SEEK_SET)
    //创建decoder对象
    decoder := gob.NewDecoder(f)
    var s1 Student
    //反序列化对象
    decoder.Decode(&s1)
    fmt.Println(s1)
}
gob序列化示例

转载请注明出处
Golang 学习笔记(08)—— 文件操作

目录
上一节:Golang 学习笔记(07)—— 错误及异常处理
下一节:Golang 学习笔记(09)—— json和xml解析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • PHP常用函数大全 usleep() 函数延迟代码执行若干微秒。 unpack() 函数从二进制字符串对数据进行解...
    上街买菜丶迷倒老太阅读 1,350评论 0 20
  • php usleep() 函数延迟代码执行若干微秒。 unpack() 函数从二进制字符串对数据进行解包。 uni...
    思梦PHP阅读 1,980评论 1 24
  • https://nodejs.org/api/documentation.html 工具模块 Assert 测试 ...
    KeKeMars阅读 6,297评论 0 6
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139
  • 文件操作 (Linux文件操作)) [文件|目录] Linux文件操作:为了对文件和目录进程处理,你需要用到系统...
    JamesPeng阅读 1,453评论 1 5