杂项(3)读写文件
c++ 对文件提供了流方式读写, 一般工作中都会简单地封装个读写函数,方便使用。
文件写入函数
/*
定义一个函数WriteFile,它接受四个参数:
path:要写入的文件的路径。
data:要写入的数据。
size:要写入的数据的大小(字节数)。
append:一个布尔值,表示是否在文件末尾追加数据。默认值为false,表示不追加。
*/
bool WriteFile(const char* path, const char* data, int size, bool append = false) {
if (data == nullptr || size <= 0) {
return false;
}
std::ios_base::openmode mode = append ? std::ios_base::app : std::ios_base::out;
mode |= std::ios_base::binary;
std::ofstream fp(path, mode);
if (!fp.is_open()) {
return false;
}
if (fp.write(data, size).fail()) {
fp.close();
return false;
}
return true;
}
文件读取函数
/*
定义一个函数ReadFile,它接受四个参数:
path:要读取的文件的路径。
data:一个引用,用于保存读取的数据。
size:要读取的数据的大小(字节数),默认值为-1,表示读取整个文件。
offset:从文件的哪个偏移量开始读取,默认值为0,表示从文件开始处读取。
*/
bool ReadFile(const char* path, std::string& data, int size = -1, int64_t offset = 0) {
std::ifstream fp(path, std::ios_base::in | std::ios_base::binary);
if (!fp.is_open()) {
return false;
}
int64_t fileSize = fp.seekg(0, std::ios_base::end).tellg();
if (size == -1) {
size = (int)(fileSize - offset);
}
if (offset > fileSize
|| (size > 128 * 1024 * 1024)
|| (fileSize - offset < (int64_t)size)
|| offset != fp.seekg(offset, std::ios_base::beg).tellg()
) {
fp.close();
return false;
}
data.clear();
char buf[4096] = { 0 };
do {
int per = (size > 4096) ? 4096 : size;
if (per != fp.read(buf, per).gcount()) {
fp.close();
return false;
}
data.append(buf, per);
size -= per;
} while (size > 0);
fp.close();
return true;
}
结合下, 以一个工具类封装:
#ifndef __XX_TOOL_H__
#define __XX_TOOL_H__
#include <stdint.h>
#include <string>
#include <iostream>
#include <fstream>
#ifdef _WIN32
#include <windows.h>
#else
#include <time.h>
#include <unistd.h>
#endif
class XXTool {
public:
//读取文件
static bool ReadFile(const char* path, std::string& data, int size = -1, int64_t offset = 0) {
std::ifstream fp(path, std::ios_base::in | std::ios_base::binary);
if (!fp.is_open()) {
return false;
}
int64_t fileSize = fp.seekg(0, std::ios_base::end).tellg();
if (size == -1) {
size = (int)(fileSize - offset);
}
if (offset > fileSize
|| (size > 128 * 1024 * 1024)
|| (fileSize - offset < (int64_t)size)
|| offset != fp.seekg(offset, std::ios_base::beg).tellg()
) {
fp.close();
return false;
}
data.clear();
char buf[4096] = { 0 };
do {
int per = (size > 4096) ? 4096 : size;
if (per != fp.read(buf, per).gcount()) {
fp.close();
return false;
}
data.append(buf, per);
size -= per;
} while (size > 0);
fp.close();
return true;
}
//写入文件
static bool WriteFile(const char* path, const char* data, int size, bool append = false) {
if (data == nullptr || size <= 0) {
return false;
}
std::ios_base::openmode mode = append ? std::ios_base::app : std::ios_base::out;
mode |= std::ios_base::binary;
std::ofstream fp(path, mode);
if (!fp.is_open()) {
return false;
}
if (fp.write(data, size).fail()) {
fp.close();
return false;
}
return true;
}
static bool WriteFile(const char* path, const std::string& data, bool append = false) {
return WriteFile(path, data.c_str(), data.size(), append);
}
//获取程序路径
static bool GetSelfPath(std::string& path) {
char tmp[4096] = { 0 };
#ifdef _WIN32
if (0 >= GetModuleFileNameA(NULL, tmp, 4096)) {
return false;
}
#else
if (0 >= readlink("/proc/self/exe", tmp, 4096)) {
return false;
}
#endif
path = tmp;
return true;
}
//注意: 字符编码问题, windows下返回的是ansi, linux下返回的是utf8
//没有达到工业强度,应该统一处理成utf8,再输出.
//windows下路径也应该转化成linux形式: c:\abc\a.exe => c:/abc/a.exe
//系统运行时间
static int64_t GetTickCount() {
#ifdef _WIN32
return ::GetTickCount64();
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (int64_t)(ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
#endif
}
};
#endif
示例:
#include "XXTool.h"
#include <iostream>
int main(){
std::string data("helloworld");
XXTool::WriteFile("abc.txt", data);
std::string data2;
XXTool::ReadFile("abc.txt", data2);
if (data == data2) {
std::cout<<"ok"<<std::endl;
}
return 0;
}