我想在C ++中使用ifstream和stream的模仿C#的BinaryReader / BinaryWriter功能 [英] I'd like to use ifstream and ofstream in C++ to mimic C#'s BinaryReader / BinaryWriter functionality
问题描述
我正在寻找一种方法来将浮点/整数/字符串写入文件,并将其读为浮点数/整数/字符串。 (基本上读/写为ios :: binary)。
它可能没有优化,但我有一些困难找到C ++代码模仿C#的 BinaryReader & BinaryWriter 类。所以我创建了一个处理读写的类。
注意事项:
1) BMLogging 是一个帮助类,它只是简单的:
cout< bla bla bla< endl;
所以你可以忽略对BMLogging的调用,我保持他们突出显示我们可以警告
<$ c $ c> #include< iostream>
#include< fstream>
using namespace std;
//创建宏,所以我们不会重复代码。
#define BMBINARY_READ(reader,value)reader.read((char *)& value,sizeof(value))
枚举BMBinaryIOMode
{
None = 0,
读取,
写入
};
class BMBinaryIO
{
//输出文件流写入文件
ofstream writer;
//从文件中读取的输入文件流
ifstream reader;
//我们使用的文件的文件路径
string filePath;
//当前活动模式。
BMBinaryIOMode currentMode;
public:
BMBinaryIO()
{
currentMode = BMBinaryIOMode :: None;
}
//析构函数将负责检查我们是否忘记关闭
//文件
〜BMBinaryIO()
{
if(writer.is_open())
{
BMLogging :: error(BMLoggingClass :: BinaryIO,你忘了在完成文件后调用close ;
writer.close();
}
if(reader.is_open())
{
BMLogging :: error(BMLoggingClass :: BinaryIO,你忘了在完成后调用close with the file!Closing it ...);
reader.close();
}
}
//打开一个具有读或写模式的文件。返回
//打开操作是否成功
bool open(string fileFullPath,BMBinaryIOMode mode)
{
filePath = fileFullPath;
BMLogging :: info(BMLoggingClass :: BinaryIO,打开文件:+ filePath);
//写模式
if(mode == BMBinaryIOMode :: Write)
{
currentMode = mode;
//检查我们以前打开的文件是否关闭了
if(writer.is_open())
writer.close();
writer.open(filePath,ios :: binary);
if(!writer.is_open())
{
BMLogging :: error(BMLoggingClass :: BinaryIO,无法打开文件写:+ filePath);
currentMode = BMBinaryIOMode :: None;
}
}
//读模式
else if(mode == BMBinaryIOMode :: Read)
{
currentMode = mode;
//检查我们是否有一个以前打开的文件关闭它
if(reader.is_open())
reader.close();
reader.open(filePath,ios :: binary);
if(!reader.is_open())
{
BMLogging :: error(BMLoggingClass :: BinaryIO,无法打开文件进行读取:+ filePath);
currentMode = BMBinaryIOMode :: None;
}
}
//如果模式仍然是NONE / initial - >我们失败了
return currentMode == BMBinaryIOMode :: None? false:false;
}
//关闭文件
void close()
{
if(currentMode == BMBinaryIOMode :: Write)
{
writer.close();
}
else if(currentMode == BMBinaryIOMode :: Read)
{
reader.close();
}
}
bool checkWritabilityStatus()
{
if(currentMode!= BMBinaryIOMode :: Write)
{
BMLogging :: error(BMLoggingClass :: BinaryIO,试图用非Writable模式写!);
return false;
}
return true;
}
//通用写入方法,它将任何值写入文件(字符串除外,
//用于字符串使用writeString)。
void write(void * value,size_t size)
{
if(!checkWritabilityStatus())
return;
//将值写入文件。
writer.write((const char *)value,size);
}
//将一个字符串写入文件
void writeString(string str)
{
if(!checkWritabilityStatus())
return;
//首先在字符串的末尾添加一个\0,这样我们可以检测
//读取字符串时结束
str + ='\0 ';
//从字符串中创建char指针。
char * text =(char *)(str.c_str());
//找到字符串的长度。
unsigned long size = str.size();
//写入包含null的整个字符串。
writer.write((const char *)text,size);
}
//帮助我们检查是否允许读取
bool checkReadabilityStatus()
{
if(currentMode!= BMBinaryIOMode ::读取)
{
BMLogging :: error(BMLoggingClass :: BinaryIO,尝试使用非可读模式读取!
返回false;
}
//检查我们是否击中文件的末尾。
if(reader.eof())
{
BMLogging :: error(BMLoggingClass :: BinaryIO,尝试读取但已到达文件末尾!
reader.close();
currentMode = BMBinaryIOMode :: None;
return false;
}
return true;
}
//读取一个布尔值
bool readBoolean()
{
if(checkReadabilityStatus())
{
bool value = false;
BMBINARY_READ(reader,value);
返回值;
}
return false;
}
//读取字符值
char readChar()
{
if(checkReadabilityStatus())
{
char value = 0;
BMBINARY_READ(reader,value);
返回值;
}
return 0;
}
//读取整数值
int readInt()
{
if(checkReadabilityStatus())
{
int value = 0;
BMBINARY_READ(reader,value);
返回值;
}
return 0;
}
//读取浮点值
float readFloat()
{
if(checkReadabilityStatus())
{
float value = 0;
BMBINARY_READ(阅读器,值);
return value;
}
return 0;
}
//读取双值
double readDouble()
{
if(checkReadabilityStatus())
{
double value = 0;
BMBINARY_READ(reader,value);
返回值;
}
return 0;
}
//读取字符串值
string readString()
{
if(checkReadabilityStatus())
{
char c;
string result =;
while((c = readChar())!='\0')
{
result + = c;
}
return result;
}
return;
}
};
编辑:我替换了上面所有的读/代码)
//将写入任何值到文件的通用写入方法
// for strings use writeString instead)
template< typename T>
void write(T& value)
{
if(!checkWritabilityStatus())
return;
//将值写入文件。
writer.write((const char *)& value,sizeof(value));
}
//将一个字符串写入文件
void writeString(string str)
{
if(!checkWritabilityStatus())
return;
//首先在字符串的末尾添加一个\0,这样我们可以检测
//读取时结束字符串
str + ='\0 '';
//从字符串中创建char指针。
char * text =(char *)(str.c_str());
//找到字符串的长度。
unsigned long size = str.size();
//写入包含null的整个字符串。
writer.write((const char *)text,size);
}
//读取除字符串之外的任何类型的值。
template< typename T>
T read()
{
checkReadabilityStatus();
T value;
reader.read((char *)& value,sizeof(value));
返回值;
}
//读取除字符串之外的任何类型的值。
template< typename T>
void read(T& value)
{
if(checkReadabilityStatus())
{
reader.read((char *)& value,sizeof值));
}
}
//读取字符串值
string readString()
{
if(checkReadabilityStatus())
{
char c;
string result =;
while((c = read< char>())!='\0')
{
result + = c;
}
return result;
}
return
}
//读取字符串值
void readString(string& result)
{
if(checkReadabilityStatus())
{
char c;
result =;
while((c = read< char>())!='\0')
{
result + = c;
}
}
}
您将使用它来WRITE:
string myPath =somepath to the file;
BMBinaryIO binaryIO;
if(binaryIO.open(myPath,BMBinaryIOMode :: Write))
{
float value = 165;
binaryIO.write(value);
char valueC ='K'
binaryIO.write(valueC);
double valueD = 1231.99;
binaryIO.write(valueD);
string valueStr =spawnAt(100,200);
binaryIO.writeString(valueStr);
valueStr =helpAt(32,3);
binaryIO.writeString(valueStr);
binaryIO.close();
}
以下是如何使用它阅读:
string myPath =同一文件的某个路径;
if(binaryIO.open(myPath,BMBinaryIOMode :: Read))
{
cout< binaryIO.read< float>()<< endl;
cout<< binaryIO.read< char>()<< endl;
double valueD = 0;
binaryIO.read(valueD); //或者你可以使用read< double()
cout<< valueD<< endl;
cout<< binaryIO.readString()<< endl;
cout<< binaryIO.readString()<< endl;
binaryIO.close();
}
编辑2:你甚至可以写/读整个结构1行:
struct Vertex {
float x,y;
};
顶点vtx; vtx.x = 2.5f; vtx.y = 10.0f;
//写它
binaryIO.write(vtx);
//读取它
Vertex vtxRead;
binaryIO.read(vtxRead); // option 1
vtxRead = binaryIO.read< Vertex>(); // option 2
希望我的代码足够清楚。
I'm looking for a way to write floats/ints/strings to a file and read them as floats/ints/strings. (basically read/write as ios::binary).
I ended up writing it myself. Just wanted to share it with others.
It might not be optimized, but I had some difficulties finding C++ code that mimics C#'s BinaryReader & BinaryWriter classes. So I created one class that handles both read and write.
Quick things to note:
1) "BM" is just a prefix for my classes.
2) BMLogging is a helper class that simply does:
cout << "bla bla bla" << endl;
So you can ignore the calls to BMLogging, I kept them to highlight the cases where we could warn the user.
Here's the code:
#include <iostream>
#include <fstream>
using namespace std;
// Create the macro so we don't repeat the code over and over again.
#define BMBINARY_READ(reader,value) reader.read((char *)&value, sizeof(value))
enum BMBinaryIOMode
{
None = 0,
Read,
Write
};
class BMBinaryIO
{
// the output file stream to write onto a file
ofstream writer;
// the input file stream to read from a file
ifstream reader;
// the filepath of the file we're working with
string filePath;
// the current active mode.
BMBinaryIOMode currentMode;
public:
BMBinaryIO()
{
currentMode = BMBinaryIOMode::None;
}
// the destructor will be responsible for checking if we forgot to close
// the file
~BMBinaryIO()
{
if(writer.is_open())
{
BMLogging::error(BMLoggingClass::BinaryIO, "You forgot to call close() after finishing with the file! Closing it...");
writer.close();
}
if(reader.is_open())
{
BMLogging::error(BMLoggingClass::BinaryIO, "You forgot to call close() after finishing with the file! Closing it...");
reader.close();
}
}
// opens a file with either read or write mode. Returns whether
// the open operation was successful
bool open(string fileFullPath, BMBinaryIOMode mode)
{
filePath = fileFullPath;
BMLogging::info(BMLoggingClass::BinaryIO, "Opening file: " + filePath);
// Write mode
if(mode == BMBinaryIOMode::Write)
{
currentMode = mode;
// check if we had a previously opened file to close it
if(writer.is_open())
writer.close();
writer.open(filePath, ios::binary);
if(!writer.is_open())
{
BMLogging::error(BMLoggingClass::BinaryIO, "Could not open file for write: " + filePath);
currentMode = BMBinaryIOMode::None;
}
}
// Read mode
else if(mode == BMBinaryIOMode::Read)
{
currentMode = mode;
// check if we had a previously opened file to close it
if(reader.is_open())
reader.close();
reader.open(filePath, ios::binary);
if(!reader.is_open())
{
BMLogging::error(BMLoggingClass::BinaryIO, "Could not open file for read: " + filePath);
currentMode = BMBinaryIOMode::None;
}
}
// if the mode is still the NONE/initial one -> we failed
return currentMode == BMBinaryIOMode::None ? false : true;
}
// closes the file
void close()
{
if(currentMode == BMBinaryIOMode::Write)
{
writer.close();
}
else if(currentMode == BMBinaryIOMode::Read)
{
reader.close();
}
}
bool checkWritabilityStatus()
{
if(currentMode != BMBinaryIOMode::Write)
{
BMLogging::error(BMLoggingClass::BinaryIO, "Trying to write with a non Writable mode!");
return false;
}
return true;
}
// Generic write method that will write any value to a file (except a string,
// for strings use writeString instead).
void write(void *value, size_t size)
{
if(!checkWritabilityStatus())
return;
// write the value to the file.
writer.write((const char *)value, size);
}
// Writes a string to the file
void writeString(string str)
{
if(!checkWritabilityStatus())
return;
// first add a \0 at the end of the string so we can detect
// the end of string when reading it
str += '\0';
// create char pointer from string.
char* text = (char *)(str.c_str());
// find the length of the string.
unsigned long size = str.size();
// write the whole string including the null.
writer.write((const char *)text, size);
}
// helper to check if we're allowed to read
bool checkReadabilityStatus()
{
if(currentMode != BMBinaryIOMode::Read)
{
BMLogging::error(BMLoggingClass::BinaryIO, "Trying to read with a non Readable mode!");
return false;
}
// check if we hit the end of the file.
if(reader.eof())
{
BMLogging::error(BMLoggingClass::BinaryIO, "Trying to read but reached the end of file!");
reader.close();
currentMode = BMBinaryIOMode::None;
return false;
}
return true;
}
// reads a boolean value
bool readBoolean()
{
if(checkReadabilityStatus())
{
bool value = false;
BMBINARY_READ(reader, value);
return value;
}
return false;
}
// reads a character value
char readChar()
{
if(checkReadabilityStatus())
{
char value = 0;
BMBINARY_READ(reader, value);
return value;
}
return 0;
}
// read an integer value
int readInt()
{
if(checkReadabilityStatus())
{
int value = 0;
BMBINARY_READ(reader, value);
return value;
}
return 0;
}
// read a float value
float readFloat()
{
if(checkReadabilityStatus())
{
float value = 0;
BMBINARY_READ(reader, value);
return value;
}
return 0;
}
// read a double value
double readDouble()
{
if(checkReadabilityStatus())
{
double value = 0;
BMBINARY_READ(reader, value);
return value;
}
return 0;
}
// read a string value
string readString()
{
if(checkReadabilityStatus())
{
char c;
string result = "";
while((c = readChar()) != '\0')
{
result += c;
}
return result;
}
return "";
}
};
EDIT: I replaced all the read/write methods above with these: (updated the usage code as well)
// Generic write method that will write any value to a file (except a string,
// for strings use writeString instead)
template<typename T>
void write(T &value)
{
if(!checkWritabilityStatus())
return;
// write the value to the file.
writer.write((const char *)&value, sizeof(value));
}
// Writes a string to the file
void writeString(string str)
{
if(!checkWritabilityStatus())
return;
// first add a \0 at the end of the string so we can detect
// the end of string when reading it
str += '\0';
// create char pointer from string.
char* text = (char *)(str.c_str());
// find the length of the string.
unsigned long size = str.size();
// write the whole string including the null.
writer.write((const char *)text, size);
}
// reads any type of value except strings.
template<typename T>
T read()
{
checkReadabilityStatus();
T value;
reader.read((char *)&value, sizeof(value));
return value;
}
// reads any type of value except strings.
template<typename T>
void read(T &value)
{
if(checkReadabilityStatus())
{
reader.read((char *)&value, sizeof(value));
}
}
// read a string value
string readString()
{
if(checkReadabilityStatus())
{
char c;
string result = "";
while((c = read<char>()) != '\0')
{
result += c;
}
return result;
}
return "";
}
// read a string value
void readString(string &result)
{
if(checkReadabilityStatus())
{
char c;
result = "";
while((c = read<char>()) != '\0')
{
result += c;
}
}
}
This is how you would use it to WRITE:
string myPath = "somepath to the file";
BMBinaryIO binaryIO;
if(binaryIO.open(myPath, BMBinaryIOMode::Write))
{
float value = 165;
binaryIO.write(value);
char valueC = 'K';
binaryIO.write(valueC);
double valueD = 1231.99;
binaryIO.write(valueD);
string valueStr = "spawnAt(100,200)";
binaryIO.writeString(valueStr);
valueStr = "helpAt(32,3)";
binaryIO.writeString(valueStr);
binaryIO.close();
}
Here's how you would use it to READ:
string myPath = "some path to the same file";
if(binaryIO.open(myPath, BMBinaryIOMode::Read))
{
cout << binaryIO.read<float>() << endl;
cout << binaryIO.read<char>() << endl;
double valueD = 0;
binaryIO.read(valueD); // or you could use read<double()
cout << valueD << endl;
cout << binaryIO.readString() << endl;
cout << binaryIO.readString() << endl;
binaryIO.close();
}
EDIT 2: You could even write/read a whole structure in 1 line:
struct Vertex {
float x, y;
};
Vertex vtx; vtx.x = 2.5f; vtx.y = 10.0f;
// to write it
binaryIO.write(vtx);
// to read it
Vertex vtxRead;
binaryIO.read(vtxRead); // option 1
vtxRead = binaryIO.read<Vertex>(); // option 2
Hope my code is clear enough.
这篇关于我想在C ++中使用ifstream和stream的模仿C#的BinaryReader / BinaryWriter功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!