常常在GCC(MinGW)和C++ Builder 中都有讀寫數據的時候,也就是從文件中將一組數據讀入二維數組<vector>,或者將數組中的數據格式化寫入文件,甚至有時還想給文件加個文件頭,當然文件頭也要對齊了才好看一點,兩個軟件實現的方法都不一樣,常常讓人惱火,今天有空,編寫了個類,兩個都能通用的文件讀寫類FileData.
有3點請大家注意:
1.FileData類讀的數據文件的格式是任意的,數據的排列方式也是任意的,
也就是說FileData可以自動檢測數據的排列方式和分割方式,每行的數據個數可以互不相同!
一句話,只要文件裡面有數據就可以正確識別!
2.FileData將數組和文件頭寫入文件的時候,自動對齊數據和文件頭.
也就是說你用記事本打開一看,數據和文件頭是排列得整整齊齊的.
3.FileData中使用了寬字符(漢字),所以為了讓MinGW識別,請將FileData.hpp保存為UTF-8的格式.
- // -----------------------------------------------------------------------------
- // 功能強大的讀寫數據文件類 FileData.hpp
- // 經常要將數據導入C++,使用這個很方便
- // Wu Xuping 2012-02-09
- // 測試環境:
- // C++ builder 2010
- // MinGW 4.5.1 windows
- // www.linuxidc.com
- // 使用很簡單,看看最後附上的測試代碼即可
- // FileData.hpp一定要保存為UTF-8的格式,因為這是MinGW的默認格式
- // -----------------------------------------------------------------------------
- #ifndef FileData_H
- #define FileData_H
- // --------------------
- #include <iostream>
- #include <fstream>
- #include <vector>
- #include <string>
- #include <sstream>
- #include <iterator>
- #include <algorithm>
- using namespace std;
-
- // ==============================================================================
- // SplitString::分割字符串的函數
- // ==============================================================================
- // -----------------------------------------------------------------------------
- void SplitString(string str, vector<string>&sv, string separator = " ;,\t") {
- // ---------------------------------------
- if (sv.size() > 0) {
- sv.clear();
- }
- // ---------------------------------------
- vector<long int>index_v; // 分割索引
- // ---------------------------------------
- for (unsigned i = 0; i < str.length(); i++) {
- for (unsigned j = 0; j < separator.length(); j++) {
- if (str[i] == separator[j]) {
- index_v.push_back(i);
- }
- }
- }
- // ---------------------------------
- index_v.push_back(-1); // 加上開始的字符
- index_v.push_back(str.length()); // 加上結尾的字符
- // -----------------------------------
- sort(index_v.begin(), index_v.end()); // 排序
- // --------------------------------
- for (unsigned i = 1; i < index_v.size(); i++) {
- long int startindex = index_v[i - 1] + 1;
- long int endindex = index_v[i];
- if (startindex < endindex) {
- string cstr(str.begin() + startindex, str.begin() + endindex);
- sv.push_back(cstr);
- }
- };
- // --------------------------------
- };
- // -----------------------------------------------------
-
- // ==============================================================================
- // StringToDoubleVector::將字符串轉換為數組的函數
- // ==============================================================================
- void StringToDoubleVector(string istr, vector<double> &od1v) {
- if (od1v.size() > 0) {
- od1v.clear();
- }
- // 將不要的字符的字符全部換成空格,
- string delimit = " ";
- for (string::size_type i = 0; i < istr.length(); i++) {
- int si = char(istr[i]);
- if (si < 43 || si > 57 || si == 44 || si == 47) {
- if (si != 100 && si != 101 && si != 68 && si != 69) {
- // 不是dD或eE的字符都用空格代替
- istr.erase(i, 1);
- istr.insert(i, delimit);
- }
- }
- }
- // -------分割字符串
- vector<string>vs;
-
- for (string::size_type i = 0; i < istr.length(); i++) {
- if (istr[i] == delimit[0]) {
- string cstr = istr.substr(0, i);
- vs.push_back(cstr);
- istr.erase(0, i);
- i = 0;
- }
- }
- vs.push_back(istr);
- // -----------字符轉為double類型的數
- for (unsigned int i = 0; i < vs.size(); i++) {
- istr = vs[i];
- istringstream istr_stream(istr);
- double num;
- while (istr_stream >> num) {
- od1v.push_back(num);
- }
- }
-
- };
-
- // -----------------------------------------------------------------------------
- // FileData::讀寫文件的類
- // -----------------------------------------------------------------------------
- class FileData {
- private:
- vector<vector<double> >_Data; // 二維數組
-
- unsigned int _Row; // 數組的行數
- unsigned int _MinColumn; // 數組最小列
- unsigned int _MaxColumn; // 數組最大列
-
- string _FileName; // 文件名
- string _Headstr; // 文件第一行字符串
-
- // -讀寫文件中的數據-----------------------------------------------
- void LoadDataFromFile();
- void SaveDataToFile();
- // -----------------------------------------------------------------
-
- public:
-
- // ---構造函數 -------------
- FileData() : _Row(0), _MinColumn(0), _MaxColumn(0), _FileName(""),
- _Headstr("") {
- };
- // -----------------------------------------------------------------
- // --讀取文件中的數據
- void LoadDataFromFile(string FileName);
- // -----------------------------------------------------------------
- // --保存數據到文件中
- void SaveDataToFile(string FileName, string Headstr = "");
-
- // ------------------------------------------------------------------------
- unsigned int GetRow() {
- _Row = _Data.size();
- return _Row;
- };
-
- // ------------------------------------------------------------------------
- unsigned int GetMinColumn() {
- _MinColumn = 999999999;
- for (unsigned int i = 0; i < _Data.size(); i++) {
- if (_MinColumn > _Data[i].size()) {
- _MinColumn = _Data[i].size(); // 獲取最小行
- }
- }
- if (_MinColumn >= 999999999) {
- _MinColumn = 0;
- }
- return _MinColumn;
- };
-
- // ------------------------------------------------------------------------
- unsigned int GetMaxColumn() {
- _MaxColumn = 0;
- for (unsigned int i = 0; i < _Data.size(); i++) {
- if (_MaxColumn < _Data[i].size()) {
- _MaxColumn = _Data[i].size(); // 獲取最小行
- }
- }
- return _MaxColumn;
- };
-
- // -------------------------------------------------------------------------
- //////////////////////////////////////////////////////////////////////////
- // 獲取文件的第一行作為文件頭
- //////////////////////////////////////////////////////////////////////////
- string GetHeadstr() {
- ifstream fin(_FileName.c_str());
- if (!fin.bad()) {
- getline(fin, _Headstr);
- }
- fin.close();
- return _Headstr;
- };
-
- // ------------------------------------------------------------------------
- // 提取數據
- // ------------------------------------------------------------------------
- void GetData(vector<vector<double> >&Data) {
- Data.assign(_Data.begin(), _Data.end());
- };
-
- // ------------------------------------------------------------------------
- // 設置數據
- // ------------------------------------------------------------------------
- void SetData(vector<vector<double> >&Data) {
- _Data.assign(Data.begin(), Data.end());
- };
- // ------------------------------------------------------------------------
- void PrintData();
-
- // -------------默認destructor函數 -------------
- ~FileData() {
- };
- // -----------
- };
-
- // ==============================================================================
- // LoadDataFromFile0
- // ==============================================================================
- void FileData::LoadDataFromFile() {
-
- _Row = 0;
- _MinColumn = 999999999;
- _MaxColumn = 0;
- if (_Data.size() > 0) {
- _Data.clear();
- }
- ifstream fin(_FileName.c_str());
- if (!fin.bad()) {
- string s;
- while (getline(fin, s)) {
- vector<double>tempdv;
- StringToDoubleVector(s, tempdv);
- if (tempdv.size() > 0) {
- _Data.push_back(tempdv);
- _Row++;
- if (tempdv.size() < _MinColumn) {
- _MinColumn = tempdv.size(); // 獲取最小行
- }
- if (tempdv.size() > _MaxColumn) {
- _MaxColumn = tempdv.size(); // 獲取最大行
- }
- }
-
- }
- }
- fin.close();
- }
-
- // ==============================================================================
- // LoadDataFromFile1
- // ==============================================================================
- void FileData::LoadDataFromFile(string FileName) {
- _FileName = FileName;
- LoadDataFromFile();
- }
-
- // ==============================================================================
- // SaveDataToFile0
- // ==============================================================================
- void FileData::SaveDataToFile() {
- if (_Data.size() > 0) {
- vector<string>strv;
- for (unsigned int i = 0; i < _Data.size(); i++) {
- string cstr = "";
- for (unsigned int j = 0; j < _Data[i].size(); j++) {
- char buffer[32];
- sprintf(buffer, "%12.6f", _Data[i][j]);
- cstr = cstr + " " + buffer;
- }
- strv.push_back(cstr);
- }
- ofstream ofs(_FileName.c_str());
- if (!ofs.bad()) {
- if (_Headstr.length() > 1) {
- vector<string>hvs;
- SplitString(_Headstr, hvs);
- string cstr = "";
- for (unsigned int n = 0; n < hvs.size(); n++) {
- char buffer[256];
- if (hvs[n].size() > 12) {
- sprintf(buffer, "%s", hvs[n].c_str());
- }
- else {
- sprintf(buffer, "%12s", hvs[n].c_str());
- }
- cstr = cstr + " " + buffer;
- }
- ofs << cstr << endl;
- }
- copy(strv.begin(), strv.end(), ostream_iterator<string>(ofs, "\n"));
- }
- ofs.close();
- }
-
- }
-
- // ==============================================================================
- // SaveDataToFile1
- // ==============================================================================
- void FileData::SaveDataToFile(string FileName, string Headstr) {
- _FileName = FileName;
- _Headstr = Headstr;
- SaveDataToFile();
- }
-
- //////////////////////////////////////////////////////////////////////////
- // --用於控制台打印數據的函數PrintData
- //////////////////////////////////////////////////////////////////////////
- void FileData::PrintData() {
- cout << _FileName.c_str() << endl;
- if (_Data.size() > 0) {
-
- string cstr = "";
- for (unsigned int n = 0; n < _Data[0].size() + 1; n++) {
- char buffer0[32];
- char buffer[32];
- if (n < 1) {
- sprintf(buffer, "%12s", "Index");
- cstr = cstr + buffer+" ";
- }
- else {
- sprintf(buffer0, "Column%d", n);
- sprintf(buffer, "%12s", buffer0);
- cstr = cstr + buffer+" ";
- }
- }
- cout << cstr << endl;
-
- // 輸出數組
- for (unsigned int i = 0; i < _Data.size(); i++) {
- char buffer0[32];
- char buffer[32];
- sprintf(buffer0, "Row[%d]", i);
- sprintf(buffer, "%12s", buffer0);
- cout << buffer << ' ';
- for (unsigned int j = 0; j < _Data[i].size(); j++) {
- sprintf(buffer, " %12.6f", _Data[i][j]);
- cout <<buffer;
- }
- cout << endl;
- }
-
- }
- else {
- cout << "There is no data in this file at all!" << endl;
- }
- }
- // ------------------------------------------------------------------------------
- #endif