52、Go语言基础 - 文件系统 - 文件操作

作者: 温新

分类: 【Go基础】

阅读: 279

时间: 2023-12-05 00:44:02

hi,我是温新

创建文件

os.Mkdir用于创建一个新的目录。其格式如下:

func Create(name string) (file *File, err Error)

参数解释:

name:一个字符串,指定要创建或打开的文件的路径。如果文件已存在,将会被截断。

案例如下:

package main

import (
	"fmt"
	"os"
)

func main() {
	// 指定要创建的文件路径
	filePath := "mydir1/my_new_file.txt"

	// 使用 os.Create 创建文件
	file, err := os.Create(filePath)
	if err != nil {
		// 如果创建文件时出错,打印错误信息
		fmt.Printf("无法创建文件:%v\n", err)
		return
	}

	defer file.Close()
	// 如果文件创建成功,打印成功消息
	fmt.Printf("文件 %s 创建成功\n", filePath)
}

文件或文件夹状态

os.Stat 用于获取文件或目录信息的函数。其格式如下:

func Stat(name string)(Fileinfo, error)

参数解释:

name:一个字符串,指定要获取信息的文件或目录的路径。

案例如下:

package main

import (
	"fmt"
	"os"
)

func main() {
	// 指定要获取信息的文件或目录路径
	path := "mydir1/my_new_file.txt"

	// 使用 os.Stat 获取文件或目录信息
	fileInfo, err := os.Stat(path)
	if err != nil {
		// 如果获取信息时出错,打印错误信息
		fmt.Printf("无法获取文件信息:%v\n", err)
		return
	}

	// 打印文件或目录信息
	fmt.Printf("文件或目录名称: %s\n", fileInfo.Name())
	fmt.Printf("大小(字节): %d\n", fileInfo.Size())
	fmt.Printf("是否为目录: %t\n", fileInfo.IsDir())
	fmt.Printf("权限: %s\n", fileInfo.Mode())
	fmt.Printf("最后修改时间: %v\n", fileInfo.ModTime())
}

输出结果:

文件或目录名称: my_new_file.txt
大小(字节): 0
是否为目录: false
权限: -rw-rw-rw-
最后修改时间: 2023-10-19 00:44:55.7445089 +0800 CST

NewFile

os.NewFile用于创建一个 *os.File 类型的文件对象,它可以用于包装已存在的文件描述符。其格式如下:

func NewFile(fd uintptr, name string) *File
  • fd:要包装的文件描述符,类型为 uintptr。这通常是操作系统提供的文件描述符,例如由 os.Open 或其他系统调用返回的。
  • name:文件的名称。这是一个字符串,通常用于标识文件。该参数在文件对象的 Name() 方法中可以获取。

注意:使用 os.NewFile 可能需要小心,因为它使你有可能在 Go 中执行低级别的文件操作,应谨慎使用。

案例如下:

package main

import (
	"fmt"
	"os"
)

func main() {
	// 打开一个文件,文件中要有内容
	file, err := os.Open("mydir1/my_new_file.txt")
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}
	defer file.Close()

	// 获取文件的文件描述符
	fileDescriptor := file.Fd()

	// 使用 os.NewFile 包装文件描述符,创建一个新的文件对象
	newFile := os.NewFile(fileDescriptor, "./new_file.txt")

	// 检查是否有错误
	if newFile == nil {
		fmt.Println("Error creating new file object")
		return
	}

	// 使用新的文件对象执行文件操作
	data := make([]byte, 100)
	n, err := newFile.Read(data)
	if err != nil {
		fmt.Println("Error reading file:", err)
		return
	}

	fmt.Printf("Read %d bytes: %s\n", n, string(data[:n]))
}

文件重命名

os.Rename 用于重命名文件或移动文件。其格式如下:

func Rename(oldpath, newpath string) error

参数解释:

  • oldpath:表示要重命名或移动的文件的原始路径。
  • newpath:表示文件的新路径或新名称。

案例如下:

package main

import (
	"fmt"
	"os"
)

func main() {
	// 原始文件名
	oldPath := "mydir1/my_new_file.txt"
	// 新文件名
	newPath := "mydir1/redme.txt"

	// 重命名文件
	err := os.Rename(oldPath, newPath)
	// 检查是否有错误
	if err != nil {
		fmt.Println("Error renaming file:", err)
		return
	}
	fmt.Println("File renamed successfully!")

	// 检查文件是否存在
	_, err = os.Stat(newPath)
	if err == nil {
		fmt.Println("New file exists.")
	} else if os.IsNotExist(err) {
		fmt.Println("New file does not exist.")
	} else {
		fmt.Println("Error checking new file:", err)
	}
}

