1. Go语言中的文件操作函数
在Go语言中,文件操作函数都被封装在标准库的`os`和`io/ioutil`包中,可以用于文件的创建、读取、写入等操作。下面我们来介绍一些常用的文件操作函数。
1.1 创建文件
要创建一个文件,可以使用`os.Create()`函数,如果文件不存在,则会创建该文件;如果文件已经存在,则会清空该文件的内容。代码如下:
file, err := os.Create("test.txt")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
file.WriteString("Hello, world!")
在这段代码中,我们调用`os.Create()`函数创建一个名为`test.txt`的文件,并将其返回给变量`file`。`defer file.Close()`语句表示在函数返回之前关闭`file`,从而确保文件被正确关闭。
1.2 打开文件
要打开一个文件,可以使用`os.Open()`函数,该函数返回一个文件对象。代码如下:
file, err := os.Open("test.txt")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
data := make([]byte, 100)
n, err := file.Read(data)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Read %d bytes: %s\n", n, data[:n])
在这段代码中,我们调用`os.Open()`函数打开一个名为`test.txt`的文件,并将其返回给变量`file`。`defer file.Close()`语句表示在函数返回之前关闭`file`,从而确保文件被正确关闭。接着,我们创建一个切片`data`来存储读取的数据,调用`file.Read(data)`函数将文件中的数据读取到切片`data`中,返回读取的字节数`n`和可能发生的错误`err`。最后,我们打印读取的字节数和读取到的数据。
1.3 写入文件
要将数据写入到文件中,可以使用`file.Write()`或`file.WriteString()`函数。代码如下:
file, err := os.OpenFile("test.txt", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
file.Write([]byte("Hello, universe!\n"))
file.WriteString("How are you?\n")
在这段代码中,我们调用`os.OpenFile()`函数打开一个名为`test.txt`的文件,并将其返回给变量`file`。`defer file.Close()`语句表示在函数返回之前关闭`file`,从而确保文件被正确关闭。`os.O_APPEND|os.O_WRONLY`表示以追加写入的方式打开文件,`0644`表示文件的权限。`file.Write()`和`file.WriteString()`函数分别用来写入数据到文件中。
2. 文件的压缩和加密
在实际应用中,文件的压缩和加密都是非常常见的操作。下面我们分别介绍文件的压缩和加密的方法。
2.1 文件的压缩
要对文件进行压缩,可以使用标准库的`compress/gzip`包或`compress/zlib`包。这里以`compress/gzip`包为例,代码如下:
srcFile, err := os.Open("test.txt")
if err != nil {
fmt.Println(err)
return
}
defer srcFile.Close()
dstFile, err := os.Create("test.txt.gz")
if err != nil {
fmt.Println(err)
return
}
defer dstFile.Close()
gzWriter := gzip.NewWriter(dstFile)
defer gzWriter.Close()
if _, err := io.Copy(gzWriter, srcFile); err != nil {
fmt.Println(err)
return
}
在这段代码中,我们首先打开名为`test.txt`的文件,并将其返回给变量`srcFile`。接着,我们创建名为`test.txt.gz`的压缩文件,并将其返回给变量`dstFile`。`gzip.NewWriter()`函数用来创建一个`gzip.Writer`对象,它可以将数据压缩并写入到文件中。`io.Copy()`函数用来将`srcFile`中的数据复制到`gzWriter`中,从而实现对文件的压缩。
2.2 文件的加密
要对文件进行加密,可以使用标准库的`crypto/aes`包和`crypto/cipher`包。这里以AES加密算法为例,代码如下:
srcFile, err := os.Open("test.txt")
if err != nil {
fmt.Println(err)
return
}
defer srcFile.Close()
dstFile, err := os.Create("test.txt.aes")
if err != nil {
fmt.Println(err)
return
}
defer dstFile.Close()
key := []byte("passw0rdpassw0rd")
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println(err)
return
}
iv := make([]byte, aes.BlockSize)
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
fmt.Println(err)
return
}
stream := cipher.NewCFBEncrypter(block, iv)
writer := &cipher.StreamWriter{S: stream, W: dstFile}
if _, err := io.Copy(writer, srcFile); err != nil {
fmt.Println(err)
return
}
if err := writer.Close(); err != nil {
fmt.Println(err)
return
}
if _, err := dstFile.Write(iv); err != nil {
fmt.Println(err)
return
}
在这段代码中,我们首先打开名为`test.txt`的文件,并将其返回给变量`srcFile`。接着,我们创建名为`test.txt.aes`的加密文件,并将其返回给变量`dstFile`。`aes.NewCipher()`函数用来创建一个AES加密器,`cipher.NewCFBEncrypter()`函数用来创建一个CFB模式的加密器,并将其返回给变量`stream`。`cipher.StreamWriter`可以将数据写入到加密文件中。
3. 文件的上传和下载
在实际应用中,文件的上传和下载也是非常常见的操作。下面我们分别介绍文件的上传和下载的方法。
3.1 文件的上传
要上传文件,可以使用标准库的`net/http`包。代码如下:
func uploadFile(w http.ResponseWriter, r *http.Request) {
file, handler, err := r.FormFile("file")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
fmt.Fprintf(w, "Upload File: %s\n", handler.Filename)
dstFile, err := os.Create(handler.Filename)
if err != nil {
fmt.Println(err)
return
}
defer dstFile.Close()
if _, err := io.Copy(dstFile, file); err != nil {
fmt.Println(err)
return
}
}
func main() {
http.HandleFunc("/upload", uploadFile)
http.ListenAndServe(":8080", nil)
}
在这段代码中,我们首先定义了一个`uploadFile`函数,它接收一个`http.ResponseWriter`对象和一个`http.Request`对象,用来处理文件上传请求。`r.FormFile("file")`用来获取上传的文件对象,`handler.Filename`表示上传的文件名。接着,我们创建名为`handler.Filename`的文件,并将其返回给变量`dstFile`。最后,我们用`io.Copy()`函数将上传的文件复制到`dstFile`中。
3.2 文件的下载
要下载文件,可以使用标准库的`net/http`包。代码如下:
func downloadFile(w http.ResponseWriter, r *http.Request) {
fileName := r.URL.Query().Get("file")
if fileName == "" {
fmt.Fprintf(w, "Please provide a file name")
return
}
file, err := os.Open(fileName)
if err != nil {
fmt.Fprintf(w, "Error opening file: %s", err.Error())
return
}
defer file.Close()
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Transfer-Encoding", "binary")
if _, err := io.Copy(w, file); err != nil {
fmt.Fprintf(w, "Error downloading file: %s", err.Error())
return
}
}
func main() {
http.HandleFunc("/download", downloadFile)
http.ListenAndServe(":8080", nil)
}
在这段代码中,我们首先定义了一个`downloadFile`函数,它接收一个`http.ResponseWriter`对象和一个`http.Request`对象,用来处理文件下载请求。`r.URL.Query().Get("file")`用来获取要下载的文件名。接着,我们打开名为`fileName`的文件,并将其返回给变量`file`。我们通过设置`w.Header()`来设置响应头信息,即告知浏览器返回的文件名和类型。最后,我们用`io.Copy()`函数将文件内容写入`http.ResponseWriter`对象中,从而实现文件的下载。
4. 文件的解压缩
要对压缩过的文件进行解压缩,可以使用标准库的`compress/gzip`包或`compress/zlib`包。这里以`compress/gzip`包为例,代码如下:
srcFile, err := os.Open("test.txt.gz")
if err != nil {
fmt.Println(err)
return
}
defer srcFile.Close()
dstFile, err := os.Create("test.txt")
if err != nil {
fmt.Println(err)
return
}
defer dstFile.Close()
gzReader, err := gzip.NewReader(srcFile)
if err != nil {
fmt.Println(err)
return
}
defer gzReader.Close()
if _, err := io.Copy(dstFile, gzReader); err != nil {
fmt.Println(err)
return
}
在这段代码中,我们首先打开名为`test.txt.gz`的压缩文件,并将其返回给变量`srcFile`。接着,我们创建名为`test.txt`的文件,并将其返回给变量`dstFile`。`gzip.NewReader()`函数用来创建一个`gzip.Reader`对象,它可以读取并解压缩数据。`io.Copy()`函数用来将`gzReader`中的数据复制到`dstFile`中,从而实现对文件的解压缩。