**我们在进行文件的相关操作时,往往不明白在哪种情况下使用那些函数,每次查百度导致开发效率低下,我这里列举一些方便以后查询:**
* **读取整个文件**
* **从文件的某个位置开始,进行读、写n个字符操作**
* **拷贝文件到另一个文件,或拷贝文件的前面n个字符到另一个文件**
* **将多个文件汇聚到一个文件来进行操作**
* **将多个字符同时写到多个文件中**
* **获取文件的相关信息(名称、大小、是否为文件夹、文件权限、创建、最后访问、最后修改时间、绝对路径、重命名操作、是否存在)**
* **获取文件夹的所有文件**
* **将一个文件的内容写入到另一个文件中,可控制写入内容**
**1、读取整个文件**
```go
func test1() {
f, err := os.Open("d:/a.txt")
if err != nil {
panic(err)
}
defer f.Close()
// 读取整个文件 1. 使用stat获取文件长度,再开辟空间,将数据写到变量中,输出到终端
fi, err := f.Stat()
if err != nil {
panic(err)
}
b := make([]byte, fi.Size())
if _, err = f.Read(b); err != nil {
panic(err)
}
os.Stdout.Write(b)
// 读取整个文件 2. 直接使用ioutil的ReadAll函数
b, err = ioutil.ReadAll(f)
if err != nil {
panic(err)
}
os.Stdout.Write(b)
}
```
**2、从文件的某个位置开始,进行读、写n个字符操作**
```go
func test2() {
f, err := os.OpenFile("d:/a.txt", os.O_RDWR, 0755)
if err != nil {
panic(err)
}
defer f.Close()
// 设置操作文件的当前位置为倒数第10个字符
if _, err := f.Seek(-10, io.SeekEnd); err != nil {
panic(err)
}
// 从当前位置读取5个字符
b := make([]byte, 10)
if _, err := f.ReadAt(b, 5); err != nil {
panic(err)
}
os.Stdout.Write(b)
// 从当前位置写5个字符(相当于覆盖文件的最后5个字符)
f.WriteAt(b, 5)
}
```
**3、拷贝文件到另一个文件,或拷贝文件的前面n个字符到另一个文件**
```go
func test3() {
f1, err := os.Open("d:/a.txt")
if err != nil {
panic(err)
}
defer f1.Close()
f2, err := os.OpenFile("d:/b.txt", os.O_CREATE | os.O_RDWR, 0755)
if err != nil {
panic(err)
}
defer f2.Close()
// 拷贝f1的所有字符到f2的前面,如果f2的size比f1大,那么后面的字符依然保留
// 如果要在f2进行追加,使用os.O_APPEND
if _, err := io.Copy(f2, f1); err != nil {
panic(err)
}
// 拷贝f1的n个字符到f2的前面
if _, err := io.CopyN(f2, f1, 10); err != nil {
panic(err)
}
}
```
**4、 将多个文件汇聚到一个文件来进行操作**
```go
func test4() {
f1, err := os.Open("d:/a.txt")
if err != nil {
panic(err)
}
defer f1.Close()
f2, err := os.Open("d:/b.txt")
if err != nil {
panic(err)
}
defer f2.Close()
// 将2个file.Reade合并成一个Reader
r := io.MultiReader(f1, f2)
// 轮询读取reader中的数据
buf := make([]byte, 10)
data := make([]byte, 0, 128)
for n, err := r.Read(buf); err != io.EOF; n, err = r.Read(buf) {
if err != nil {
panic(err)
}
data = append(data, buf[:n]...)
}
os.Stdout.Write(data)
}
```
**5、将多个字符同时写到多个文件中**
```go
func test5() {
f, err := os.OpenFile("d:/a.txt", os.O_CREATE | os.O_RDWR | os.O_APPEND, 0755)
if err != nil {
panic(err)
}
defer f.Close()
// 将file和标准输出合并到一个writer中
w := io.MultiWriter(f, os.Stdout)
// 每次write都会写到w包含的所有writer中
w.Write([]byte("helloworld"))
w.Write([]byte("nihaoshijie"))
}
```
**6、获取文件的相关信息(名称、大小、是否为文件夹、文件权限、创建、最后访问、最后修改时间、绝对路径、重命名操作、是否存在)**
```go
func test6() {
f, err := os.OpenFile("d:/a.txt", os.O_CREATE|os.O_RDWR, 0755)
if err != nil {
panic(err)
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
panic(err)
}
// 名称、大小、是否为文件夹、详细信息、文件权限、最后修改时间
fmt.Printf("name: %s\n", fi.Name())
fmt.Printf("size: %d\n", fi.Size())
fmt.Printf("isDir: %t\n", fi.IsDir())
fmt.Printf("sys: %v\n", fi.Sys())
fmt.Printf("mode: %o\n", fi.Mode())
fmt.Printf("modTime: %s\n", fi.ModTime())
// 获取详细信息中的文件创建时间,具体详细信息见Stat_t结构体(windows和linux不同)
// windows
// CreatetionTime uint32
// LastAccessTime uint32
if reflect.ValueOf(fi.Sys()).Elem().FieldByName("CreatetionTime").IsValid() {
ctim := reflect.ValueOf(fi.Sys()).Elem().FieldByName("CreatetionTime").Field(0).Uint()
fmt.Printf("ctim: %d\n", ctim)
}
// 获取文件的绝对路径
dir, err := filepath.Abs("d:/a.txt")
if err != nil {
panic(err)
}
fmt.Printf("dir: %s\n", dir)
// 判断文件是否不存在
if _, err := os.Stat("d:/c.txt"); err != nil {
if os.IsNotExist(err) {
fmt.Println("file not exist")
} else {
panic(err)
}
}
// 重命名文件或文件夹(要有权限/文件已关闭)
if err := os.Rename("d:/b.txt", "d:/d.txt"); err != nil {
panic(err)
}
}
```
**7、获取文件夹的所有文件**
```go
func test7() {
files, err := ioutil.ReadDir("d:/")
if err != nil {
panic(err)
}
// 获取文件夹下所有文件和文件夹的相关信息
for _, f := range files {
fmt.Printf("name: %s, size: %d, isDir: %t\n", f.Name(), f.Size(), f.IsDir())
}
}
```
**8、将一个文件的内容写入到另一个文件中,可控制写入内容**
```go
func test8() {
f1, err := os.Open("d:/a.txt")
if err != nil {
panic(err)
}
defer f1.Close()
f2, err := os.OpenFile("d:/b.txt", os.O_CREATE | os.O_RDWR | os.O_APPEND, 0755)
if err != nil {
panic(err)
}
defer f2.Close()
// 设置将从f1中读到的写到f2中
r := io.TeeReader(f1, f2)
// 循环5次读取f1前面100个字符,每次读取后会自动写到f2中
for i := 0; i < 5; i++ {
f1.Seek(0, io.SeekStart)
if _, err := r.Read(make([]byte, 100)); err != nil {
if err == io.EOF{
return
}
panic(err)
}
time.Sleep(time.Second)
}
}
```
案例来源于: 《go语言标准库》
https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter01/01.1.html
有疑问加站长微信联系(非本文作者))