1 文件分类和为什么需要文件
1.1 文件分类和为什么需要文件
-
1)设备文件:
屏幕(标准输出设备) fmt.Println() 从标准输出设备写内容。
键盘(标准输入设备) fmt.Scan() 从标准输入设备读取内容。 -
2)磁盘文件,放在存储设备上的文件:
1、文本文件 以记事本打开,能看到内容(不是乱码)。
2、二进制文件 以记事本打开 ,能看到内容(是乱码)。 -
3)为什么需要文件?
1、内存掉电丢失,程序结束,内存中的内容消失。
2、文件放磁盘,程序结束,文件还是存在。
2 文件常用操作接口介绍和使用
1、创建文件
法1: 推荐用法
func Create(name string) (file *File, err Error)
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
法2:
func NewFile(fd uintptr, name string) *File
根据文件描述符创建相应的文件,返回一个文件对象
2、打开文件
法1:
func Open(name string) (file *File, err Error)
该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile。
法2: 推荐用法
func OpenFile(name string, flag int, perm uint32) (file *File, err Error)
打开名称为name的文件,flag是打开的方式,只读、读写等,perm是权限
3、写文件
法1:
func (file *File) Write(b []byte) (n int, err Error)
写入byte类型的信息到文件
法2:
func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
在指定位置开始写入byte类型的信息
法3:
func (file *File) WriteString(s string) (ret int, err Error)
写入string信息到文件
4、读文件
法1:
func (file *File) Read(b []byte) (n int, err Error)
读取数据到b中
法2:
func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
从off开始读取数据到b中
5、删除文件
func Remove(name string) Error
调用该函数就可以删除文件名为name的文件
3 标准设备文件的使用
这里只是简单写一下。
package main
import (
"fmt"
"os"
)
func main() {
//os.Stdout.Close() //关闭后,无法输出
//fmt.Println("are u ok?") //往标准输出设备(屏幕)写内容
// 1. 标准输出
//标准设备文件(os.Stdout),默认已经打开,用户可以直接使用
//os.Stdout
os.Stdout.WriteString("are u ok?\n")
//os.Stdin.Close() //关闭后,无法输入
// 2. 标准输入
var a int
fmt.Println("请输入a: ")
fmt.Scan(&a) //从标准输入设备中读取内容,放在a中
fmt.Println("a = ", a)
}
4 WriteString的使用
package main
import (
"fmt"
"os"
)
func WriteFile(path string) {
// 1. 新建文件
f, err := os.Create(path)
if err != nil {
fmt.Println("err = ", err)
return
}
// 2. 使用完毕,需要关闭文件
defer f.Close()
// 3. 往文件中写入内容
var buf string
for i := 0; i < 10; i++ {
//"i = 1\n", 这个字符串存储在buf中
buf = fmt.Sprintf("i = %d\n", i)
//fmt.Println("buf = ", buf)
n, err := f.WriteString(buf)
if err != nil {
fmt.Println("err = ", err)
}
fmt.Println("n = ", n)
}
}
func main() {
path := "./demo.txt"
WriteFile(path)
}
生成一个demo.txt:
5 Read的使用
package main
import (
"fmt"
"io"
"os"
)
func WriteFile(path string) {
f, err := os.Create(path)
if err != nil {
fmt.Println("err = ", err)
return
}
//使用完毕,需要关闭文件
defer f.Close()
var buf string
for i := 0; i < 10; i++ {
//"i = 1\n", 这个字符串存储在buf中
buf = fmt.Sprintf("i = %d\n", i)
//fmt.Println("buf = ", buf)
n, err := f.WriteString(buf)
if err != nil {
fmt.Println("err = ", err)
}
fmt.Println("n = ", n)
}
}
func ReadFile(path string) {
f, err := os.Open(path)
if err != nil {
fmt.Println("err = ", err)
return
}
//关闭文件
defer f.Close()
buf := make([]byte, 1024*2) //2k大小
//n代表从文件读取内容的长度
n, err1 := f.Read(buf)
if err1 != nil && err1 != io.EOF { //文件出错,同时没有到结尾
fmt.Println("err1 = ", err1)
return
}
fmt.Println(string(buf[:n]))
}
func main() {
path := "./demo.txt"
//写
//WriteFile(path)
//读
ReadFile(path)
}
将上面写入的内容读取出来:
6 借助bufio实现按行读取内容
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func WriteFile(path string) {
//打开文件,新建文件
f, err := os.Create(path)
if err != nil {
fmt.Println("err = ", err)
return
}
//使用完毕,需要关闭文件
defer f.Close()
var buf string
for i := 0; i < 10; i++ {
//"i = 1\n", 这个字符串存储在buf中
buf = fmt.Sprintf("i = %d\n", i)
//fmt.Println("buf = ", buf)
n, err := f.WriteString(buf)
if err != nil {
fmt.Println("err = ", err)
}
fmt.Println("n = ", n)
}
}
func ReadFile(path string) {
//打开文件
f, err := os.Open(path)
if err != nil {
fmt.Println("err = ", err)
return
}
//关闭文件
defer f.Close()
buf := make([]byte, 1024*2) //2k大小
//n代表从文件读取内容的长度
n, err1 := f.Read(buf)
if err1 != nil && err1 != io.EOF { //文件出错,同时没有到结尾
fmt.Println("err1 = ", err1)
return
}
fmt.Println("buf = ", string(buf[:n]))
}
//每次读取一行
func ReadFileLine(path string) {
//打开文件
f, err := os.Open(path)
if err != nil {
fmt.Println("err = ", err)
return
}
//关闭文件
defer f.Close()
//新建一个缓冲区,把内容先放在缓冲区
r := bufio.NewReader(f)
for {
//遇到'\n'结束读取, 但是会连通'\n'本身也会读取进入。但不会因为中间有\n而停止,这个是挺好的。
buf, err := r.ReadBytes('\n')
if err != nil {
if err == io.EOF { //文件已经结束
break
}
fmt.Println("err = ", err)
}
fmt.Printf("buf = #%s#\n", string(buf))
}
}
func main() {
path := "./demo.txt"
//WriteFile(path)
//ReadFile(path)
ReadFileLine(path)
}
将WriteString的内容按行读取出来,但是会连通\n本身也会读取:
但是不会因一行的中间有\n而停止读取,例如修改demo.txt:
可以看到同样可以读取到\n。
7 拷贝文件案例
package main
import (
"fmt"
"io"
"os"
)
func main() {
list := os.Args //获取命令行参数
if len(list) != 3 {
fmt.Println("usage: xxx srcFile dstFile")
return
}
srcFileName := list[1]
drcFileName := list[2]
if srcFileName == drcFileName {
fmt.Println("源文件和目的文件名字不能相同")
return
}
//只读方式打开源文件
sF, err1 := os.Open(srcFileName)
if err1 != nil {
fmt.Println("err1 = ", err1)
return
}
//新建目的文件
dF, err2 := os.Create(drcFileName)
if err2 != nil {
fmt.Println("err2 = ", err2)
return
}
//操作完毕,需要关闭文件
defer sF.Close()
defer dF.Close()
//核心处理,从源文件读取内容,往目的文件写,读多少写多少
buf := make([]byte, 4*1024) //4k大小临时缓冲区
for {
n, err := sF.Read(buf) //从源文件读取内容
if err != nil {
if err == io.EOF{//文件读取完毕
break
}
fmt.Println("err = ", err)
}
//往目的文件写,读多少写多少
dF.Write(buf[:n])
}
}
首先生成可执行程序:
#进入对应盘符
d:
#cd到对应目录
cd D:\xxx\xxx
#build生成可执行程序
go build test.go
#最后执行拷贝命令
test.exe demo.txt yyy.txt
yyy的内容与demo.txt是一样的,图片、视频的拷贝也是没问题的。
注意:需要使用cmd去build,不要使用bash,我试过了不行,只能cmd去build。否则会执行拷贝命令时会报参数丢失。