文章目录
- 文件操作
- 打开文件
- 文件读取
- 写文件
- 判读文件或文件夹是否存在
- 拷贝文件
- 统计文件字符
- 命令行参数
- flag包解析命令行参数
文件操作
os.File
封装所有文件相关操作,File是一个结构体
打开文件
package main
import (
"fmt"
"os"
)
func main() {
file,err:=os.Open("test/test.txt")
if err!=nil{
fmt.Println("open file err=",err)
}
fmt.Printf("file=%v\n",file)
err=file.Close()
if err!=nil{
fmt.Println("close file err=",err)
}
}
//open file err= open test.txt: The system cannot find the file specified.
// file=<nil>
// close file err= invalid argument
//自行创建文件之后
//file=&{0xc0000c2780}
文件读取
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
file,err:=os.Open("test/test.txt")
if err!=nil{
fmt.Println("open file err=",err)
}
defer file.Close()
reader:=bufio.NewReader(file)
for{
str,err:=reader.ReadString('\n')
fmt.Print(str)
if err==io.EOF{//io.EOF表示文件的末尾
break
}
}
fmt.Println()
fmt.Println("文件读取结束。。。")
}
//123
//123
//文件读取结束。。。
使用ioutil一次将整个文件读入内存中,这种方法适用于文件不大的情况
package main
import (
"fmt"
"io/ioutil"
)
func main() {
content,err:=ioutil.ReadFile("test/test.txt")
if err!=nil{
fmt.Printf("read file err=%v\n",err)
}
fmt.Println(content)//[]byte
fmt.Printf("%v",string(content))
}
//[49 50 51 13 10 49 50 51]
//123
//123
写文件
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file,err:=os.OpenFile("test/a.txt",os.O_WRONLY | os.O_CREATE,0666)
if err!=nil{
fmt.Printf("open file err=%v",err)
return
}
defer file.Close()
str:="hello,world!\n"
writer:=bufio.NewWriter(file)
for i:=0;i<5;i++{
writer.WriteString(str)
}
//先写到缓存,需要调用Flush方法,将缓冲的数据真正写入到文件中,否则文件没有数据
writer.Flush()
}
示例:将一个文件的内容写入到另一个文件
注意:这两个文件都已经存在了
package main
import (
"fmt"
"io/ioutil"
)
func main() {
content1,err:=ioutil.ReadFile("test/a.txt")
if err!=nil{
fmt.Printf("read file err=%v",err)
return
}
err2:=ioutil.WriteFile("test/b.txt",content1,0666)
if err2!=nil{
fmt.Printf("write file err=%v",err)
}
}
判读文件或文件夹是否存在
os.Stat()
函数返回的错误值
- nil,文件或文件夹存在
- os.IsNotExist()判断为true,说明文件夹不存在
- 如果返回的错误为其他类型,不确定是否存在
package main
import (
"fmt"
"os"
)
func PathExists(path string)(bool,error){
_,err:=os.Stat(path)
if err==nil{//文件或目录
return true,nil
}
if os.IsNotExist(err){
return false,nil
}
return false,err
}
func main() {
paths:=[]string{"test/test.go","test/a.txt","test/test/"}
for _,v:=range paths{
b,e:=PathExists(v)
fmt.Printf("bool=%v,err=%v\n",b,e)
}
}
//bool=false,err=<nil>
//bool=true,err=<nil>
//bool=false,err=<nil>
拷贝文件
// filecopy.go
package main
import (
"fmt"
"io"
"os"
)
func main() {
CopyFile("target.txt", "source.txt")
fmt.Println("Copy done!")
}
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
统计文件字符
package main
import (
"bufio"
"fmt"
"io"
"os"
)
type CharCount struct {
ChCount int//英文个数
NumCount int//数字个数
SpaceCount int//空格个数
OtherCount int//其他字符个数
}
func main() {
// 打开文件,创建Reader,
// 每读取一行,就去统计该行有多少个英文、数字、空格和其他字符
fileName:="test/file_IsExist.go"
file,err:=os.Open(fileName)
if err!=nil{
fmt.Printf("open file err=%v\n",err)
return
}
defer file.Close()
var cout CharCount
reader:=bufio.NewReader(file)
// 循环读取
for{
str,err:=reader.ReadString('\n')
if err == io.EOF{
break
}
//为了兼容中文字符,可以将str转成[]rune
//str=[]rune(str)
for _,v:=range str{
switch {
case v>='a' && v<='z':
fallthrough//穿透
case v>='A' && v<='Z':
cout.ChCount++
case v==' ' && v=='\t':
cout.SpaceCount++
default:
cout.OtherCount++
}
}
}
fmt.Println(cout)
}
//{227 0 0 146}
命令行参数
os.Args
是一个string的切片,用来存储命令行参数
//file_args.go
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("命令行参数数量:",len(os.Args))
for i,v:=range os.Args{
fmt.Printf("args[%v]=%v\n",i,v)
}
}
先编译,后执行
flag包解析命令行参数
前面的方法是比较原生的方式,解析参数不是特别的方便,特别是带有指定参数形式的命令行
flag包,可以更加方便的解析命令行参数,而且参数顺序可以随意
//file_flag.go
package main
import (
"flag"
"fmt"
)
func main() {
var user string
var pwd string
var host string
var port int
//&user接收用户命令行中的输入-u后面的参数值
//"u",就是-u的指定参数
//"", 默认值
//"用户名,默认为空", 说明
flag.StringVar(&user,"u","","用户名,默认为空")
flag.StringVar(&pwd,"pwd","","密码,默认为空")
flag.StringVar(&host,"h","localhost","主机名,默认为localhost")
flag.IntVar(&port,"port",3306,"端口号,默认为3306")
//这里有一个非常重要的操作,转换,必须调用这个方法
flag.Parse()
fmt.Printf("user=%v, pwd=%v, host=%v, port=%v\n",user,pwd,host,port)
}