Loading... ## 前置知识 本节主要是对标准文件IO进行一些简单的封装。 ## 代码实现 ### 项目结构 ``` |-bitcask |--fio//新增 |---file_io.go //新增 |---io_manager.go//新增 |--data |---log_record.go |--index |---btree.go |---index.go ``` ### IO接口定义 * 新增文件:`fio/io_manager.go` ``` package fio const FilePermCode = 0644 // IOManager 文件IO管理器 type IOManager interface { // Read 从文件指定位置读取数据 Read(b []byte, offset int64) (int, error) // Write 写入数据到文件指定位置 Write(b []byte) (int, error) // Sync 将存放在内存缓冲区的数据持久化到磁盘中 Sync() error // Close 关闭文件 Close() error } ``` ### IO接口实现 以下代码就是对标准文件IO进行简单的封装,方法的相应注释也都一并复制了,虽然是英文单但都很简单,应该不难看懂。 * 新增:`fio/file_io.go` ``` package fio import "os" // FileIO 对标准文件系统的一些接口进行简单封装 type FileIO struct { //系统文件描述符 fd *os.File } // NewFileIO 初始化标准文件IO func NewFileIO(filename string) (*FileIO, error) { fd, err := os.OpenFile( filename, // 以读写模式的模式打开文件,如果文件不存在则创建, // 如果文件已存在则以追加的方式进行写入 os.O_RDWR|os.O_CREATE|os.O_APPEND, FilePermCode) if err != nil { return nil, err } return &FileIO{fd: fd}, nil } // Read 从文件指定位置读取数据 func (fio *FileIO) Read(b []byte, offset int64) (int, error) { // ReadAt reads len(b) bytes from the File starting at byte offset off. // It returns the number of bytes read and the error, if any. // ReadAt always returns a non-nil error when n < len(b). // At end of file, that error is io.EOF. return fio.fd.ReadAt(b, offset) } // Write 写入数据到文件指定位置 func (fio *FileIO) Write(b []byte) (int, error) { // Write writes len(b) bytes to the File. // It returns the number of bytes written and an error, if any. // Write returns a non-nil error when n != len(b). return fio.fd.Write(b) } // Sync 将存放在内存缓冲区的数据持久化到磁盘中 func (fio *FileIO) Sync() error { // Sync commits the current contents of the file to stable storage. // Typically, this means flushing the file system's in-memory copy // of recently written data to disk. return fio.fd.Sync() } // Close 关闭文件 func (fio *FileIO) Close() error { return fio.fd.Close() } ``` ### 单元测试 - 工具函数,用于删除测试文件 ``` func destroyFile(path string) { if err := os.RemoveAll(path); err != nil{ panic(err) } } ``` - FileIO ``` func TestNewFileIOManager(t *testing.T) { path := filepath.Join("/tmp", "test.data") io, err := NewFileIO(path) cerr := io.Close() assert.Nil(t, cerr) defer destroyFile(path) assert.Nil(t, err) assert.NotNil(t, io) } ``` - Write ``` func TestFileIO_Writer(t *testing.T) { path := filepath.Join("/tmp", "test.data") io, err := NewFileIO(path) defer destroyFile(path) assert.Nil(t, err) assert.NotNil(t, io) n, err := io.Write([]byte("hello")) assert.Nil(t, err) assert.Equal(t, 5, n) n, err = io.Write([]byte("world")) assert.Nil(t, err) assert.Equal(t, 5, n) cerr := io.Close() assert.Nil(t, cerr) } ``` - Read ``` func TestFileIO_Read(t *testing.T) { path := filepath.Join("/tmp", "test.data") io, err := NewFileIO(path) defer destroyFile(path) assert.Nil(t, err) assert.NotNil(t, io) n, err := io.Write([]byte("hello")) assert.Nil(t, err) assert.Equal(t, 5, n) n, err = io.Write([]byte("world")) assert.Nil(t, err) assert.Equal(t, 5, n) b := make([]byte, 5) n, err = io.Read(b, 0) assert.Nil(t, err) assert.Equal(t, 5, n) assert.Equal(t, b, []byte("hello")) b = make([]byte, 5) n, err = io.Read(b, 5) assert.Nil(t, err) assert.Equal(t, 5, n) assert.Equal(t, b, []byte("world")) cerr := io.Close() assert.Nil(t, cerr) } ``` - Sync ``` func TestFileIO_Sync(t *testing.T) { path := filepath.Join("/tmp", "test.data") io, err := NewFileIO(path) defer destroyFile(path) assert.Nil(t, err) assert.NotNil(t, io) err = io.Sync() assert.Nil(t, err) cerr := io.Close() assert.Nil(t, cerr) } ``` - Close ``` func TestFileIO_Close(t *testing.T) { path := filepath.Join("/tmp", "test.data") io, err := NewFileIO(path) defer destroyFile(path) assert.Nil(t, err) assert.NotNil(t, io) err = io.Close() assert.Nil(t, err) } ``` 最后修改:2024 年 01 月 20 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,请随意赞赏
1 条评论
想想你的文章写的特别好