移动文件

移动文件同样是使用 os.Rename。如果是移到其他目录,则需要该目录存在。

package main

import (
	"fmt"
	"os"
)

func main() {
	// 原始文件路径
	oldPath := "mydir1/redme.txt"
	// 新文件路径,这里是移动文件到另一个目录
	newPath := "mydir1/test/redme.txt"
	// 移动文件
	err := os.Rename(oldPath, newPath)
	// 检查是否有错误
	if err != nil {
		fmt.Println("Error moving file:", err)
		return
	}

	fmt.Println("File moved successfully!")

	// 检查原始文件是否存在(已被移走)
	_, err = os.Stat(oldPath)
	if err != nil && os.IsNotExist(err) {
		fmt.Println("Original file no longer exists.")
	} else if err != nil {
		fmt.Println("Error checking original file:", err)
	}

	// 检查新文件是否存在
	_, err = os.Stat(newPath)
	if err == nil {
		fmt.Println("New file exists in the destination.")
	} else if os.IsNotExist(err) {
		fmt.Println("New file does not exist in the destination.")
	} else {
		fmt.Println("Error checking new file in the destination:", err)
	}
}

打开与关闭文件

**os.Open 用于打开文件。**其格式如下:

func Open(name string) (*File, error)

参数解释:

  • name(参数):表示要打开的文件的路径。
  • 返回值:
    • *File:表示已打开文件的指针,可以用于读取或写入文件。
    • error:如果打开文件时发生错误,将返回一个描述错误的值,否则为nil

**os.OpenFile 用于打开文件。**其格式如下:

func OpenFile(name string, flag int, perm FileMode) (*File, error)

参数含义:

  • name:要打开的文件的名称或路径。
  • flag:打开文件的标志,指定文件的打开方式,如读、写、追加等。
  • perm:创建文件时的权限位(仅在创建文件时使用),通常表示文件的读、写、执行权限。

name:要打开的文件名 flag:打开文件的模式。 模式有以下几种:

模式 含义
os.O_WRONLY 只写
os.O_CREATE 创建文件
os.O_RDONLY 只读
os.O_RDWR 读写
os.O_TRUNC 清空
os.O_APPEND 追加

perm:文件权限,一个八进制数。r(读)04,w(写)02,x(执行)01。

**File.Close 方法关闭文件句柄。**其格式如下 :

func (f *File) Close() error

参数含义:

fFile 类型的文件对象,表示要关闭的文件。

os.Open案例

package main

import (
	"fmt"
	"os"
)

func main() {
	// 打开文件以进行读取操作
	file, err := os.Open("mydir1/test.txt")
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}

	// 关闭 file
	defer file.Close()

	// 读取文件内容
	data := make([]byte, 1024)
	n, err := file.Read(data)
	if err != nil {
		fmt.Println("Error reading file:", err)
		return
	}
	fmt.Printf("Read %d bytes: %s\n", n, string(data[:n]))
}

os.OpenFile 案例

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	// 打开源文件
	sourcePath := "mydir1/test.txt"
	sourceFile, err := os.OpenFile(sourcePath, os.O_RDONLY, 0644)
	if err != nil {
		fmt.Println("无法打开源文件:", err)
		return
	}
	// 确保在函数结束时关闭文件
	defer sourceFile.Close()
	// 创建或打开目标文件
	destPath := "mydir1/destination.txt"
	destFile, err := os.OpenFile(destPath, os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("无法创建或打开目标文件:", err)
		return
	}
	// 确保在函数结束时关闭文件
	defer destFile.Close()

	// 将源文件的内容复制到目标文件
	_, err = io.Copy(destFile, sourceFile)
	if err != nil {
		fmt.Println("文件移动失败:", err)
		return
	}

	fmt.Println("文件复制成功!")
}

Open 与 OpenFile 的区别如下:

os.Open 用于简单的只读文件操作,而 os.OpenFile 更加灵活,适用于各种文件操作,包括读取、写入和创建文件。

文件写入

文件写入有如下几种方式:

函数 功能
Write 写入 byte 类型的信息到文件
WriteAt 在指定位置开始写入 byte 类型的信息
WriteString 写入 string 信息到文件

os.Write函数

func (f *File) Write(b []byte) (n int, err error)
  • f(参数):表示要写入的文件的指针。
  • b(参数):表示要写入文件的字节切片。
  • 返回值:
    • n:表示写入的字节数。
    • err:如果写入文件时出现错误,将返回一个描述错误的值,否则为nil

os.WriteString函数

