终端读写

操作终端相关文件句柄常量

  • os.Stdin(standard):标准输入
  • os.Stdout:标准输出
  • os.Stderr:标准错误输出

标准输出

demo:直接输出和 判断之后输出的结果不一致

func main(){
//标准输出接口, 格式, 需要格式化的内容
fmt.Fprintf(os.Stdout, "%s\n", "hello world ~") fmt.Fprintln(os.Stdout, "hello, world ~")
} 运行结果:
hello world ~
hello, world ~

标准输入

package main
import (
"fmt"
) var (
firstName, lastName string
age, salary int
) func main(){
//从键盘获取string类型赋值给fistName
fmt.Scanf("%s", &firstName) //将字符串赋值给lastName, 中间不能空格
fmt.Sscan("helloworld", &lastName) //将一个字符串按照指定格式赋值给变量
fmt.Sscanf("18-3000", "%d-%d", &age, &salary) fmt.Printf("%s\n%s\n%d\n%d", firstName, lastName, age, salary)
} 运行结果:
"holle go" //手动输入,有空格不行
"holle
helloworld
18
3000

  

带缓存的输出

package main
import (
"bufio"
"fmt"
"os"
) func main(){
//先得到*Write缓存
buf := bufio.NewWriter(os.Stdout) //标准输出接口, 格式, 需要格式化的内容
fmt.Fprintf(buf, "%s\n", "hello world ~") fmt.Fprintln(buf, "hello, world ~") buf.Flush()
} 运行结果:
hello world ~
hello, world ~

  

带缓存的输入

package main
import (
"bufio"
"fmt"
"os"
) func main(){
buf := bufio.NewReader(os.Stdin) input, err := buf.ReadString('\n') //delim 定界符
if err == nil {
fmt.Println(input)
}
} 运行结果:
hello world //手动输入
hello world

  

读文件

Go 中读取一个文件有多种方式,下面介绍主要的几种:

使用 ioutil 包直接读取

先需要引入 io/ioutil 包,该包默认拥有以下函数供使用者调用

func NopCloser(r io.Reader) io.ReadCloser
func ReadAll(r io.Reader) ([]byte, error)
func ReadDir(dirname string) ([]os.FileInfo, error)
func ReadFile(filename string) ([]byte, error)
func TempDir(dir, prefix string) (name string, err error)
func TempFile(dir, prefix string) (f *os.File, err error)
func WriteFile(filename string, data []byte, perm os.FileMode) error

1)通过指定路径,读取一个文件,并返回 []byte 数据和错误信息

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

demo:通过文件路径读取一个文件,输出文件中的内容

package main
import (
"fmt"
"io/ioutil"
) func readFileByName(fileName string){
contentSlice, err := ioutil.ReadFile(fileName)
if err == nil {
fmt.Print(string(contentSlice))
}
} func main(){
var fileName string = "D:\\code\\go_dev\\projects\\src\\part_10_终端输入输出 && 文件操作\\01_使用os.osutil读取文件\\test.txt"
readFileByName(fileName)
} 运行结果:
my name is johny
i'm 12 years old
i like speaking english
i like to eat cake

2)通过指定路径,读取一个目录,并返回目录下的文件类型列表和错误信息

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

demo:打开一个目录,输出目录下文件的名称

package main
import (
"fmt"
"io/ioutil"
) func readDiractory(dirName string) {
fileInfoSlice, err := ioutil.ReadDir(dirName)
if err != nil {
fmt.Println(err)
return
}
for _, fileInfo := range fileInfoSlice {
fileName := fileInfo.Name()
fmt.Println(fileName)
}
} func main() {
var dirName string = "D:\\code\\go_dev\\file_test"
readDiractory(dirName)
} 运行结果:
test1.txt
test2.txt
test3.txt

使用 os.Open() 和 os.OpenFile() 函数读取

不论是 os.Open() 还是 os.OpenFile,都返回一个文件类型指针(*File),File 文件类型是一个结构体,封装了关于文件相关操作的方法

关闭一个文件:

File.Close()

1)os.Open()

打开一个将被读取的文件,如果读取成功,返回文件类型,默认的权限是 O_RDONLY,也就是只读权限,否则返回错误

