go 常用标准库 I/O操作
go 常用标准库 I/O操作
1.1 格式化输出
2.1 标准化输入
fmt.Println("please input two word")
var word1 string
var word2 string
//读入多个单词,空格分隔。如果输入了更多单词会被缓存起来,丢给下一次scan
fmt.Scan(&word1, &word2)
fmt.Println("please input an int")
var i int
//类似于Scan,转为特定格式的数据
//这里注意,如果上面输入参数多了,就会把多出来的给i,
//而i是int类型,如果你第三个字符多输了,且第三个是you这个单词,那他只会接收y这字母,ou是多出来的,直接报错了
fmt.Scanf("%d", &i)
3.1 打开文件
如果是只读一个文件,我们用Open就可以了
如果想有别的操作可以用OpenFile,因为可以有更多的操作
func os.Open(name string) (*os.File, error)
fout, err := os.OpenFile("data/verse.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
os.O_CREATE 如果没有这个文件就创建
os.O_TRUNC 如果有这个文件,会先清空文件内容
os.O_WRONLY 以只写的方式打开文件
0666 权限控制 这里也可以用os.ModePerm 代替,表示最大权限
不管是Open还是OpenFile都会返回一个 *os.File的对象,我们可以对*os.File进行读写
cont := make([]byte, 10)
fin.Read(cont) //读出len(cont)个字节,返回成功读取的字节数
fin.ReadAt(cont, int64(n)) //从指定的位置开始读len(cont)个字节,这里就是偏移量,从n个字节开始读
fin.Seek(int64(n), 0) //重新定位。whence: 0从文件开头计算偏移量,1从当前位置计算偏移量,2到文件末尾的偏移量
reader := bufio.NewReader(fin) //读文件文件建议用bufio.Reader缓冲提前加载
for { //无限循环
#这里会一直读,直到遇到\n换行符,这样就读出了一行,注意这里读出来是带换行符的,后面可以删掉
if line, err := reader.ReadString('\n'); err != nil { //指定分隔符
#EOF的意思是 END OF FILE
if err == io.EOF {
#这里判断,如果4行代码,第4行的时候回车是带换行符没问题的,它就会把值赋给line,但是如果第4行没回车,那么他是没换行符的,没换行符就判断下line的长度,如果大于0页打印出来,否则少最后一行数据
if len(line) > 0 { //如果最后一行没有换行符,则此时最后一行就存在line里
fmt.Println(line)
}
break //已读到文件末尾
} else {
#如果不是EOF,就打印出报错
fmt.Printf("read file failed: %v\n", err)
}
} else {
#这里把右边的换行符删掉了
line = strings.TrimRight(line, "\n") //line里面是包含换行符的,需要去掉
fmt.Println(line)
}
}
读取文件完整代码
func main() {
if fin,err := os.Open("go.mod3");err != nil {
fmt.Println(err)
return
} else {
defer fin.Close()
reader := bufio.NewReader(fin) //内存中创建缓存读取文件
for {
if line,err := reader.ReadString('\n');err == nil {
fmt.Println(line)
} else {
if err == io.EOF { //判断没有换行符的那一行,长度是否大于0,如果大于0就打印,否则会丢失最后一行
if len(line) > 0 {
fmt.Println(line)
}
} else {
fmt.Println(err)
break
}
}
}
}
}
4.1 写文件
defer fout.Close() //别忘了关闭文件句柄
writer := bufio.NewWriter(fout)
writer.WriteString("明月多情应笑我")
writer.WriteString("\n") //需要手动写入换行符,go是不会默认帮你写换行符的
写文件完整代码
注意:
- os.O_CREATE 没有这个文件就创建,有则不改动里面内容
- os.O_APPEND 对这个文件进行追加内容
- os.O_TRUNC 每次写之前先清空文件内容
func main() {
if fout,err := os.OpenFile("D:\\go\\code\\项目\\test\\test2\\go.mod3",os.O_CREATE|os.O_APPEND|os.O_WRONLY,0666); err != nil {
fmt.Println(err)
return
} else {
write := bufio.NewWriter(fout)
write.WriteString("李文超的go语言测试写文件\n")
write.WriteString("第一行\n")
write.Flush() //WriteString会先写到内存中,堆积到一定数量才会写到磁盘,这里Flush能强制直接保存到磁盘。避免程序导致刚写的内容丢失
}
}
5.1 创建文件/目录
os.Create(name string)//创建文件
os.Mkdir(name string, perm fs.FileMode)//创建目录
os.MkdirAll(path string, perm fs.FileMode)//增强版Mkdir,沿途的目录不存在时会一并创建
os.Rename(oldpath string, newpath string)//给文件或目录重命名,还可以实现move的功能
os.Remove(name string)//删除文件或目录,目录不为空时才能删除成功
os.RemoveAll(path string)//增强版Remove,所有子目录会递归删除
6.1 遍历目录
#ioutil.ReadDir获取path路径,把所有的目录和子目录都存储成切片放到 subfiles,然后对subfiles遍历获取
func main() {
walk(".")
}
func walk(path string) error {
if subfiles,err := ioutil.ReadDir(path);err != nil {
return err
} else {
for _,file := range subfiles{
fmt.Println(file)
if file.IsDir(){
//这里最好用filepath.join拼接,因为windows系统中的是\而不是 /
//if err:= walk(path+"/"+file.Name());err != nil {
if err:= walk(filepath.Join(path,file.Name()));err != nil {
return err
}
}
}
}
return nil
}
7.1 默认的log输出到控制台
程序运行肯定伴随日志,官方有log包,但是生产中基本没人用,因为有第三方的log包比如glog。
这里我们还是先介绍下官方的log包
//我们生成日志并输出到一个文件里
func logger(){
//打印 2022/05/13 13:50:58 5 ,默认前面是带时间的
log.Printf("%d\n",5)
font,err := os.OpenFile("D:\\go\\code\\测试\\test.log",os.O_APPEND|os.O_CREATE|os.O_WRONLY,os.ModePerm)
if err != nil {
return
}
defer font.Close()
//每行日志前缀都加一个 China,打印时间并且时间精确到毫秒
//打印出 China 2022/05/13 14:32:50.477063 abc
logWrite := log.New(font,"China ",log.Ldate|log.Lmicroseconds)
logWrite.Printf("%s\n","abc")
logWrite.Printf("%s","abc")
}
8.1 调用系统命令
cmd_path, err := exec.LookPath("df") //查看系统命令所在的目录,确保命令已安装
cmd := exec.Command("df", "-h") //相当于命令df -h,注意Command的每一个参数都不能包含空格
output, err := cmd.Output() //cmd.Output()运行命令并获得其输出结果
cmd = exec.Command("rm", "./data/test.log")
cmd.Run() //如果不需要获得命令的输出,直接调用cmd.Run()即可
代码整理
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"strings"
)
//格式化输出
func format() {
var i int = 1234
var f float32 = 3.1415
var stu struct {
Name string
Age int
}
stu.Name = "张三"
stu.Age = 18
fmt.Printf("%b\n", i) //二进制表示
fmt.Printf("%d\n", i)
fmt.Printf("%8d\n", i) //左边补空格,补够8位
fmt.Printf("%08d\n", i) //左边补0,补够8位
fmt.Printf("%f\n", f) //默认6位小数
fmt.Printf("%.8f\n", f)
fmt.Printf("%e\n", f) //科学计数法,默认6位小数
fmt.Printf("%.8e\n", f)
fmt.Printf("%g\n", f) //根据实际情况采用 %e 或 %f 格式(获得更简洁、准确的输出)
fmt.Printf("%t\n", 3 > 9) //true或false
fmt.Printf("%s\n", stu.Name)
fmt.Printf("%T\n", stu) //输出类型,包括结构体各个字段的名称和类型。struct { Name string; Age int }
fmt.Printf("%v\n", stu) //输出结构体各个字段的值。{张三 18}
fmt.Printf("%+v\n", stu) //还会带上字段名。{Name:张三 Age:18}
fmt.Printf("%#v\n", stu) //差不多相当于先调用%T,再调%+v。struct { Name string; Age int }{Name:"张三", Age:18}
}
//从标准输入读入数据
func scan() {
fmt.Println("please input a word")
var word string
fmt.Scan(&word) //读入第1个空格前的单词
fmt.Println(word)
fmt.Println("please input two word")
var word1 string
var word2 string
fmt.Scan(&word1, &word2) //读入多个单词,空格分隔。如果输入了更多单词会被缓存起来,丢给下一次scan
fmt.Println(word1, word2)
fmt.Println("please input an int")
var i int
fmt.Scanf("%d", &i) //类似于Scan,转为特定格式的数据
fmt.Println(i)
}
func read_file() {
if fin, err := os.Open("data/digit.txt"); err != nil {
fmt.Printf("open file faied: %v\n", err) //比如文件不存在
} else {
defer fin.Close() //别忘了关闭文件句柄
//读二进制文件
cont := make([]byte, 10)
if n, err := fin.Read(cont); err != nil { //读出len(cont)个字节,返回成功读取的字节数
fmt.Printf("read file failed: %v\n", err)
} else {
fmt.Println(string(cont[:n]))
if m, err := fin.ReadAt(cont, int64(n)); err != nil { //从指定的位置开始读len(cont)个字节
fmt.Printf("read file failed: %v\n", err)
} else {
fmt.Println(string(cont[:m]))
}
fin.Seek(int64(n), 0) //whence: 0从文件开头计算偏移量,1从当前位置计算偏移量,2到文件末尾的偏移量
if n, err = fin.Read(cont); err != nil {
fmt.Printf("read file failed: %v\n", err)
} else {
fmt.Println(string(cont[:n]))
}
}
//读文本文件建议用bufio.Reader
fin.Seek(0, 0) //定位到文件开头
reader := bufio.NewReader(fin)
for { //无限循环
if line, err := reader.ReadString('\n'); err != nil { //指定分隔符
if err == io.EOF {
if len(line) > 0 { //如果最后一行没有换行符,则此时最后一行就存在line里
fmt.Println(line)
}
break //已读到文件末尾
} else {
fmt.Printf("read file failed: %v\n", err)
}
} else {
line = strings.TrimRight(line, "\n") //line里面是包含换行符的,需要去掉
fmt.Println(line)
}
}
}
}
func write_file() {
//OpenFile()比Open()有更多的参数选项。os.O_WRONLY以只写的方式打开文件,os.O_TRUNC把文件之前的内容先清空掉,os.O_CREATE如果文件不存在则先创建,0666新建文件的权限设置
if fout, err := os.OpenFile("data/verse.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666); err != nil {
fmt.Printf("open file faied: %v\n", err)
} else {
defer fout.Close() //别忘了关闭文件句柄
//写文本文件建议使用
writer := bufio.NewWriter(fout)
writer.WriteString("明月多情应笑我")
writer.WriteString("\n") //需要手动写入换行符
writer.WriteString("笑我如今")
writer.Flush() //buffer中的数据量积累到一定程度后才会真正写入磁盘。调用Flush强行把缓冲中的所有内容写入磁盘
}
}
func create_file() {
os.Remove("data/verse.txt") //先删除,不去理会Remove可能返回的error
if file, err := os.Create("data/verse.txt"); err != nil {
fmt.Printf("create file faied: %v\n", err)
} else {
file.Chmod(0666) //设置文件权限
fmt.Printf("fd=%d\n", file.Fd()) //获取文件描述符file descriptor,这是一个整数
info, _ := file.Stat()
fmt.Printf("is dir %t\n", info.IsDir())
fmt.Printf("modify time %s\n", info.ModTime())
fmt.Printf("mode %v\n", info.Mode()) //-rw-rw-rw-
fmt.Printf("file name %s\n", info.Name())
fmt.Printf("size %d\n", info.Size())
}
os.Mkdir("data/sys", os.ModePerm) //创建目录并设置权限
os.MkdirAll("data/sys/a/b/c", os.ModePerm) //增强版Mkdir,沿途的目录不存在时会一并创建
os.Rename("data/sys/a", "data/sys/p") //给文件或目录重命名
os.Rename("data/sys/p/b/c", "data/sys/p/c") //Rename还可以实现move的功能
os.Remove("data/sys") //删除文件或目录,目录不为空时才能删除成功
os.RemoveAll("data/sys") //增强版Remove,所有子目录会递归删除
}
//遍历一个目录
func walk(path string) error {
if fileInfos, err := ioutil.ReadDir(path); err != nil {
return err
} else {
for _, fileInfo := range fileInfos {
fmt.Println(fileInfo.Name())
if fileInfo.IsDir() { //如果是目录,就递归子遍历
if err := walk(filepath.Join(path, fileInfo.Name())); err != nil { //通过filepath.Join连接父目录和当前目录
return err
}
}
}
}
return nil
}
//打日志
func logger() {
log.Printf("%d+%d=%d\n", 3, 4, 3+4)
log.Println("Hello Golang")
// log.Fatalln("Bye, the world") //日志输出后会执行os.Exit(1)
//以append方式打开日志文件
fout, err := os.OpenFile("data/test.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
fmt.Printf("open log file failed: %v\n", err)
}
defer fout.Close()
logWriter := log.New(fout, "[MY_BIZ]", log.Ldate|log.Lmicroseconds) //通过flag参数定义日志的格式,时间精确到微秒1E-6s
logWriter.Printf("%d+%d=%d\n", 3, 4, 3+4)
logWriter.Println("Hello Golang")
// logWriter.Fatalln("Bye, the world")
}
//执行系统命令
func sys_call() {
//查看系统命令所在的目录,确保命令已安装
cmd_path, err := exec.LookPath("df")
if err != nil {
fmt.Println("could not found command echo")
}
fmt.Printf("command echo in path %s\n", cmd_path) // /bin/df
cmd := exec.Command("df", "-h") //相当于命令df -h,注意Command的每一个参数都不能包含空格
//cmd.Output()运行命令并获得其输出结果
if output, err := cmd.Output(); err != nil {
fmt.Println("got output failed", err)
} else {
fmt.Println(string(output))
}
cmd = exec.Command("rm", "./data/test.log")
//如果不需要获得命令的输出,直接调用cmd.Run()即可
err = cmd.Run()
if err != nil {
fmt.Println("run failed", err)
}
}
func main() {
format()
fmt.Println()
scan()
fmt.Println()
read_file()
fmt.Println()
write_file()
fmt.Println()
create_file()
fmt.Println()
walk("./lib")
logger()
sys_call()
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!