我正在尋找一種將float/ints/strings寫入文件並將它們讀取爲float/ints/strings的方法。 (基本上讀/寫爲ios :: binary)。我想在C++中使用ifstream和ofstream來模仿C#的BinaryReader/BinaryWriter功能
回答
我最終自己寫了。只是想分享給別人。
它可能不是最優的,但我有一些困難,找到C++代碼,模仿C#的BinaryReader在 & 的BinaryWriter類。所以我創建了一個處理讀取和寫入的類。
快速兩點需要注意:
1)「BM」僅僅是我的課的前綴。
2)BMLogging是一個輔助類,簡單地做:
cout << "bla bla bla" << endl;
所以,你可以無視BMLogging的電話,我讓他們在哪些方面我們可以向用戶發出警告的案件。
下面的代碼:
#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 "";
}
};
編輯:我取代以上這些所有的讀/寫方法:(更新的使用代碼以及)
// 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;
}
}
}
這是如何使用它來寫:
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 = "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();
}
編輯2:你甚至可以寫/ 1線看整體結構:
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
希望我的代碼很清楚。
I subclassed ifstream
and ofstream
:ibfstream
and obfstream
。我做了一個輔助類,它可以檢測我正在編譯/運行的機器的字節順序。然後,我添加了一個ibfstream
和obfstream
的標誌,指示原始類型中的字節是否應該翻轉。這些類也有方法來讀取/寫入原始類型和這種類型的數組,以根據需要翻轉字節順序。最後,我默認爲這些類設置ios::binary
。
我經常在一個小端機器上工作,想寫大端文件,反之亦然。這被用在一個程序中,它使用各種格式的3D圖形文件進行了大量的I/O操作。
I subclassed ifstream
and ofstream
:ibfstream
and obfstream
。我創建了一個能夠檢測我正在編譯/運行的機器的序列號的類。然後,我添加了一個ibfstream
和obfstream
的標誌,指示原始類型中的字節是否應該翻轉。這些類也有方法來讀取/寫入原始類型和這種類型的數組,以根據需要翻轉字節順序。
我經常在一個小端機器上工作,想寫大端文件,反之亦然。這在一個程序中使用了很多I/O,包括各種格式的3D圖形文件。
- 1. ifstream - > ofstream C++
- 2. Ifstream和Ofstream問題
- 3. 在C++中使用ifstream的
- 4. 我想使用整數和float-objective-c中的相同功能?
- 5. C++使用ofstream的
- 6. ifstream ofstream on mac
- 7. C++:使用ifstream和getline();
- 8. C++傳遞的功能,一個功能使用仿函數
- 9. 使用ifstream來讀取文件的C++
- 10. ifstream和ofstream在崩潰後不工作
- 11. 在C++中改善ifstream的性能
- 12. 模仿c#中findstr功能的最佳方式是什麼?
- 13. 的ofstream和ifstream的路徑作品用C++編寫不讀書生成器
- 14. C++ ifstream :: read()和C數組
- 15. 模仿`ALLOCA()`用C
- 16. 使用ifstream和ofstream與cin和cout之間的區別
- 17. ofstream的功能在Linux
- 18. C++想不通陣列和功能
- 19. 在Scala中模擬C#和參考 - 準備使用功能?
- 20. 在C和通用功能
- 21. 公共父類型ifstream和ofstream
- 22. 想在我的C#機應用添加導入/導出功能
- 23. C++,使用獲取和>>爲ifstream
- 24. C++使用從內存中的ifstream
- 25. C++ ostream和ofstream轉換
- 26. C++ ofstream刪除和清理
- 27. 是否可以使用c#來模擬ms-access的功能?
- 28. 使用位打包來模擬3d數組的功能c
- 29. C++ ifstream,ofstream:在二進制模式下,raw read()/ write()調用和打開文件有什麼區別?
- 30. 在C#中使用功能的做法
1)'BMBINARY_READ'並不需要是一個宏時,它可以是一個函數模板,這應該是優選的。 '模板空隙BMBinaryRead(標準:: istream的&讀者,T&值){reader.read((字符*)值,的sizeof(值)); }' –
2)使用一個名稱空間來代替前綴。 –
打開閱讀然後寫,你處於一種奇怪的狀態。閱讀器功能應該是帶有字符串規範的模板。你毫無意義地拋棄const,停止使用C風格的轉換。 c_str已經是空的,但理論上也可以包含嵌入的空值 - 這是格式化設計要求嗎?因爲你可以做得更好。將pascal樣式表示爲254個字符,然後255表示2字節編碼長度,-1再次編碼但長度更長,等等。對於短字符串,讀取速度更快,並支持2^64長度的字符串。 – Yakk