func os.Open(name string) (*File, error)

  

2)os.OpenFile()

大部分用户会选择这个函数来代替 os.Open() 函数

主要原因是这个函数打开文件时可以指定参数(os.O_APPEND | os.O_CREATE | os.O_WRONLY),以及文件权限(0666)

func os.OpenFile(name string, flag int, perm FileMode) (*File, error)

flag 相关参数:

const (
O_RDONLY int = syscall.O_RDONLY // 只读打开文件和os.Open()同义
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 // 如果可以的话,当打开文件时先清空文件
)

3)使用 os.Open() 函数和 ioutil.ReadAll() 函数来读取文件

由于 os.Open 是打开一个文件并返回文件指针类型(*File),因此其实可以结合 ioutil 包中的 ReadAll(r io.Reader) ([]byte, error) 函数来进行读取的(这里还有点疑问)

io.Reader 其实是一个包含 Read() 方法的接口类型,而文件类型(File)是实现了 Read() 方法的

ioutil.ReadAll() 函数从一个文件类型( io.Reader )中读取内容直到返回错误或者结束(EOF)时返回读取的数据,当 err == nil 时,数据成功读取到 []byte 中

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

demo:打开一个绝对路径下的文件

package main
import (
"fmt"
"io"
"io/ioutil"
"os"
) func readByFielType(fileType io.Reader){
contentSlice, err := ioutil.ReadAll(fileType)
if err == nil {
fmt.Print(string(contentSlice))
}
} func main(){
fileType, err := os.Open("D:\\code\\go_dev\\projects\\src\\part_10_终端输入输出 && 文件操作\\01_使用os.osutil读取文件\\test.txt")
if err != nil {
fmt.Printf("file open failed, detail is %v", err.Error())
} else {
readByFielType(fileType)
}
defer fileType.Close()
} 运行结果:
my name is johny
i'm 12 years old
i like speaking english
i like to eat cake

这种方式会比较繁琐一些,因为使用了 os 的同时借助了 ioutil,但是在读取大文件的时候还是比较有优势的

带缓存的读取(bufio)

bufio 包实现了缓存 IO,创建了 Reader 和 Writer 类型结构体,这种带有缓存的方式,对于文本 I/O 来说,提供了一些便利

bufio 包中对 Reader 类型结构体有很多相关的函数及方法:

//首先定义了一个用来缓冲io.Reader对象的结构体,同时该结构体拥有以下相关的方法
type Reader struct {
} //NewReader函数用来返回一个默认大小buffer的Reader对象(默认大小好像是4096) 等同于NewReaderSize(rd,4096)
func NewReader(rd io.Reader) *Reader //该函数返回一个指定大小buffer(size最小为16)的Reader对象,如果 io.Reader参数已经是一个足够大的Reader,它将返回该Reader
func NewReaderSize(rd io.Reader, size int) *Reader //该方法返回从当前buffer中能被读到的字节数
func (b *Reader) Buffered() int //Discard方法跳过后续的 n 个字节的数据,返回跳过的字节数。如果0 <= n <= b.Buffered(),该方法将不会从io.Reader中成功读取数据。
func (b *Reader) Discard(n int) (discarded int, err error) //Peekf方法返回缓存的一个切片,该切片只包含缓存中的前n个字节的数据
func (b *Reader) Peek(n int) ([]byte, error) //把Reader缓存对象中的数据读入到[]byte类型的p中,并返回读取的字节数。读取成功,err将返回空值
func (b *Reader) Read(p []byte) (n int, err error) //返回单个字节,如果没有数据返回err
func (b *Reader) ReadByte() (byte, error) //该方法在b中读取delimz之前的所有数据,返回的切片是已读出的数据的引用,切片中的数据在下一次的读取操作之前是有效的。如果未找到delim,将返回查找结果并返回nil空值。因为缓存的数据可能被下一次的读写操作修改,因此一般使用ReadBytes或者ReadString,他们返回的都是数据拷贝
func (b *Reader) ReadSlice(delim byte) (line []byte, err error) //功能同ReadSlice,返回数据的拷贝
func (b *Reader) ReadBytes(delim byte) ([]byte, error) //功能同ReadBytes,返回字符串
func (b *Reader) ReadString(delim byte) (string, error) //该方法是一个低水平的读取方式,一般建议使用ReadBytes('\n') 或 ReadString('\n'),或者使用一个 Scanner来代替。ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片,用于读取一行数据,不包括行尾标记(\n 或 \r\n)
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) //读取单个UTF-8字符并返回一个rune和字节大小
func (b *Reader) ReadRune() (r rune, size int, err error)

