1. 输入输出的底层原理
终端其实是一个文件(linux下一切皆文件),相关实例如下:
- os.stdin:标准输出的文件实例,类型为*file
- os.stdout:标准输入的文件实例,类型为*file
- os.stderr:标准错误输出的文件实例,类型为*file
以文件方式操作终端:
package main import ( "os" ) func main() { var buf []byte os.stdin.read(buf[:]) //从标准输入中读取 os.stdin.writestring(string(buf)) //写入标准输入 }
2. 文件操作相关api
根据提供的文件名创建新的文件,返回一个文件对象,默认权限0666,任何人可读可写,不可执行,如果文件存在,则会截断它(为空文件),如果成功,返回的文件对象可用于i/o;对应的文件描述符具有o_rdwr模式。如果出错,错误底层类型是*patherror。
func create(name string) (file *file, err error)
newfile使用给出的unix文件描述符和名称创建一个文件。
func newfile(fd uintptr, name string) *file
只读方式打开一个名称为name文件。
func open(name string) (file *file, err error)
打开一个名为name的文件,flag是打开方式,只读或只写,不存在创建等,perm文件权限。
func openfile(name string, flag int, perm filemode) (file *file, err error)
在指定位置(相对于文件起始位置),写入byte类型的数据到文件,它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。
func (f *file) writeat(b []byte, off int64) (n int, err error)
向文件中写入string类型的信息到文件。
func (f *file) writestring(s string) (ret int, err error)
从f中读取最多len(b)字节数的数据到b。
func (f *file) read(b []byte) (n int, err error)
从f的指定位置(相对于文件起始位置),读取len(b)字节数并写入b。
func (f *file) readat(b []byte, off int64) (n int, err error)
删除name指定的文件或目录。
func remove(name string) error
3. 打开和关闭文件
os.open()函数能够打开一个文件,返回一个*file和一个err。对得到的文件实例调用close()方法能够关闭文件。
package main import ( "log" "os" ) func main() { //只读的方式打开文件 f, err := os.open("./main.go") if err != nil { log.println("open main.go file fail") return } //关闭文件 defer f.close() }
4. 写文件
package main import ( "log" "os" ) func main() { //可读可写的方式创建一个文件 f, err := os.create("./xx.txt") if err != nil { log.println("create file fail") return } defer f.close() for i := 0; i < 5; i++ { f.write([]byte("ab\n")) f.writestring("ab\n") } }
5. 读文件
文件读取可以用file.read()和file.readat(),读到文件末尾会返回io.eof的错误。
package main import ( "fmt" "io" "log" "os" ) func main() { f, err := os.open("./xx.txt") if err != nil { log.println("open file fail") return } defer f.close() var content []byte for { var buf [128]byte n, err := f.read(buf[:]) if err == io.eof { //读到文件末尾 break } if err != nil { log.println("read file fail", err) return } content = append(content, buf[:n]...) //buf[:n]切片被打散传入 } fmt.println(string(content)) }
“…”的用法:三个点“...”其实是go的一种语法糖(糖衣语法)
- 第一个用法主要是用于函数有多个不定参数的情况,表示为可变参数,可以接受任意个数但相同类型的参数。
- 第二个用法是slice可以被打散进行传递。
6. 拷贝文件
package main import ( "io" "log" "os" ) func main() { f1, err := os.open("./xx.txt") if err != nil { log.println("open xx.txt file fail", err) return } defer f1.close() f2, err := os.create("./abc.txt") if err != nil { log.println("create file fail ", err) return } defer f2.close() for { var buf [128]byte n, err := f1.read(buf[:]) if err == io.eof { log.println("读取完毕") break } if err != nil { return } f2.write(buf[:n]) } }
7. bufio
- bufio包实现了带缓冲区的读写,是对文件读写的封装。
- bufio缓冲写数据。
- bufio读数据 ,bufio先把数据读/写到缓冲区,达到某一上限,会刷新到文件中,也可以强制刷新。
package main import ( "bufio" "fmt" "io" "log" "os" ) func wr() { f, err := os.openfile("./xxx.txt", os.o_create|os.o_wronly, 0664) if err != nil { log.println("open file fail ", err) return } defer f.close() //获取writer对象 writer := bufio.newwriter(f) for i := 0; i < 5; i++ { writer.writestring("hello\n") } //刷新缓冲区,强制写入 writer.flush() } func rd() { f, err := os.open("./xxx.txt") if err != nil { log.println("open file fail") return } defer f.close() //获取reader对象 reader := bufio.newreader(f) var content []byte for { line, _, err := reader.readline() if err == io.eof { log.println("读取完毕") break } if err != nil { return } content = append(content, line...) } fmt.println(string(content)) } func main() { wr() rd() }
8. ioutil工具包
- 工具包写文件
- 工具包读文件
package main import ( "fmt" "io/ioutil" "log" ) func wr() { err := ioutil.writefile("./xxxx.txt", []byte("hello world!"), 0666) if err != nil { log.println("err") return } } func rd() { data, err := ioutil.readfile("./xxxx.txt") if err != nil { log.println("err") return } fmt.println(string(data)) } func main() { wr() rd() }
9. 例子
实现cat命令
package main import ( "bufio" "flag" "fmt" "io" "log" "os" ) func cat(reader *bufio.reader) { for { buf, err := reader.readbytes('\n') //注意是字符 if err == io.eof { break } fmt.fprintf(os.stdout, "%s", string(buf)) } } func main() { flag.parse() if flag.narg() == 0 { cat(bufio.newreader(os.stdin)) } else { for i := 0; i < flag.narg(); i++ { f, err := os.open(flag.arg(i)) if err != nil { log.printf("open file %s fail, err %v\n", flag.arg(i), err) continue } cat(bufio.newreader(f)) f.close() } } }
到此这篇关于golang实现io操作的文章就介绍到这了,更多相关golang io操作内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论