目录操作
创建名称为name的目录,权限设置是perm,例如0777
func Mkdir(name string, perm FileMode) error
根据path创建多级子目录,例如test/test1/test2。
func MkdirAll(path string, perm FileMode) error
删除名称为name的目录,当目录下有文件或者其他目录时会出错
func Remove(name string) error
根据path删除多级子目录,如果path是单个名称,那么该目录下的子目录全部删除。
func RemoveAll(path string) error
eg:
package main
import (
"fmt"
"os"
)
func main() {
os.Mkdir("test", 0777)
os.MkdirAll("test/test1/test2", 0777)
err := os.Remove("test")
if err != nil {
fmt.Println(err)
}
os.RemoveAll("test")
}
创建文件
根据提供的文件名创建新的文件,返回一个文件对象,默认权限是0666的文件,返回的文件对象是可读写的。
func Create(name string) (file *File, err Error)
根据文件描述符创建相应的文件,返回一个文件对象
func NewFile(fd uintptr, name string) *File
读取文件
open
该方法打开一个名称为name的文件,但是是只读方式,内部实现其实调用了OpenFile。
func Open(name string) (file *File, err Error)
为了防止文件忘记关闭,我们通常使用defer注册文件关闭语句。eg:
package main
import (
"fmt"
"os"
)
func main() {
// 只读方式打开程序同级目录下的word.txt
file, err := os.Open("word.txt")
if err != nil {
fmt.Println( err)
return
}
// 关闭文件
defer file.Close()
}
OpenFile
函数签名如下
func OpenFile(name string, flag int, perm FileMode) (*File, error)
OpenFile函数的第二个参数是文件的打开模式:
const (
// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.
O_RDONLY int = syscall.O_RDONLY // 只读模式
O_WRONLY int = syscall.O_WRONLY //只写模式
O_RDWR int = syscall.O_RDWR // 读写混合模式
// The remaining values may be or'ed in to control behavior.
O_APPEND int = syscall.O_APPEND // 写模式的时候将数据附加到文件末尾
O_CREATE int = syscall.O_CREAT // 文件如果不存在就新建
O_EXCL int = syscall.O_EXCL // 和 O_CREATE模式一起使用, 文件必须不存在
O_SYNC int = syscall.O_SYNC //打开文件用于同步 I/O.
O_TRUNC int = syscall.O_TRUNC // 打开文件时清空文件
)
前面三种是文件打开模式,后面五种是打开文件之后相应的操作模式;前面三个你只能选择一个,后面可以多选,中间用”|”隔开。
OpenFile函数的第三个参数perm
是文件的权限,跟linux文件权限一致,一个八进制数。r(读)04,w(写)02,x(执行)01。
r ——> 004
w ——> 002
x ——> 001
// Open opens the named file for reading. If successful, methods on
// the returned file can be used for reading; the associated file
// descriptor has mode O_RDONLY.
// If there is an error, it will be of type *PathError.
func Open(name string) (*File, error) {
return OpenFile(name, O_RDONLY, 0)
}
// Create creates or truncates the named file. If the file already exists,
// it is truncated. If the file does not exist, it is created with mode 0666
// (before umask). If successful, methods on the returned File can
// be used for I/O; the associated file descriptor has mode O_RDWR.
// If there is an error, it will be of type *PathError.
func Create(name string) (*File, error) {
return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
open 函数和Create 底层都是调用的OpenFile函数
// OpenFile is the generalized open call; most users will use Open
// or Create instead. It opens the named file with specified flag
// (O_RDONLY etc.). If the file does not exist, and the O_CREATE flag
// is passed, it is created with mode perm (before umask). If successful,
// methods on the returned File can be used for I/O.
// If there is an error, it will be of type *PathError.
func OpenFile(name string, flag int, perm FileMode) (*File, error)
Read
读取数据到b中,最大可以读取一个1G 文件
func (file *File) Read(b []byte) (n int, err Error)
eg:
package main
import (
"fmt"
"os"
)
func main() {
fileName := "testFile"
currFile,err:=os.Create(fileName)
if err!= nil {
fmt.Println(err,currFile);
}
currFile.WriteString("hello world\n")
currFile.Write([]byte("hello go\n"))
currFile,err = os.Open(fileName);
defer currFile.Close()
buf := make([]byte,1024)
for {
n,_:=currFile.Read(buf)
if 0==n {
break
}
os.Stdout.Write(buf[:n])
}
}
从off开始读取数据到b中
func (file *File) ReadAt(b []byte, off int64) (n int, err Error)
准备测试文件word.txt
白日依山尽
黄河入海流
欲穷千里目
更上一层楼
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("word.txt")
if err != nil {
fmt.Println(err)
}
defer file.Close()
buf := make([]byte, 1024)
offset := 0
for {
n, err := file.ReadAt(buf, int64(offset))
if len(buf) > 0 {
fmt.Println(string(buf))
}
if err != nil {
fmt.Println(err)
break
}
offset = offset + n
}
}
字节推荐选择2的n次方数数值,不然在中文混合中偏移量就是个坑
bufio.NewReader
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("word.txt")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
reader := bufio.NewReader(file)
for {
line, err := reader.ReadString('\n') //按行读取
if err == io.EOF {
fmt.Println("文件读完了")
break
}
if err != nil {
fmt.Println("read file failed, err:", err)
break
}
fmt.Print(line)
}
}
也可以直接调用ReadLine()函数
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("word.txt")
if err != nil {
fmt.Println(err)
}
defer file.Close()
reader := bufio.NewReader(file)
for {
line, _, err := reader.ReadLine()
if err == io.EOF {
break
}
if err != nil {
fmt.Println(err)
break
}
fmt.Println(string(line))
}
}
ioutil.Readxxx
io/ioutil
包的ReadFile
方法能够读取完整的文件,只需要将文件名作为参数传入。
package main
import (
"fmt"
"io/ioutil"
)
func main() {
content, err := ioutil.ReadFile("word.txt")
if err != nil {
fmt.Println("read file failed, err:", err)
return
}
fmt.Println(string(content))
}
ReadAll 文件输入流
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
file, err := os.Open("word.txt")
if err != nil {
fmt.Println("read file failed, err:", err)
return
}
defer file.Close()
content, err := ioutil.ReadAll(file)
if err != nil {
fmt.Println("read content failed, err:", err)
return
}
fmt.Println(string(content))
}
文件写入
OpenFile()
os.OpenFile()
函数不仅可以指定模式打开文件读文件,也可以指定响应的写模式从而实现文件写入功能。
os.O_RDWR|os.O_CREATE : 文件不存在会新建文件,文件如果存在,会从文件开始处用新内容覆盖原始内容,(如果新内容只有5个字符,原始内容有10个,那么只有开始5个是新内容,后面5个还是以前的内容)
os.O_RDWR|os.O_APPEND : 本次写入的值会在文件末尾进行append操作,不会覆盖以前的内容。
os.O_RDWR|os.O_TRUNC : 打开文件的时候先清空文件。
Writexx
Write
写入byte类型的信息到文件
func (file *File) Write(b []byte) (n int, err Error)
WriteAt
在指定位置开始写入byte类型的信息
func (file *File) WriteAt(b []byte, off int64) (n int, err Error)
WriteString
写入string信息到文件
func (file *File) WriteString(s string) (ret int, err Error)
bufio.NewWriter
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
file, err := os.OpenFile("word.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("open file failed, err:", err)
return
}
defer file.Close()
writer := bufio.NewWriter(file)
for i := 0; i < 10; i++ {
writer.WriteString("hello"+strconv.Itoa(i)+"\n") //将数据先写入缓存
}
writer.Flush() //将缓存中的内容写入文件
}
ioutil.WriteFile
创建文件,如果存在删除 重新写入
package main
import (
"fmt"
"io/ioutil"
)
func main() {
str := "hello word"
err := ioutil.WriteFile("word.txt", []byte(str), 0644)
if err != nil {
fmt.Println("write file failed, err:", err)
return
}
}
删除文件
Go语言里面删除文件和删除文件夹是同一个函数, 调用该函数就可以删除文件名为name的文件
func Remove(name string) Error
// Discard 是一个 io.Writer 接口,调用它的 Write 方法将不做任何事情
// 并且始终成功返回。
var Discard io.Writer = devNull(0)
// ReadAll 读取 r 中的所有数据,返回读取的数据和遇到的错误。
// 如果读取成功,则 err 返回 nil,而不是 EOF,因为 ReadAll 定义为读取
// 所有数据,所以不会把 EOF 当做错误处理。
func ReadAll(r io.Reader) ([]byte, error)
// ReadFile 读取文件中的所有数据,返回读取的数据和遇到的错误。
// 如果读取成功,则 err 返回 nil,而不是 EOF
func ReadFile(filename string) ([]byte, error)
// WriteFile 向文件中写入数据,写入前会清空文件。
// 如果文件不存在,则会以指定的权限创建该文件。
// 返回遇到的错误。
func WriteFile(filename string, data []byte, perm os.FileMode) error
// ReadDir 读取指定目录中的所有目录和文件(不包括子目录)。
// 返回读取到的文件信息列表和遇到的错误,列表是经过排序的。
func ReadDir(dirname string) ([]os.FileInfo, error)
// NopCloser 将 r 包装为一个 ReadCloser 类型,但 Close 方法不做任何事情。
func NopCloser(r io.Reader) io.ReadCloser
// TempFile 在 dir 目录中创建一个以 prefix 为前缀的临时文件,并将其以读
// 写模式打开。返回创建的文件对象和遇到的错误。
// 如果 dir 为空,则在默认的临时目录中创建文件(参见 os.TempDir),多次
// 调用会创建不同的临时文件,调用者可以通过 f.Name() 获取文件的完整路径。
// 调用本函数所创建的临时文件,应该由调用者自己删除。
func TempFile(dir, prefix string) (f *os.File, err error)
// TempDir 功能同 TempFile,只不过创建的是目录,返回目录的完整路径。
func TempDir(dir, prefix string) (name string, err error)
文件压缩
package main
import (
"archive/zip"
"fmt"
"io"
"log"
"os"
)
type file struct {
Name, Body string
}
func main() {
// List of Files to Zip
var files = []file{
{"readme.txt", "This archive contains some text files."},
{"gopher.txt", "Gopher names:\nGeorge\nGeoffrey\nGonzo"},
{"todo.txt", "Get animal handling licence.\nWrite more examples."},
}
for _, file := range files {
f, err := os.Create(file.Name)
if err != nil {
log.Fatal(err)
}
_, err = f.Write([]byte(file.Body))
if err != nil {
log.Fatal(err)
}
}
output := "dome.zip"
if err := ZipFiles(output, files); err != nil {
panic(err)
}
fmt.Println("Zipped File:", output)
}
// ZipFiles compresses one or many files into a single zip archive file.
// Param 1: filename is the output zip file's name.
// Param 2: files is a list of files to add to the zip.
func ZipFiles(filename string, files []file) error {
newZipFile, err := os.Create(filename)
if err != nil {
return err
}
defer newZipFile.Close()
zipWriter := zip.NewWriter(newZipFile)
defer zipWriter.Close()
// Add files to zip
for _, file := range files {
if err = AddFileToZip(zipWriter, file.Name); err != nil {
return err
}
}
return nil
}
func AddFileToZip(zipWriter *zip.Writer, filename string) error {
fileToZip, err := os.Open(filename)
if err != nil {
return err
}
defer fileToZip.Close()
// Get the file information
info, err := fileToZip.Stat()
if err != nil {
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
return err
}
// Using FileInfoHeader() above only uses the basename of the file. If we want
// to preserve the folder structure we can overwrite this with the full path.
header.Name = filename
// Change to deflate to gain better compression
// see http://golang.org/pkg/archive/zip/#pkg-constants
header.Method = zip.Deflate
writer, err := zipWriter.CreateHeader(header)
if err != nil {
return err
}
_, err = io.Copy(writer, fileToZip)
return err
}