go标准库的学习-os

参考https://studygolang.com/pkgdoc

导入方式:

import "os"

os包提供了操作系统函数的不依赖平台的接口

一开始简单举个例子:

package main 
import(
    "fmt"
    "os"
    "log"
)
func main() {
    file, err := os.Open("test.txt")
    if err != nil{
        log.Fatal(err)
    }
    data := make([]byte, 100)
    count, err := file.Read(data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("read %d bytes: %q\n", count, data[:count])
}

因为没有file.txt这个文件,所以会返回:

userdeMBP:go-learning user$ go run test.go
2019/01/22 11:03:11 open test.txt: no such file or directory
exit status 1

在当前目录生成一个test.txt文件:

hello
what do you want
no thanks

然后再运行返回:

userdeMBP:go-learning user$ go run test.go
read 32 bytes: "hello\nwhat do you want\nno thanks"

 

1.const常量

1)

const (
    O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件
    O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件
    O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件
    O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部
    O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件
    O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在
    O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/O
    O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件
)

作为参数flag传输,用于包装底层系统的参数,说明使用什么模式打开文件

Open()函数默认使用的是flag == O_RDONLY,即只读模式,相当于OpenFile(name,O_RDONLY,0)

但是不是所有flag都能在特定系统中使用的

 

1》func Open

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

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

 

2》func OpenFile

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

OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。它会使用指定的选项(如O_RDONLY等)、指定的模式FileMode(如0666,即可读写,但是不可执行)打开指定名称的文件。如果操作成功,返回的文件对象可用于I/O。如果出错,错误底层类型是*PathError。

参数flag可以结合使用:

os.O_WRONLY | os.O_CREATE | O_EXCL     //如果已经存在,则失败
os.O_WRONLY | os.O_CREATE              //如果已经存在,会覆盖写,不会清空原来的文件,而是从头直接覆盖写
os.O_WRONLY | os.O_CREATE | os.O_APPEND //如果已经存在,则在尾部添加写

参数perm:

linux中的权限rwx分别对应4 2 1,相加的值为7。如0666,即可读写,但是不可执行

下面的例子设置为不可写,然后进行写操作时会出错:

package main 
import(
    "fmt"
    "os"
    "log"
)
func main() {
    file, err := os.OpenFile("test.txt", os.O_RDONLY, 0555) //只可读、执行,不可写
    if err != nil{
        log.Fatal(err)
    }
    defer file.Close()

    data1 := []byte("add something to test.txt")
    number, err := file.Write(data1)
    if err != nil{
        log.Fatal(err)
    }
    fmt.Printf("successfully add %d bytes: %q\n", number, data1[:number])

    data := make([]byte, 100)
    count, err := file.Read(data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("read %d bytes: %q\n", count, data[:count])

}

出错:

userdeMBP:go-learning user$ go run test.go
2019/01/22 11:49:38 write test.txt: bad file descriptor
exit status 1

改权限:

file, err := os.OpenFile("test.txt", os.O_RDWR | os.O_APPEND, 0666) //可读写,且写的内容添加在末尾

返回:

userdeMBP:go-learning user$ go run test.go
successfully add 25 bytes: "add something to test.txt"
2019/01/22 11:52:37 EOF
exit status 1

返回EOF(end-of-file)的原因是上面的Write()运行完后指针指在文件终端,这个时候读取就读取不到数据

所以写完后想读应该重新调用一个Open():

package main 
import(
    "fmt"
    "os"
    "log"
)
func main() {
    file, err := os.OpenFile("test.txt", os.O_RDWR | os.O_APPEND, 0666) //可读写,且写的内容添加在末尾
    if err != nil{
        log.Fatal(err)
    }
    defer file.Close()

    data1 := []byte("add something to test.txt")
    number, err := file.Write(data1)
    if err != nil{
        log.Fatal(err)
    }
    fmt.Printf("successfully add %d bytes: %q\n", number, data1[:number])

    file1, err := os.Open("test.txt") //只读
    data := make([]byte, 100)
    count, err := file1.Read(data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("read %d bytes: %q\n", count, data[:count])
    defer file1.Close()

}

返回:

userdeMBP:go-learning user$ go run test.go
successfully add 25 bytes: "add something to test.txt"
read 57 bytes: "hello\nwhat do you want\nno thanksadd something to test.txt"

 

3》func Create

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

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

package main 
import(
    "fmt"
    "os"
    "log"
)
func main() {
    file, err := os.Create("testCreate.txt") //可读写,且写的内容添加在末尾
    if err != nil{
        log.Fatal(err)
    }
    defer file.Close()

    data1 := []byte("write something to testCreate.txt")
    number, err := file.Write(data1)
    if err != nil{
        log.Fatal(err)
    }
    fmt.Printf("successfully write %d bytes: %q\n", number, data1[:number])

}

返回:

userdeMBP:go-learning user$ ls
hello.go    test.go        test.txt
userdeMBP:go-learning user$ go run test.go
successfully write 33 bytes: "write something to testCreate.txt"
userdeMBP:go-learning user$ ls
hello.go    test.go        test.txt    testCreate.txt

可见生成了一个testCreate.txt文件,并将相应的内容写入

 

2)

const (
    SEEK_SET int = 0 // 相对于文件起始位置seek
    SEEK_CUR int = 1 // 相对于文件当前位置seek
    SEEK_END int = 2 // 相对于文件结尾位置seek
)

用于Seek(offset int64, whence int)函数,指定从何处开始搜索(即相对位置whence)

func (*File) Seek

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

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

举例说明:

package main 
import(
    "fmt"
    "os"
    "log"
)
func main() {
    file, err := os.Open("test.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    set_offset, _ := file.Seek(5, os.SEEK_SET)//从文件的起始位置偏移5
    fmt.Println(set_offset)

    data := make([]byte, 10)
    count, err := file.Read(data)
    if err != nil{
        log.Fatal(err)
    }
    fmt.Printf("Read %d bytes: %q\n", count, data[:count])

    cur_offset, _ := file.Seek(0, os.SEEK_CUR) //获得文件指针当前位置
    fmt.Println(cur_offset)
}

返回:

userdeMBP:go-learning user$ go run test.go
5
Read 10 bytes: "\nwhat do y"
15

 

3)

const (
    PathSeparator     = '/' // 操作系统指定的路径分隔符
    PathListSeparator = ':' // 操作系统指定的表分隔符
)

举例:

const DevNull = "/dev/null"

DevNull是操作系统空设备的名字。在类似Unix的操作系统中,是"/dev/null";在Windows中,为"NUL"。

package main 
import(
    "fmt"
    "os"
)
func main() {
    fmt.Println(os.PathSeparator)            //47
    fmt.Printf("%q\n", os.PathSeparator)     //'/'
    fmt.Println(os.PathListSeparator)        //58
    fmt.Printf("%q\n", os.PathListSeparator) //':'
}

 

2.var变量

1)

var (
    ErrInvalid    = errors.New("invalid argument")
    ErrPermission = errors.New("permission denied")
    ErrExist      = errors.New("file already exists")
    ErrNotExist   = errors.New("file does not exist")
)

一些可移植的、共有的系统调用错误。

package main 
import(
    "fmt"
    "os"
)
func main() {
    fmt.Println(os.ErrInvalid)      //invalid argument
    fmt.Println(os.ErrPermission)   //permission denied
    fmt.Println(os.ErrExist)        //file already exists
    fmt.Println(os.ErrNotExist)     //file does not exist
}

 

2)

