实现BuffereFileWriter
分析
想要实现此功能
1、首先,需要一个结构体BuffereFIleWriter,用于保存缓冲区的数据和文件句柄。
2、在结构体中,我们需要定义一个缓冲区数组和一个文件句柄指针。
3、接着,我们需要实现一个构造函数 NewBufferedFileWriter,它接受一个文件句柄作为参数,并返回一个 BufferedFileWriter 的指针。
4、在构造函数中,我们需要初始化结构体的字段,包括缓冲区和文件句柄。
5、接下来,我们需要实现 Write 方法,用于将数据写入缓冲区。
6、在 Write 方法中,我们需要判断数据是否超过缓冲区的大小,如果超过,则直接将数据写入文件;如果没有超过,则将数据复制到缓冲区,并更新缓冲区的位置。
7、我们还需要实现一个 Flush 方法,用于将缓冲区中的数据写入文件并清空缓冲区。
8、转换,让string类型的都可以写入。字符串转切片函数WriteString
9、最后,我们可以编写一个测试函数,调用 NewBufferedFileWriter 创建一个 BufferedFileWriter,并使用 Write 方法写入数据,然后调用 Flush 方法将数据写入文件。
那我们来实践一下步骤吧。
创建结构体 BufferedFileWriter
我们需要一个结构体来保存缓冲区的数据和文件句柄
type BufferedFileWriter struct {
//定义字段 ,缓冲区数组 以及文件指针
buffer [1024]byte
endPos int // 已写入缓冲区的数据长度
fileHandler *os.File
}
讲解: 在这一步,我们创建了一个结构体
BufferedFileWriter它包含了一个大小为 1024 的字节数组作为缓冲区,一个记录已写入缓冲区数据长度的字段
endPos,以及一个指向文件句柄的指针fileHandler。
实现构造函数 NewBufferedFileWriter
描述: 我们需要实现一个构造函数,该函数接受一个文件句柄作为参数,并返回一个 BufferedFileWriter 的实例。
//创建构造函数
func NewBufferedFileWriter(fd *os.File) *BufferedFileWriter {
//初始化字段
return &BufferedFileWriter{
fileHandler: fd,
}
}
讲解: 在这一步,我们定义了一个构造函数
NewBufferedFileWriter它接受一个文件句柄
fd作为参数,并返回一个新的BufferedFileWriter实例,初始化其中的fileHandler字段为传入的文件句柄。
实现 Write 方法
描述: 我们需要实现一个 Write 方法,用于将数据写入缓冲区。如果数据大小超过缓冲区大小,则直接写入文件;否则,将数据复制到缓冲区并更新位置。
//第五步实现writer方法
func (writer *BufferedFileWriter) Write(content []byte) {
// 有点意思是结构体的方法前面的括号就是 哪个类型的结构体
//判断缓冲区大小
if len(content) >= 1024 {
writer.fileHandler.Write(content)
} else {
if writer.endPos+len(content) >= 1024 {
writer.Flush()
writer.Write(content)
} else {
copy(writer.buffer[writer.endPos:], content)
writer.endPos += len(content)
}
}
}
讲解: 在这一步,我们实现了
Write方法。首先,我们检查传入的数据是否超过缓冲区大小,如果超过,则直接写入文件。
如果没有超过,我们检查是否将数据写入缓冲区后,缓冲区已满,如果已满则调用
Flush方法,然后递归调用Write方法。
否则,我们使用
copy函数将数据复制到缓冲区中,并更新endPos。
实现 Flush 方法
描述: 我们需要实现一个 Flush 方法,用于将缓冲区中的数据写入文件并清空缓冲区。
//创建Flush用于 将缓冲区写入文件
func (writer *BufferedFileWriter) Flush() {
if writer.endPos > 0 {
writer.fileHandler.Write(writer.buffer[0:writer.endPos])
// 这个数组[:] 加 " : " 是把数组转化为切片 // 真正写入磁盘
writer.endPos = 0
}
}
讲解: 在这一步,我们实现了
Flush方法。如果缓冲区中有数据(endPos > 0),我们将缓冲区中的数据写入文件,然后清空缓冲区并将endPos重置为0。
实现 WriteString 方法
描述: 我们实现一个 WriteString 方法,该方法将字符串转换为切片,并调用 Write 方法进行写入。
//字符串转为切片
func (writer *BufferedFileWriter) WriteString(content string) {
writer.Write([]byte(content))
}
讲解: 在这一步,我们实现了
WriteString方法,它将输入的字符串转换为字节数组,并调用已实现的Write方法进行写入。
编写测试函数
描述: 最后,我们可以编写一个测试函数,以验证 BufferedFileWriter 是否正常工作。在测试函数中,我们创建一个文件句柄,使用 NewBufferedFileWriter 创建一个 BufferedFileWriter 实例,多次使用 WriteString 方法写入数据,最后使用 Flush 方法将数据写入文件。
//编写测试函数
func testBufferWriter() {
fout, err := os.OpenFile("output.txt", os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
return
}
defer fout.Close()
writer := NewBufferedFileWriter(fout)
for i := 0; i < 500; i++ {
writer.WriteString("0123456789\n")
}
writer.Flush()
}
讲解: 在这一步,我们编写了一个名为
testBufferWriter的测试函数。
在该函数中,我们创建一个文件句柄,使用
NewBufferedFileWriter创建一个BufferedFileWriter实例,并使用WriteString方法多次写入数据。
最后,我们使用
Flush方法将剩余的数据写入文件。这个测试函数可以验证BufferedFileWriter是否正常工作,能够高效地写入大量数据。
总结
到这里,我们已经成功地实现了一个缓冲文件写入的功能。这个 BufferedFileWriter 结构体可以在写入大量数据时提高性能,减少频繁的磁盘写入操作,从而更加高效地操作文件。
完整代码实现
package main
import (
"fmt"
"os"
)
// 第一步创建结构体
type BufferedFileWriter struct {
// 第二部定义字段 ,缓冲区数组 以及文件指针
buffer [1024]byte
endPos int //已写入缓冲区的数据长度
fileHandler *os.File
}
// 第三步创建构造函数
func NewBufferedFileWriter(fd *os.File) *BufferedFileWriter {
// 第四步 初始化字段
return &BufferedFileWriter{
fileHandler: fd,
}
}
// 第七步 创建Flush用于 将缓冲区写入文件
func (writer *BufferedFileWriter) Flush() {
if writer.endPos > 0 {
writer.fileHandler.Write(writer.buffer[0:writer.endPos]) // 这个数组[:] 加 " : " 是把数组转化为切片
fmt.Println("真正写入磁盘")
writer.endPos = 0
}
}
// 第五步实现writer方法
func (writer *BufferedFileWriter) Write(content []byte) { // 有点意思是结构体的方法前面的括号就是 哪个类型的结构体
// 第六步判断缓冲区大小
if len(content) >= 1024 {
writer.fileHandler.Write(content)
} else {
if writer.endPos+len(content) >= 1024 {
writer.Flush()
writer.Write(content)
} else {
copy(writer.buffer[writer.endPos:], content)
writer.endPos += len(content)
}
}
}
// 第八步 字符串转为切片
func (writer *BufferedFileWriter) WriteString(content string) {
writer.Write([]byte(content))
}
// 第九步编写测试函数
func testBufferWriter() {
fout, err := os.OpenFile("zcy.txt", os.O_CREATE|os.O_TRUNC, os.ModePerm)
if err != nil {
return
}
defer fout.Close()
writer := NewBufferedFileWriter(fout)
for i := 0; i < 500; i++ {
writer.WriteString("0123456789\n")
}
}