demo:使用 NewReader() 函数返回一个 *Reader 类型,然后使用 ReadString() 方法读取文件内容,使用 for 循环,一直读到文件结尾

package main
import (
"bufio"
"fmt"
"io"
"os"
) func bufioRead(){
fileType, err := os.Open("D:\\golang_workspace\\file_test\\test.txt")
if err != nil {
fmt.Printf("file open failed, detail is %v", err.Error())
os.Exit(2)
}
defer fileType.Close() var bufReader *bufio.Reader = bufio.NewReader(fileType)
for {
contents, err := bufReader.ReadString('\n')
if err != io.EOF {
fmt.Print(contents)
} else {
break
}
}
} func main(){
bufioRead()
} 运行结果:
想带你逃学看一场演唱会
想你难过时在我怀中流泪
想和你背包走遍天南地北
想你共我尝尽人生的滋味
想下雨时小伞中有你依偎
想把酒言欢时也有你作陪

写文件

上面的读操作的方式同样也支持写操作

使用 ioutil 包进行文件写入

写入 []byte 类型的数据到 filename 文件中,文件的权限为 perm

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

demo:使用 WriteFile() 函数写入内容到文件

package main
import (
"fmt"
"io/ioutil"
) func ioutilWrite(){
var contents string = "hello world ~"
var data []byte = []byte(contents)
err := ioutil.WriteFile("D:\\golang_workspace\\file_test\\test.txt", data, 0644)
if err != nil {
fmt.Printf("open file failed, detail is %v", err)
} else {
fmt.Println("write success ~")
}
} func main(){
ioutilWrite()
} 运行结果:
write success ~ //覆盖写入

使用 os.OpenFile() 函数进行文件写入

因为 os.OpenFile() 函数会打开文件,并返回文件类型结构体指针,而该文件类型是一个结构体,拥有一些写入相关的方法

func os.OpenFile(name string, flag int, perm FileMode) (*File, error)

flag 相关参数及含义:

const (
O_RDONLY int = syscall.O_RDONLY // 只读打开文件和os.Open()同义
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 // 如果可以的话,当打开文件时先清空文件
)

文件类型结构体以及相关写入文件的方法:

1)写入长度为b字节切片到文件f中,返回写入字节号和错误信息。当n不等于len(b)时,将返回非空的err

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

2)在off偏移量出向文件f写入长度为b的字节

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

3)类似于Write方法,但是写入内容是字符串而不是字节切片

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

demo:使用 os.OpenFile() 函数打开文件,使用 Write() 和 WriteString() 方法将内容写入到文件

package main
import (
"fmt"
"os"
) func osOpenWrite(){
fileType, errOpen := os.OpenFile("D:\\golang_workspace\\file_test\\test.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if errOpen != nil {
fmt.Printf("openfile failed, detail is %v", errOpen.Error())
return
}
defer fileType.Close() //写入字符串
_, errWrite1 := fileType.WriteString("hello world")
if errWrite1 != nil {
fmt.Printf("write file error, detail is %v", errWrite1.Error())
} else {
fmt.Println("write string success ~")
} //写入字符切片
_, errWrite2 := fileType.Write([]byte("hello world"))
if errWrite2 != nil {
fmt.Printf("write file error, detail is %v", errWrite2.Error())
} else {
fmt.Println("write []byte success ~")
}
} func main(){
osOpenWrite()
} 运行结果:
write string success ~
write []byte success ~

带缓存的写入(bufio)

bufio 和 io 包中很多操作都是相似的,唯一不同的是 bufio 提供了一些缓冲的操作,如果对文件操作比较频繁的,使用 bufio 还是能提高程序的性能和效率的