var (
    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

syscall的额外知识:

var (
    Stdin  = 0
    Stdout = 1
    Stderr = 2
)

Stdin、Stdout和Stderr是指向标准输入、标准输出、标准错误输出的文件描述符。

package main 
import(
    "fmt"
    "os"
)
func main() {
    fmt.Println(os.Stdin)      //&{0xc42008c000}
    fmt.Println(os.Stdout)     //&{0xc42008c050}
    fmt.Println(os.Stderr)     //&{0xc42008c0a0}
}

其中os.Stdout 和 os.Stderr实现了io.Writer,所以其可以使用Write();os.Stdin 实现了io.Reader,所以可以使用Read()

1》uintptr

uintptr是一种无符号的整数类型,没有指定具体的bit大小但是足以容纳指针,是能存储指针的整形。

uintptr类型只有在底层编程时才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方

 

2》func NewFile

func NewFile(fd uintptr, name string) *File

NewFile使用给出的Unix文件描述符和名称创建一个文件

这个函数并不是真正创建了一个文件,是新建一个文件,但是不保存,然后返回文件的指针

参数fd其实可以通过os.Fd()函数得到

 

3》func (*File) Fd

func (f *File) Fd() uintptr

Fd返回与文件f对应的整数类型的Unix文件描述符

Fd()举例:

package main 
import(
    "fmt"
    "os"
    "log"
    "syscall"
)
func main() {
    file, err := os.Open("test.txt")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    fmt.Printf("%q\n", file.Fd()) //'\x03'
    fmt.Printf("%q\n", uintptr(syscall.Stdin)) //'\x00'
    fmt.Printf("%q\n", uintptr(syscall.Stdout)) //'\x01'
    fmt.Printf("%q\n", uintptr(syscall.Stderr)) //'\x02'
}

Fd()和NewFile():

package main 
import(
    "fmt"
    "os"
    "syscall"
    "log"
)
func main() {
    file := os.NewFile(uintptr(syscall.Stdin), "testNewFile.txt")
    fmt.Printf("%q\n", file.Fd())
    fmt.Printf("%q\n", file.Name())
    fileInfo, err := file.Stat()
    if err != nil{
        log.Fatal(err)
    }
    fmt.Printf("%q\n", fileInfo)
}

返回:

userdeMBP:go-learning user$ go run test.go
'\x00'
"testNewFile.txt"
&{"testNewFile.txt" '\x00' %!q(os.FileMode=69206416) {%!q(uint64=199080000) %!q(int64=63683738309) %!q(*time.Location=&{ [] [] 0 0 <nil>})} {%!q(int32=862660272) '' '\x01' 'ʍ' 'ǵ' '\x04' %!q(int32=268435456) "\x00\x00\x00\x00" {%!q(int64=1548141508) %!q(int64=943988000)} {%!q(int64=1548141509) %!q(int64=199080000)} {%!q(int64=1548141509) %!q(int64=199080000)} {'\x00' '\x00'} '\x00' '\x00' '𠀀' '\x00' '\x00' '\x00' ['\x00' '\x00']}}

fileInfo对应的内容的意思:

type FileInfo

type FileInfo interface {
    Name() string       // 文件的名字(不含扩展名)
    Size() int64        // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同
    Mode() FileMode     // 文件的模式位
    ModTime() time.Time // 文件的修改时间
    IsDir() bool        // 等价于Mode().IsDir()
    Sys() interface{}   // 底层数据来源(可以返回nil)
}

FileInfo用来描述一个文件对象

 对应函数:

1> func Stat

func Stat(name string) (fi FileInfo, err error)

Stat返回一个描述name指定的文件对象的FileInfo。如果指定的文件对象是一个符号链接,返回的FileInfo描述该符号链接指向的文件的信息,本函数会尝试跳转该链接。如果出错,返回的错误值为*PathError类型。

上面的例子就是使用该函数获得的fileinfo

2> func Lstat

func Lstat(name string) (fi FileInfo, err error)

Lstat返回一个描述name指定的文件对象的FileInfo。如果指定的文件对象是一个符号链接,返回的FileInfo描述该符号链接的信息,本函数不会试图跳转该链接。如果出错,返回的错误值为*PathError类型。

和Stat()的区别在于指定的文件是符号链接时

3)

var Args []string

Args保管了命令行参数,第一个是程序名

package main 
import(
    "fmt"
    "os"
)
func main() {    
    fmt.Println(os.Args)
}

返回:

userdeMBP:go-learning user$ go run test.go testArgs
[/var/folders/2_/g5wrlg3x...3r0000gn/T/go-build...6436/b001/exe/test testArgs]

从该例子中可以看出os.Args[0]得到的是程序名,后面的内容就是运行时输入的命令行参数

 

3.函数

1)获得环境变量的函数

1》func Hostname

func Hostname() (name string, err error)

Hostname返回内核提供的主机名

2》func Getpagesize

func Getpagesize() int

Getpagesize返回底层的系统内存页的尺寸

3》func Environ

func Environ() []string

