文章目录
1 读取文件
读文件用 os
包,需要注意的是在打开一个文件进行操作后需要及时关闭文件。用几个小例子来说明一下。
1.1 exa1
package main
import (
"fmt"
"os"
)
func main() {
// 打开一个文件
// 概念说明:file的叫法
// 1.file 叫 file对象
// 2.file 叫 file指针
// 3.file 叫 file文件句柄
file, err := os.Open("d:/test.txt")
if err != nil {
fmt.Println("Open file err=", err)
}
// 输出以下内容可以看出file就是一个指针
fmt.Printf("file=%v", file) // 输出file=&{0xc000084780}
// 关闭文件
err = file.Close()
if err != nil {
fmt.Println("close file err=", err)
}
}
1.2 exa2
读文件的内容并显示在终端(带缓冲区的方式)使用os.Open()
, file.close()
, bufio.NewReader()
, reader.ReadString
函数和方法。
package main
import (
"fmt"
"os"
"bufio"
"io"
)
func main() {
// 打开文件
file, err := os.Open("d:/test.txt")
if err != nil {
fmt.Println("Open file err=", err)
}
// 当函数退出时候,要及时关闭文件句柄,否则会有内存泄漏
defer file.Close()
// 创建一个带缓冲的 *Reader
// 默认缓冲区 4096
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('\n') // 每读到一个换行就结束一次
if err == io.EOF { // io.EOF代表文件的末尾
break
}
// 输出内容
fmt.Print(str)
}
fmt.Println("文件读取结束")
}
// 需要注意的是如果使用 if err == io.EOF ,那么在我们要读取的文件中最后一行一定是一个换行
// 否则不能读取到最后一行
1.3 exa3
读取文件的内容并显示在终端(使用ioutil
一次将整个文件读入到内存中)这种方式适用于文件不大的情况,相关方法和函数(ioutil.ReadFile),此函数封装了打开和关闭的操作
package main
import (
"fmt"
"io/ioutil"
)
func main() {
// 使用 ioutil.ReadFile 一次性将文件读取到位
file := "d:/test.txt"
content, err := ioutil.ReadFile(file)
if err != nil {
fmt.Printf("read file err = %v", err)
}
// 把读取到的内容显示到终端
fmt.Printf("%v", content) // []byte 会以byte切片的样式输出
// 因为没有显式Open,因此也不需要显式的Close文件文件的Open和Close功能都被封装到函数中
fmt.Printf("%s", content) // 可以完整将字符串输出
//fmt.Printf("%v", string(content))
}
1.4 判断文件是否存在
golang中判断文件或文件夹是否存在的方法是使用 os.Stat()
函数返回的错误值进行判断。
package main
import (
"fmt"
"os"
)
// 判断文件是否存在
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { // 如果err为空,则证明文件存在
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func main() {
filePath := "d:/test.txt"
b, err := PathExists(filePath)
if b == true && err == nil {
fmt.Printf("%v文件存在", filePath)
return
}
fmt.Printf("%v文件不存在", filePath)
}
2 写入文件内容
需要用到 os.OpenFile
函数
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
说明: os.OpenFile
它会使用指定的选项(如os.o_RDONLY
等)、指定的模式(如0666等,此选项只在linux系统中生效),如果成功,则返回的对象可以用于 I/O
操作
2.1 exa1
创建一个新文件,写入内容 5 句 “hello, Gardon”
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
// 创建一个新文件,写入内容 5 句 "hello, Gardon"
// 1.打开文件 d:/abc.txt
filePath := "d:/abc.txt"
file, err := os.OpenFile(filePath, os.O_CREATE | os.O_WRONLY, 0666)
if err != nil {
fmt.Printf("open file err = %v", err)
return
}
// 准备写入5句话
str := "hello, Gardon\r\n" // 表示换行
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
// 及时关闭file句柄
defer file.Close()
// 因为writer是带缓存,因此在调用WriteString方法时
// 其实内容是先写入到缓存的,所以需要调用Flush方法,将缓冲的数据真正写入到文件中,
// 否则文件中会没有数据
writer.Flush()
}
2.2 exa2
打开一个已经存在的文件,将原来的内容覆盖成新的内容10句 “你好,我是老大”
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
// 打开一个已经存在的文件,将原来的内容覆盖成新的内容10句 "你好,我是老大"
// 1.打开文件 d:/abc.txt
filePath := "d:/abc.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_TRUNC , 0666)
if err != nil {
fmt.Printf("open file err = %v", err)
return
}
// 及时关闭file句柄
defer file.Close()
// 写入10句 "你好,我是老大"
str := "你好,我是老大\r\n" // 表示换行
writer := bufio.NewWriter(file)
for i := 0; i < 10; i++ {
writer.WriteString(str)
}
writer.Flush()
}
2.3 exa3
打开一个存在的文件,在原来的内容追加内容 'ABC!ENGHSK’
package main
import (
"fmt"
"bufio"
"os"
)
func main() {
// (3)打开一个存在的文件,在原来的内容追加内容 'ABC!ENGHSK'
filePath := "d:/abc.txt"
file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_APPEND , 0666)
if err != nil {
fmt.Printf("open file err = %v", err)
return
}
// 及时关闭file句柄
defer file.Close()
// 写入10句 'ABC!ENGHSK'
str := "'ABC!ENGHSK'\r\n" // 表示换行
writer := bufio.NewWriter(file)
for i := 0; i < 10; i++ {
writer.WriteString(str)
}
writer.Flush()
}
2.4 exa4
打开一个存在的文件,将原来的内容读出显示在终端,并且追加5句"hello, 北京"
package main
import (
"fmt"
"bufio"
"os"
"io"
)
func main() {
// (4)打开一个存在的文件,将原来的内容读出显示在终端,并且追加5句"hello, 北京"
filePath := "d:/abc.txt"
file, err := os.OpenFile(filePath, os.O_RDONLY | os.O_APPEND , 0666)
if err != nil {
fmt.Printf("open file err = %v", err)
return
}
// 及时关闭file句柄
defer file.Close()
// 先读取原来的内容
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('\n')
if err == io.EOF {
break
}
// 显示到终端
fmt.Print(str)
}
// 写入10句 "hello, 北京"
str := "hello, 北京\r\n" // 表示换行
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
writer.Flush()
}
2.5 exa5
编写一个程序,将一个文件的内容写入到另一个文件。这两个文件已经存在
package main
// 编写一个程序,将一个文件的内容写入到另一个文件。这两个文件已经存在
// 使用ioutil.ReadFile / ioutil.WriteFile
import (
"fmt"
"io/ioutil"
)
func main() {
// 将d:/abc.txt文件内容导入到 f:/kkk.txt
// 声明两个文件名
file1Path := "d:/abc.txt"
file2Path := "f:/kkk.txt"
// 1.将d:/abc.txt内容读取到内存
content, err := ioutil.ReadFile(file1Path)
if err != nil {
// 说明文件读取有错误
fmt.Printf("read file err = %v\n", err)
return
}
// 2.将读取到的内容写入到 f:/kkk.txt
err = ioutil.WriteFile(file2Path, content, 0666)
if err != nil {
fmt.Printf("write file error = %v\n", err)
}
}
3 文件的拷贝
3.1 拷贝非文本文件的文件
package main
import (
"fmt"
"os"
"io"
_ "io/ioutil"
"bufio"
)
// 将一张图片/电影/mp3文件拷贝到另一个文件中 需要用到io包(注意不是文本文件)
// io.Copy
// 编写一个函数,接收两个文件路径 srcFileName dstFileName
func CopyFile(dstFileName string, srcFileName string) (written int64, err error) {
srcfile, err := os.Open(srcFileName)
if err != nil {
fmt.Printf("Open file err = %v", err)
}
defer srcfile.Close()
//通过srcfile句柄获取到 Reader
reader := bufio.NewReader(srcfile)
// 打开dstFileName(由于这个文件可能不存在,所以不能用os.Open来打开)
dstFile, err := os.OpenFile(dstFileName, os.O_CREATE | os.O_WRONLY, 0666)
if err != nil {
fmt.Printf("open file err = %v", err)
return
}
// 通过dstFile,获取到writer
writer := bufio.NewWriter(dstFile)
defer dstFile.Close()
return io.Copy(writer, reader)
}
func main() {
// 将 d:/flower.jpg 拷贝到 f:/abc.jpg
// 调用CopyFile完成文件的拷贝
srcFile := "d:/flower.jpg"
dstFile := "f:/abc.jpg"
_, err := CopyFile(dstFile, srcFile)
if err == nil {
fmt.Println("Copy Successd!")
} else {
fmt.Println("Copy error info = %v", err)
}
}
3.2 拷贝文本文件
package main
import (
"fmt"
"os"
"io"
_ "io/ioutil"
"bufio"
)
// 将文本文件拷贝到另一个文件中 需要用到io包,
// io.Copy
// 编写一个函数,接收两个文件路径 srcFileName dstFileName
func CopyFile(dstFileName string, srcFileName string) (written int64, err error) {
srcfile, err := os.Open(srcFileName)
if err != nil {
fmt.Printf("Open file err = %v", err)
}
defer srcfile.Close()
//通过srcfile句柄获取到 Reader
reader := bufio.NewReader(srcfile)
// 打开dstFileName(由于这个文件可能不存在,所以不能用os.Open来打开)
dstFile, err := os.OpenFile(dstFileName, os.O_CREATE | os.O_WRONLY, 0666)
if err != nil {
fmt.Printf("open file err = %v", err)
return
}
// 通过dstFile,获取到writer
writer := bufio.NewWriter(dstFile)
// 循环把src读取的每行数据写入到writer
for {
str, err := reader.ReadString('\n')
if err == io.EOF { // io.EOF代表文件的末尾
break
}
// 显示到终端
writer.WriteString(str)
}
// flush把缓冲的数据写入到真实文件中
writer.Flush()
defer dstFile.Close()
return io.Copy(writer, reader)
}
func main() {
// 将 d:/flower.txt 拷贝到 f:/abc.txt
srcFile := "d:/flower.txt"
dstFile := "f:/abc.txt"
_, err := CopyFile(dstFile, srcFile)
if err == nil {
fmt.Println("Copy Successd!")
} else {
fmt.Println("Copy error info = %v", err)
}
}
4 命令行参数
如果希望获取到命令行输入的各种参数,可以使用os.Args
,它是一个string切片
,用来存储所有的命令行参数
4.1 exa1
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)
}
/*
D:\goproject\src\go_code\file\commandLineArgs>main.exe D:\goproject\src\go_code 99
命令行的参数有 3
args[0]=main.exe
args[1]=D:\goproject\src\go_code
args[2]=99
*/
}
4.2 exa2 (flag)
golang中可以用flag
包来解析命令行参数,exa1中使用的 os.Args
来获取命令行参数比较原生,解析不是特别方便,尤其是带有指定参数形式的命令行
package main
import (
"fmt"
"flag"
)
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",
user, pwd, host, port)
/*
可以不用指定顺序
D:\goproject\src\go_code\file\commandLineArgs\flag>go build -o flag.exe main.go
D:\goproject\src\go_code\file\commandLineArgs\flag>flag.exe -u root -pwd 12335465 -h 192.168.0.1 -port 8080
user=root pwd=12335465 host=192.168.0.1 port=8080
默认值
D:\goproject\src\go_code\file\commandLineArgs\flag>flag.exe -u root -pwd 12335465
user=root pwd=12335465 host=localhost port=3306
*/
}