c++文件持续读写
通常我们读取文件的过程是直接从将整个文件内容磁盘读取到内存,但是有时候文件很大,由于内存有限甚至文件大小以及超过了可用内存大小,这时候我们就需要一段一段的持续读/写
类实现(这里是一个可持续读取的实现,可持续写入就append模式多写几次啦 😃
// 大文件读取
namespace io {
class bigfi {
private:
int fd;//目标文件描述符
off_t size;//目标文件实际大小
size_t buffer_size;//预留缓冲区大小
off_t pos;//当前偏移位置,以文件开头为起点
char* mem;//缓冲区
ismove=false;
public:
bigfi(const char* filepath, size_t max_buffer_size = 1 << 20, off_t offs = 0)
: buffer_size(max_buffer_size)
, pos(offs)
, mem(new char[buffer_size])
{
struct stat st;
if (stat(filepath, &st) < 0) throw std::logic_error("get file status failed");
size = st.st_size;
fd = open(filepath, O_RDONLY);
if (fd < 0) throw std::logic_error("open file failed");
if (pos > 0) lseek(fd, pos, SEEK_SET);
memset(mem, 0, buffer_size);
if (read(fd, mem, buffer_size) < 0) throw std::logic_error("read file failed");
}
bigfi(const bigfi&& src)
: fd(src.fd)
, mem(src.mem)
, size(src.size)
, pos(src.pos)
, buffer_size(src.buffer_size)
{
src.ismove = true;
}
const char* c_str() const
{
return mem;
}
const size_t length() const
{
return size;
}
bigfi& operator+=(int newpos)//模拟c字符串指针计算,带边界检查
{
if (size <= newpos + pos | pos < -newpos) throw std::logic_error("index out of range");
memset(mem, 0, buffer_size);
pos += newpos;
lseek(fd, pos, SEEK_SET);
if (read(fd, mem, buffer_size) < 0) throw std::logic_error("read file failed");
return *this;
}
bigfi& operator++()
{
*this += 1;
return *this;
}
~bigfi()
{
if (!ismove) {
delete[] mem;
close(fd);
}
}
};
}
使用案例
static const char infile[] = "test.txt";
int main()
{
io::bigfi bf(infile, 5);
printf("length %zu\n", bf.length());
std::cout << bf.c_str() << std::endl;
while (true) {//这里我们设为无限循环是为了触发边界检查
bf += 1;
std::cout << bf.c_str() << std::endl;
}
}
测试结果
每次都会向后移一位,并保持最大5个字节长