Environ返回表示环境变量的格式为"key=value"的字符串的切片拷贝。

举例:

package main 
import(
    "fmt"
    "os"
)
func main() {    
    hostName, _ := os.Hostname()
    fmt.Println(hostName)       //userdeMacBook-Pro.local
    pageSize := os.Getpagesize()
    fmt.Printf("%d\n", pageSize)//4096
    env := os.Environ()
    fmt.Println(env)
    //[NVM_RC_VERSION= TERM_PROGRAM=Apple_Terminal NVM_CD_FLAGS= TERM=xterm-256color SHELL=/bin/bash TMPDIR=/var/folders/2_/g5wrlg3x75zbzyqvsd5f093r0000gn/T/ GOBIN=/Users/user/go/bin Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.hCiYCRjE9x/Render TERM_PROGRAM_VERSION=421 TERM_SESSION_ID=35382D39-F90B-4104-90D6-0F43A69EAA8A NVM_DIR=/Users/user/.nvm USER=user SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.HV5a0Olhhd/Listeners PATH=/Library/Frameworks/Python.framework/Versions/3.7/bin:./usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home/bin:/usr/local/bin:/Users/user/go/bin:/usr/local/mysql/bin PWD=/Users/user/go-learning JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-10.0.1.jdk/Contents/Home LANG=zh_CN.UTF-8 XPC_FLAGS=0x0 XPC_SERVICE_NAME=0 HOME=/Users/user SHLVL=1 LOGNAME=user GOPATH=/Users/user/go SECURITYSESSIONID=186a8 _=/usr/local/bin/go]
}

 

4》func Getenv

func Getenv(key string) string

Getenv检索并返回名为key的环境变量的值。如果不存在该环境变量会返回空字符串。

5》func Setenv

func Setenv(key, value string) error

Setenv设置名为key的环境变量。如果出错会返回该错误

6》func Clearenv

func Clearenv()

Clearenv删除所有环境变量。

举例:

package main 
import(
    "fmt"
    "os"
)
func main() {    
    shell := os.Getenv("SHELL")
    fmt.Println(shell)       ///bin/bash
}

 

7》func Exit

func Exit(code int)

Exit让当前程序以给出的状态码code退出。一般来说,状态码0表示成功,非0表示出错。程序会立刻终止,defer的函数不会被执行。

举例:

package main 
import(
    "fmt"
    "os"
    "path/filepath"
)
func main() {    
    if len(os.Args) == 1{
        fmt.Printf("usage: %s \n", filepath.Base(os.Args[0]))
        os.Exit(1)
    }
}

返回:

userdeMBP:go-learning user$ go run test.go
usage: test 
exit status 1

 

8》func Getuid

func Getuid() int

Getuid返回调用者的用户ID

9》func Geteuid

func Geteuid() int

Geteuid返回调用者的有效用户ID

10》func Getgid

func Getgid() int

Getgid返回调用者的组ID。

11》func Getgroups

func Getgroups() ([]int, error)

Getgroups返回调用者所属的所有用户组的组ID

12》func Getpid

func Getpid() int

Getpid返回调用者所在进程的进程ID

13》func Getppid

func Getppid() int

Getppid返回调用者所在进程的父进程的进程ID。

举例:

package main 
import(
    "fmt"
    "os"
)
func main() {
    uid := os.Getuid()
    fmt.Printf("%d\n", uid)        //501
    euid := os.Geteuid()
    fmt.Printf("%d\n", euid)    //501
    gid := os.Getgid()
    fmt.Printf("%d\n", gid)        //20
    egid := os.Getegid()
    fmt.Printf("%d\n", egid)    //20
    groups, _ := os.Getgroups()
    fmt.Println(groups)            //[20 12 61 79 80 81 98 33 100 204 250 395 398 399 701]
    pid := os.Getpid()
    fmt.Printf("%d\n", pid)        //2031
    ppid := os.Getppid()
    fmt.Printf("%d\n", ppid)    //2016
}

 

2)

type FileMode

type FileMode uint32

FileMode代表文件的模式和权限位。这些字位在所有的操作系统都有相同的含义,因此文件的信息可以在不同的操作系统之间安全的移植。不是所有的位都能用于所有的系统,唯一共有的是用于表示目录的ModeDir位。