在 bufio 中,有一个 Writer 类型结构体,与其相关的方法支持一系列的写入操作:

//Writer是一个空的结构体,一般需要使用NewWriter或者NewWriterSize来初始化一个结构体对象
type Writer struct {
// contains filtered or unexported fields
} //NewWriterSize和NewWriter函数
//返回默认缓冲大小的Writer对象(默认是4096)
func NewWriter(w io.Writer) *Writer //指定缓冲大小创建一个Writer对象
func NewWriterSize(w io.Writer, size int) *Writer //Writer对象相关的写入数据的方法 //把p中的内容写入buffer,返回写入的字节数和错误信息。如果nn<len(p),返回错误信息中会包含为什么写入的数据比较短
func (b *Writer) Write(p []byte) (nn int, err error)
//将buffer中的数据写入 io.Writer
func (b *Writer) Flush() error //以下三个方法可以直接写入到文件中
//写入单个字节
func (b *Writer) WriteByte(c byte) error
//写入单个Unicode指针返回写入字节数错误信息
func (b *Writer) WriteRune(r rune) (size int, err error)
//写入字符串并返回写入字节数和错误信息
func (b *Writer) WriteString(s string) (int, error)

demo:使用 NewWriter() 函数得到一个 *Writer(指针类型结构体),然后调用 Write() 方法将内容写入到文件,最后调用 Flush() 方法把数据刷新到磁盘