func (f *File) WriteString(s string) (n int, err error)
  • f(参数):表示要写入的文件的指针。
  • s(参数):表示要写入文件的字符串。
  • 返回值:
    • n:表示写入的字节数。
    • err:如果写入文件时出现错误,将返回一个描述错误的值,否则为nil

案例如下:

package main

import (
	"fmt"
	"os"
)

func main() {
	// 创建或打开目标文件
	destPath := "mydir1/lucy.txt"
	destFile, err := os.OpenFile(destPath, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println("无法创建或打开目标文件:", err)
		return
	}
	// 确保在函数结束时关闭文件
	defer destFile.Close()

	// 使用 os.Write 写入字节数据
	data := []byte("我叫王美丽 ")
	n, err := destFile.Write(data)
	if err != nil {
		fmt.Println("写入文件失败:", err)
		return
	}
	fmt.Printf("使用 Write 写入了%d字节的数据\n", n)

	// 使用 os.WriteString 写入字符串数据
	strData := "我正在学习 Golang"
	n, err = destFile.WriteString(strData)
	if err != nil {
		fmt.Println("写入文件失败:", err)
		return
	}
	fmt.Printf("使用 WriteString 写入了%d字节的数据\n", n)

	fmt.Println("数据写入文件成功!")
}

文件读取

Read 函数

func (f *File) Read(b []byte) (n int, err error)
  • f(参数):表示要读取的文件的指针。
  • b(参数):表示用于接收读取数据的字节切片。
  • 返回值:
    • n:表示读取的字节数。
    • err:如果读取文件时出现错误,将返回一个描述错误的值,否则为nil
package main

import (
	"fmt"
	"os"
)

func main() {
	sourcePath := "mydir1/jianjia.txt"
	sourceFile, err := os.Open(sourcePath)
	if err != nil {
		fmt.Println("无法打开源文件:", err)
		return
	}

	defer sourceFile.Close()
	// 使用 os.Read 读取数据
	data := make([]byte, 128) // 创建一个字节切片用于接收数据
	n, err := sourceFile.Read(data)
	if err != nil {
		fmt.Println("读取文件失败:", err)
		return
	}
	fmt.Printf("读取了%d字节的数据\n", n)
	fmt.Println("读取的数据:", string(data[:n]))
	fmt.Println("数据读取成功!")
}

这个案例中读取了 128 字节的数据,并没有完全读取所有内容。

ReadAll 函数

func ReadAll(r io.Reader) ([]byte, error)
  • r(参数):表示要从中读取数据的io.Reader接口,通常是文件或其他数据源。
  • 返回值:
    • []byte:包含从io.Reader中读取的所有数据的字节切片。
    • error:如果读取数据时出现错误,将返回一个描述错误的值,否则为nil
package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	sourcePath := "mydir1/jianjia.txt"
	sourceFile, err := os.Open(sourcePath)
	if err != nil {
		fmt.Println("无法打开源文件:", err)
		return
	}
	defer sourceFile.Close()

	// 使用 os.ReadAll 读取所有数据
	allData, err := io.ReadAll(sourceFile)
	if err != nil {
		fmt.Println("读取文件失败:", err)
		return
	}
	
	fmt.Println("读取的数据:", string(allData))
	fmt.Println("数据读取成功!")
}

这个示例演示了如何使用os.ReadAll函数从文件中读取所有数据,并将其以字符串形式输出。这对于一次性读取整个文件内容非常方便。

os.Reados.ReadAll的区别:

  • os.Read是一个较低级别的文件读取函数,用于读取文件的指定数量字节。
  • os.ReadAll是一个更高级别的函数,用于从io.Reader接口中读取所有可用的数据,然后将其返回为一个字节切片。
  • os.Read需要你显式指定要读取的字节数,而os.ReadAll会读取直到遇到文件末尾或io.Reader关闭。
  • 通常情况下,os.ReadAll更适用于读取整个文件的内容,而os.Read更适用于读取文件的一部分或按照固定大小的块进行读取。

删除文件

os.Remove 文件文件或目录 。

func Remove(name string) error

参数解释

  • name(参数):表示要删除的文件或目录的路径。
  • 返回值:如果删除成功,os.Remove函数返回nil;如果删除时出现错误,将返回一个描述错误的值
package main

import (
	"fmt"
	"os"
)

func main() {
	// 删除文件
	filePath := "mydir1/destination.txt"
	err := os.Remove(filePath)
	if err != nil {
		fmt.Printf("无法删除文件 %s: %v\n", filePath, err)
		return
	}
	fmt.Printf("成功删除文件 %s\n", filePath)
}
请登录后再评论