const (
    // 单字符是被String方法用于格式化的属性缩写。
    ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目录
    ModeAppend                                     // a: 只能写入,且只能写入到末尾
    ModeExclusive                                  // l: 用于执行
    ModeTemporary                                  // T: 临时文件(非备份文件)
    ModeSymlink                                    // L: 符号链接(不是快捷方式文件)
    ModeDevice                                     // D: 设备
    ModeNamedPipe                                  // p: 命名管道(FIFO)
    ModeSocket                                     // S: Unix域socket
    ModeSetuid                                     // u: 表示文件具有其创建者用户id权限
    ModeSetgid                                     // g: 表示文件具有其创建者组id的权限
    ModeCharDevice                                 // c: 字符设备,需已设置ModeDevice
    ModeSticky                                     // t: 只有root/创建者能删除/移动文件
    // 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
    ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
    ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
)

这些被定义的位是FileMode最重要的位。另外9个不重要的位为标准Unix rwxrwxrwx权限(任何人都可读、写、运行)。这些(重要)位的值应被视为公共API的一部分,可能会用于线路协议或硬盘标识:它们不能被修改,但可以添加新的位。

package main 
import(
    "fmt"
)
func main() {    
    type FileMode uint32
    const (
        // 单字符是被String方法用于格式化的属性缩写。
        ModeDir        FileMode = 1 << (32 - 1 - iota) // d: 目录
        ModeAppend                                     // a: 只能写入,且只能写入到末尾
        ModeExclusive                                  // l: 用于执行
        ModeTemporary                                  // T: 临时文件(非备份文件)
        ModeSymlink                                    // L: 符号链接(不是快捷方式文件)
        ModeDevice                                     // D: 设备
        ModeNamedPipe                                  // p: 命名管道(FIFO)
        ModeSocket                                     // S: Unix域socket
        ModeSetuid                                     // u: 表示文件具有其创建者用户id权限
        ModeSetgid                                     // g: 表示文件具有其创建者组id的权限
        ModeCharDevice                                 // c: 字符设备,需已设置ModeDevice
        ModeSticky                                     // t: 只有root/创建者能删除/移动文件
        // 覆盖所有类型位(用于通过&获取类型位),对普通文件,所有这些位都不应被设置
        ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
        ModePerm FileMode = 0777 // 覆盖所有Unix权限位(用于通过&获取类型位)
    )
    fmt.Println(ModeDir)       //2147483648
    fmt.Println(ModeAppend)    //1073741824
    fmt.Println(ModeExclusive) //536870912
    fmt.Println(ModeTemporary) //268435456
    fmt.Println(ModeSymlink)   //134217728
    fmt.Println(ModeDevice)    //67108864
    fmt.Println(ModeNamedPipe) //33554432
    fmt.Println(ModeSocket)    //16777216
    fmt.Println(ModeSetuid)    //8388608
    fmt.Println(ModeSetgid)    //4194304
    fmt.Println(ModeCharDevice)//2097152
    fmt.Println(ModeSticky)    //1048576
    fmt.Println(ModeType)      //2399141888
    fmt.Println(ModePerm)      //511
    fmt.Printf("%o\n", ModePerm)//777
}

 没弄其对应的函数。。。

 

3)func Pipe()

func Pipe() (r *File, w *File, err error)

Pipe返回一对关联的文件对象。从r的读取将返回写入w的数据。本函数会返回两个文件对象和可能的错误。

举例:

package main

import (
    "fmt"
    "log"
    "os"
)

func main() {
    reader, writer, err := os.Pipe()
    if err != nil {
        log.Fatal(err)
    }
    data := []byte("write something to approve test pipe()")
    count, err := writer.Write(data)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("write %d bytes: %q \n", count, data[:count])
    defer writer.Close()

    data1 := make([]byte,100)
    count1, err := reader.Read(data1)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("read %d bytes: %q \n", count1, data1[:count1])
    defer reader.Close()
}

返回:

userdeMBP:go-learning user$ go run test.go
write 38 bytes: "write something to approve test pipe()" 
read 38 bytes: "write something to approve test pipe()" 

 

4)type file

type File struct {
}

File代表一个打开的文件对象。

1》func (*File) Name