package main
import (
"bufio"
"fmt"
"os"
) func bufioWrite(){
fileType, errOpen := os.OpenFile("D:\\golang_workspace\\file_test\\test.txt", os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if errOpen != nil {
fmt.Printf("openfile failed, detail is %v", errOpen.Error())
return
}
defer fileType.Close() //生成 *Writer 指针结构体
var writer *bufio.Writer = bufio.NewWriter(fileType)
_, errWrite := writer.Write([]byte("hello world ~"))
if errWrite != nil {
fmt.Printf("file write error, detail is %v", errWrite.Error())
} //刷新数据到磁盘
errFlush := writer.Flush()
if errFlush != nil {
fmt.Println("file flush error")
panic(errFlush)
} else {
fmt.Println("write file success")
}
} func main(){
bufioWrite()
} 运行结果:
write file success

文件 copy

demo:把一个文件的内容,拷贝到另一个文件中

package main
import (
"fmt"
"io"
"os"
) func main(){
var srcFileName string = "D:\\golang_workspace\\file_test\\source.txt"
var targetFileName string = "D:\\golang_workspace\\file_test\\target.txt"
CopyFile(srcFileName, targetFileName)
} func CopyFile(srcFileName, targetFileName string){
srcFile, err := os.Open(srcFileName)
if err != nil {
fmt.Printf("open srcfile failed, err:[%v]", err)
}
defer srcFile.Close() targetFile, err := os.OpenFile(targetFileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil {
fmt.Printf("open targetfile failed, err:[%v]", err)
}
defer targetFile.Close() written, err := io.Copy(targetFile, srcFile)
if err != nil {
fmt.Printf("file copy failed, err[%v]", err)
}
fmt.Printf("copy complete, writen[%v]", written)
} 运行结果:
copy complete, writen[14]

  

总结:

Go 语言中,文件操作读和写用到了三个包,分别是 ioutil    os    bufio:

  1. ioutil.ReadFile,   ioutil.ReadDir,  ioutil.ReadAll       和       ioutil.WriteFile
  2. os.Open      和      os.OpenFile
  3. bufio.Reader      和      bufio.Writer

其中也有穿插使用,比如:os.Open 和 ioutil.ReadAll,os.Open 和 bufio.Reader,os.OpenFile 和 bufio.Writer

ending ~

Go 终端读写 && 文件读写、copy的更多相关文章

  1. 【python系统学习17】python中的文件读写

    python中的文件读写 文件读写,是Python代码调用电脑文件的主要功能,能被用于读取和写入文本.音频片段.Excel文档.邮件以及任何保存在电脑上的东西. 可使用python批量的操作本地文件, ...

  2. Lua读写文件

    文件读写 文件读写对制作游戏很有帮助.可以调用别的文件中的代码,保存最高分.游戏存档.玩家状态等信写到文件中. 首先,让我们看一个简单的命令:dofile.这个命令会读入另一个文件的代码并立即执行. ...

  3. 处理Python2.7读写文件中的中文乱码问题

    1.设置默认编码 在Python代码中的任何地方出现中文,编译时都会报错,这时可以在代码的首行添加相应说明,明确utf-8编码格式,可以解决一般情况下的中文报错.当然,编程中遇到具体问题还需具体分析啦 ...

  4. LINUX读写文件

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  5. C/C++文件读写操作总结

    本文主要从两方面介绍读写文件操作,一个是C,另一个是C++. 一.基于C的文件操作. 在ANSI C中对文件操作有两种方式,一种是流式文件操作,另一种是I/O文件操作.下面分别介绍. 1.流式文件操作 ...

  6. C/C++ 文件读写

    •前言 第一次接触文件读写是在大一的C语言教材中,当时哼哧吧唧的学的贼费劲,虽然最后也学会了,但好像没怎么用过. 在后来,就是在OJ上刷题的时候,编写的代码有时候连样例都不能通过: 这个时候就需要各种 ...

  7. go 终端读写、文件读写

    go 终端读写 操作终端相关文件句柄常量 os.Stdin:标准输入 os.Stdout:标准输出 os.Stderr:标准错误输出 示例: package main import ( "b ...

  8. Go语言学习之7 接口实例、终端文件读写、异常处理

    本节主要内容: 1. 终端读写2. 文件读写3. 命令行参数4. Json5. 自定义错误 1. 终端读写 操作终端相关文件句柄常量    os.Stdin:标准输入    os.Stdout:标准输 ...

  9. linux shell 之终端读写文件数据流和重定向>,<,<<,>>

    终端实现文件中数据流的读写: 重定向命令列表如下: 命令 说明 command > file 将输出重定向到 file.将终端数据写到文件file中 command < file 将输入重 ...

随机推荐

  1. typescript类 继承 修饰符

    //1.ts中类的定义 /* es5: function Person(name){ this.name=name; this.run=function(){ console.log(this.nam ...

  2. ISO/IEC 9899:2011 条款6.8.6——跳转语句

    6.8.6 跳转语句 语法 1.jump-statement: goto    identifier    ; continue    ; break    ; return    expressio ...

  3. 转 移动云基于MySQL Galera的PXC运维实战

    ##sample 1 : mysql 监控 1.phpadmin  比较简单,适合上手 2.mysql_web python 写的, https://github.com/ycg/mysql_web/ ...

  4. CentOS7下yum安装Redis

    (1).Redis概述 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value(键值型)数据库(非关系型数据库),并提供多种语言的API. Redi ...

  5. django项目mysite

    项目建立 建立项目mysite 各文件和目录解释: 外层的mysite/目录与Django无关,只是你项目的容器,可以任意重命名. manage.py:一个命令行工具,用于与Django进行不同方式的 ...

  6. MVC ViewBag和ViewData的使用

    ViewBag public ActionResult About() { ViewBag.Message = "Your application description page.&quo ...

  7. 个人博客搭建全记录(Hexo,Github)

    搭建过程主要借鉴小歪的博客 博客主题airclod Hexo,Github建站记录 1. 准备 Github账号 注册登陆Github 创建Repository,Repository Name就是Yo ...

  8. 【剑指offer】面试题 52. 两个链表的第一个公共结点

    面试题 52. 两个链表的第一个公共结点 NowCoder 题目描述 输入两个链表,找出它们的第一个公共结点. Java 实现 ListNode Class class ListNode { int ...

  9. lnmp+tp5安装纪要

    1: lnmp : https://lnmp.org/install.html  官网安装帮助 运行命令:wget http://soft.vpser.net/lnmp/lnmp1.6.tar.gz ...

  10. 《Mysql - Count(*) 的优化》

    一:Count(*) 的实现方式? - 要明确的是,在不同的 MySQL 引擎中,count(*) 有不同的实现方式. - MyISAM 引擎把一个表的总行数存在了磁盘上,因此执行 count(*) ...