1.文件操作
题外话:标准库怎么访问?
- 两种
- 到Go文件中打开
- ctrl+点击 某函数
- 到Go文件中打开
- 官网
1.1、文件与目录
创建
作用 | 语法/实例说明 | ||
---|---|---|---|
create |
创建文件 | 底层是OpenFile,实例见下方 |
|
CreateTemp |
创建临时文件 | 结果 1. "" 是表示是临时文件,temp是前缀(temp2896…..)2. 创建地址在临时目录地址(系统自设的) 3. 临时文件有什么作用??? |
|
创建目录 | <font style="color:rgb(0,0,0);">Mkdir</font> |
创建单个目录 | 地址在项目目录下 |
<font style="color:rgb(0,0,0);">MkdirAll</font> |
创建多层目录 | 地址在项目目录下 | |
NewFile | ???描述 | **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">NewFile(fd </font><font style="color:rgb(0,0,128);">uintptr</font><font style="color:rgb(0,0,0);">, name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) *File </font> 根据文件描述符创建相应的文件,返回一个文件对象 |
:::info create实例
:::
结果
- 文件格式——包含在名字里(我猜的,目前只创建过文本文件)
- 地址在项目地址里
- 若已存在同名文件名,再创建,就会覆盖旧文件重新创建
(OpenFile("a.txt", os.O_RDWR|os.O_CREATE|O_TRUNC,0666)
等价于create("a.txt")
其中O_TRUNC
表示覆盖同名旧文件的意思)
删除文件
remove
- 删除文件
**<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">Remove(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) Error</font>
- 删除目录以及其包含的东西
**<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">RemoveAll(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) Error</font>
?获取和修改工作目录
这里的临时目录是什么???干什么用的???
作用 | 语法/实例解析 | |
---|---|---|
getWd() |
获得工作目录 | 结果(获得地项目地址) |
chWd() |
修改工作目录 | |
TempDir() |
获得临时目录 | 结果 |
重命名文件
注意,必须是Rename,不能是rename
黑马实例分析
:::info 写文件
:::
package main
import (
"fmt"
"os"
)
func main() {
fout, err := os.Create("./xxx.txt") //新建文件
//fout, err := os.OpenFile("./xxx.txt", os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
return
}
defer fout.Close() //main 函数结束前, 关闭文件
for i := 0; i < 5; i++ {
outstr := fmt.Sprintf("%s:%d\n", "Hello go", i)
fout.WriteString(outstr) //写入 string 信息到文件
fout.Write([]byte("abcd\n")) //写入 byte 类型的信息到文件
}
}
结果:
:::info 读文件
:::
读文件,要先打开,Open方法,给到fin,再读取read,给到buf,n:_:=fin.Read(buf)
,n=0时就表示读完了
func main() {
fin, err := os.Open("./xxx.txt") //打开文件
if err != nil {
fmt.Println(err)
}
defer fin.Close()
buf := make([]byte, 1024) //开辟 1024 个字节的 slice 作为缓冲
for {
n, _ := fin.Read(buf) //读文件
if n == 0 { //0 表示已经到文件结束
break
}
fmt.Println(string(buf)) //输出读取的内容
}
}
:::info 拷贝文件
:::
package main
import (
"fmt"
"io"
"os"
)
func main() {
args := os.Args //获取用户输入的所有参数
/*如果用户没有输入,或参数个数不够,则调用该函数提示用户
(需要三个参数,可执行程序一个 xxx,源文件 src,目的文件dst)
*/
if args == nil || len(args) != 3 {
fmt.Println("useage : xxx srcFile dstFile")
return
}
srcName := args[1] //获取输入的第一个参数,
dstName := args[2] //获取输入的第二个参数
fmt.Printf("srcName = %s, dstName = %s\n", srcPath, dstPath)
if srcName == dstName {
fmt.Println("源文件和目的文件名字不能相同")
return
}
srcFile, err1 := os.Open(srcName) //打开源文件
if err1 != nil { //源文件在程序之前已存在,不创建,前面只是命个名
fmt.Println(err1)
return
}
dstFile, err2 := os.Create(dstName) //创建目的文件
if err2 != nil {
fmt.Println(err2)
return
}
buf := make([]byte, 1024) //切片缓冲区
for { //从源文件读取内容,n 为读取文件内容的长度
n, err := srcFile.Read(buf)
if err != nil && err != io.EOF {
fmt.Println(err)
break
}
if n == 0 {
fmt.Println("文件处理完毕")
break
}
//切片截取
tmp := buf[:n]
//把读取的内容写入到目的文件
dstFile.Write(tmp)
}
//关闭文件
srcFile.Close()
dstFile.Close()
}
运行结果:
拷贝的是一个MP4文件注意点:
args := os.Args
需要三个参数,可执行程序一个 xxx,源文件 src,目的文件ds
1.2、File文件读操作
打开、关闭文件
作用 | 语法→实例 | |||
---|---|---|---|---|
Open | 只读打开 | + 语法 **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">Open(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) (file *File, err Error) </font> 该方法打开一个名称为 name 的文件,但是是只读方式,内部实现其实调用了 OpenFile+ 实例 - 若不存在结果是(注意这里用println的话,结果是一堆编码???): - 若存在这里获得的结果(由于是打印名字, <font style="color:rgb(0,0,0);">f.Name()</font> ): + 若直接打印 (我发现每次执行结果都不一样,不知道为什么???) 结果 |
||
OpenFile | 根据第二个参数,打开后读写 or 创建后打开 | + 语法 **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">OpenFile(name </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">, flag </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, perm </font><font style="color:rgb(0,0,128);">uint32</font><font style="color:rgb(0,0,0);">) (file *File, err Error) </font> 打开名称为 name 的文件,flag 是打开的方式,只读、读写等,perm 是权限+ 实例 - os.O_RDWR 表示可读可写;os.O_CREATE 表示若无则创建;755是一个权限(???) - `OpenFile(“a.txt”, os.O_RDWR |
os.O_CREATE | O_TRUNC,0666)等价于 create(“a.txt”)` |
关闭 | 是一个方法,当不访问的时候,把他关闭,以保证之后读写等操作不会出错 | f.close() (f是open后读取的文件) |
读文件
作用 | 语法→实例 | |
---|---|---|
ReadFile | ???第一节 | + 语法 + 实例 |
Read | 只读不写 | + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) Read(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">) (n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error) </font> file文件的内容,读取数据到 变量b 中+ 实例 1. 打开文件 2. 设置缓冲区+读文件读进缓冲区buf,且返回得读取的字符数目n 和 error 3. 打印 实际缓冲区不可能设置的无限大,在不知道文件大小的前提下,可以使用for无限循环包住2 3 步,用 <font style="color:rgb(0,0,0);">if err == io.EOF{break}</font> 来结束 ,<font style="color:rgb(0,0,0);">io.EOF</font> 表示末尾 |
ReadAt | 从指定从某个字节开始读 | + 语法:**<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) ReadAt(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">, off </font><font style="color:rgb(0,0,128);">int64</font><font style="color:rgb(0,0,0);">)(n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 从 off 开始读取数据到 b 中+ 实例 结果: b,txt文件: |
ReadDir | 读取目录 或者叫,遍历某个目录 | 结果 注意:要求查询的目录,必须从项目地址之下的(不包含项目地址,因此不可读取所有项目地址下的所有目录),一层一层下去, "a/b/c" |
seek辅助+Read | 告诉从指定位置开始读 | 结果: offset是起点,终点取决于buf容量,后面的0确实不知道是什么??? |
1.3、File写文件操作
作用 | 语法→实例 | |
---|---|---|
writeFile | ??? | 实例 |
write | 写字节数组/切片 | + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) Write(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">) (n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 写入 byte 类型的信息到文件+ 实例 |
writeString | 写字符串 | + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">) WriteString(s </font><font style="color:rgb(0,0,128);">string</font><font style="color:rgb(0,0,0);">) (ret </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 写入 string 信息到文件+ 实例 |
writeAt | 在某个位置开始写 | + **<font style="color:rgb(0,0,128);">func </font>**<font style="color:rgb(0,0,0);">(file *</font><font style="color:rgb(0,0,128);">File</font><font style="color:rgb(0,0,0);">)WriteAt(b []</font><font style="color:rgb(0,0,128);">byte</font><font style="color:rgb(0,0,0);">, off </font><font style="color:rgb(0,0,128);">int64</font><font style="color:rgb(0,0,0);">)(n </font><font style="color:rgb(0,0,128);">int</font><font style="color:rgb(0,0,0);">, err Error)</font> 在指定位置开始写入 byte 类型的信息+ 实例 |
1.4、总结
文件 | |
---|---|
创建 | 创建文件Create |
删除 | 删除文件Remove |
重命名文件 | rename |
所有文件都要:打开→写入/只读→关闭 | |
打开文件 | Open、OpenFile |
写文件 | WriteFile、Write、WriteAt、WriteString |
读文件 | ReadFile、Read、ReadAt |
关闭文件 | Close |
目录 | |
---|---|
创建 | 创建单个目录Mkdir、创建多层目录MkdirAll |
删除 | 删除目录及包含的一切RemoveAll |
获取和修改工作目录 | 获取工作目录Getwd、修改工作目录Chdir、获得临时目录TempDir |
遍历目录 | ReadDir |
package main
import (
"fmt"
"io"
"os"
)
func CreatFile(){
f, err := os.Create("a.txt")
if err != nil {
fmt.Println(err)
}else {
fmt.Println(f)
}
}
func CreateDir(){
err := os.Mkdir("a", os.ModePerm)
if err != nil {
println(err)
}
}
func CreateDirAll(){
err := os.MkdirAll("a/b/c", os.ModePerm)
if err != nil {
println(err)
}
}
func RemoveFile(){
err := os.Remove("a.txt")
if err != nil {
println(err)
}
}
func RemoveFileAll(){
err := os.RemoveAll("a")
if err != nil {
println(err)
}
}
//获取和修改工作目录
func GetWd(){
dir, err := os.Getwd()
if err != nil {
println(err)
}else {
println(dir)
}
}
func TempDir(){
dir := os.TempDir()
println(dir)
}
//重命名
func rename() {
err := os.Rename("a.txt", "b.txt")
if err != nil {
println(err)
}
}
//打开、关闭文件
func Open() {
f, err := os.Open("b.txt")
if err != nil {
fmt.Printf("err:%v\n", err)
}else{
fmt.Printf("f:%v\n", f)
f.Close()
}
}
func OpenFile(){
f, err := os.OpenFile("a.txt", os.O_RDWR|os.O_CREATE, 755)
if err != nil {
println(err)
}else {
println(f.Name())
f.Close()
}
}
//读文件
//这个read没反应,也没报错,效果还没实现
func ReadOps(){
f, _:= os.Open("b.txt")
for{
buf := make([]byte, 10)
n, err := f.Read(buf)
if err != io.EOF {
break
}
fmt.Printf("n:%v\n", n)
fmt.Printf("string(buf):%v\n", string(buf))
}
f.Close()
}
func ReadAt(){
f, _ := os.Open("b.txt")
buf := make([]byte, 10)
n, err := f.ReadAt(buf, 3)
if err != nil {
println(err)
}
fmt.Printf("n:%v\n", n)
fmt.Printf("buf:%v\n", string(buf))
}
func ReadDir(){
dir, _ := os.ReadDir("a")
for _, v := range dir {
fmt.Printf("v.IdDir():%v\n", v.IsDir())
fmt.Printf("v.Name():%v\n", v.Name())
}
}
func ReadSeek(){
f, _ := os.Open("b.txt")
f.Seek(3,0)
buf:= make([]byte, 20)
n, _ := f.Read(buf)
fmt.Printf("n:%v\n", n)
fmt.Printf("String(buf):%v\n", string(buf))
f.Close()
}
//写文件
func Write(){
f, _ := os.OpenFile("c.txt",os.O_RDWR|os.O_APPEND, 0775)
f.Write([]byte("!!!!!!"))
f.Close()
}
func WriteString(){
f, _ := os.OpenFile("c.txt",os.O_RDWR|os.O_APPEND, 0775)
f.WriteString("that is good")
f.Close()
}
func WriteAt(){
f, _ := os.OpenFile("c.txt",os.O_RDWR, 0775)
f.WriteAt([]byte("_this way_"), 3)
f.Close()
}
func main(){
WriteAt()
}
注意点
- 读取的结果很多时候都需要进行转化,
string()
f.Name()
- …
- 文件操作
- 打开就可以与创建合并,但注意打开若进入循环就会反复从头开始
- 写入和只读,可以对位置、内容操作
- 权限不是很懂???,0775,0666,755
- OpenFile具有很大的自由度,可以有各种命令嵌入
os.O_RDWR
表示可读写os.O_CREATE
表示若没有这个文件就创建os.O_TRUNC
表示覆盖同名旧文件的意思os.O_APPEND
表示在旧文件上追加新内容
技巧
- if有智能按键
- 变量/值.Print——生成打印语句
- 变注释
- 值.var——创建了它,并且有返回err(是根据函数返回值自动创建吗?)
- pkgm直接创建main包声明和main函数(没成功)
?2.进程相关的操作
- 设置进程的属性(一个进程,一个父进程)
- 开始一个新进程(???这种格式,没见过)
- 通过进程id查找进程
- 杀死进程→等待进程退出,返回进程状态(告知已退出)
???方法里,嵌入一个匿名函数?
以上代码的结果
package main
import (
"os"
"fmt"
)
func main(){
//获取当前进程
fmt.Printf("os.Getpid():%v\n", os.Getpid())
fmt.Printf("os.Getppid():%v\n", os.Getppid())
//设置新的进程属性
attr := &os.ProcAttr{
Files: []*os.File{os.stdin, os.Stdout, os.Stderr},
Env: os.Environ(),
}
p, err := os.StartProcess("C:\\Windows\\System32\\notepad.exe", []string{"C:\\Windows\\System32\\notepad.exe"
}, "D:\\a.txt", attr)
}
3、获取命令行参数
通过os.Args获得用户传递的参数,注意所有的参数,都是以字符串的方式进行传递(也就是说,os.Args
是一个字符串型切片[]string
)
注意:
- 切片第一位往往是执行命令
- 空格不算进切片
实例1
实例2
用go build运行文件,形成可执行程序main.exe,再输入参数