func (f *File) Name() string

Name方法返回(提供给Open/Create等方法的)文件名称。

2》func (*File) Stat

func (f *File) Stat() (fi FileInfo, err error)

Stat返回描述文件f的FileInfo类型值。如果出错,错误底层类型是*PathError。

3》func (*File) Fd(上面有举例说明)

举例:

package main 
import(
    "os"
    "fmt"
    "log"
)
func main() {
    testFile, err := os.Create("testOs.txt")
    if err != nil{
        log.Fatal(err)
    }
    fmt.Println(testFile.Name())
    fileInfo, err := testFile.Stat()
    if err != nil{
        log.Fatal(err)
    }
    fmt.Println(fileInfo)
}

返回:

userdeMBP:src user$ go run test.go
testOs.txt
&{testOs.txt 0 420 {792912742 63683925836 0x113ca20} {16777221 33188 1 14021387 501 20 0 [0 0 0 0] {1548329036 792912742} {1548329036 792912742} {1548329036 792912742} {1548329036 792912742} 0 0 4096 0 0 0 [0 0]}}

 

4》func (*File) Read

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

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

5》func (*File) ReadAt

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

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

6》func (*File) Write

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

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

7》func (*File) WriteString

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

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

8》func (*File) WriteAt

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

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

9》func (*File) Seek(上面有举例说明)

10》func (*File) Close

func (f *File) Close() error

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

举例说明:

package main 
import(
    "os"
    "fmt"
    "log"
    "io"
)
func main() {
    testFile, err := os.Create("testOs.txt")
    if err != nil{
        log.Fatal(err)
    }
    defer testFile.Close()
    contents := []string{
        "right now is trying to test Write\n",
        "here is the end\n",
    }
    for _, content := range contents{
        _, err = testFile.Write([]byte(content))
        if err != nil{
            log.Fatal(err)
        }
    }
    anoContents := []string{
        "here is trying to test WriteString\n",
        "and then is the end\n",
    }
    for _, anoContent := range anoContents{
        _, err = testFile.WriteString(anoContent)
        if err != nil{
            log.Fatal(err)
        }
    }
  //指定位置的写法会将之前的内容覆盖
    // insertContent := "!!!insert string  to test WriteAt!!!!\n"
    // _, err = testFile.WriteAt([]byte(insertContent), 34)
    // if err != nil{
    //     log.Fatal(err)
    // }

    readFile, err := os.Open("testOs.txt")
    if err != nil{
        log.Fatal(err)
    }
    defer readFile.Close()

    data := make([]byte, 20)
    n, err := readFile.ReadAt(data,5)//从偏移量5处开始读取,即跳过right
    if err != nil{
        log.Fatal(err)
    }
    fmt.Println(string(data[:n]))
    for{
        number, err := readFile.Read(data)
        if err != nil{
            if err == io.EOF{
                break
            }
            log.Fatal(err)
        }
     fmt.Println(number)
        fmt.Println(string(data[:number]))        
    }
}

 

运行后返回:

userdeMBP:src user$ go run test.go
 now is trying to te
20
right now is trying 
20
to test Write
here i
20
s the end
here is tr
20
ying to test WriteSt
20
ring
and then is the
5
 end

userdeMBP:src user$ 

此时testOS.txt中的内容是:

right now is trying to test Write
here is the end
here is trying to test WriteString
and then is the end

如果将上面的注释消除,使用WriteAt(),运行返回结果为:

userdeMBP:src user$ go run test.go
 now is trying to te
20
right now is trying 
20
to test Write
!!!ins
20
ert string  to test 
20
WriteAt!!!!
 WriteSt
20
ring
and then is the
5
 end

userdeMBP:src user$ 

此时testOS.txt中的内容是:

right now is trying to test Write
!!!insert string  to test WriteAt!!!!
 WriteString
and then is the end

 

11》func (*File) Sync

func (f *File) Sync() (err error)

Sync递交文件的当前内容进行稳定的存储。一般来说,这表示将文件系统的最近写入的数据在内存中的拷贝刷新到硬盘中稳定保存。

 未完待续

posted @ 2019-02-28 23:26  慢行厚积  阅读(3450)  评论(0编辑  收藏  举报