C ++ код для сортировки данных в CSV-файле из строки - PullRequest
0 голосов
/ 06 февраля 2020

Я написал функцию, которая анализирует данные из файла и хранится в переменной String, которая называется content. Например:

 String Content =  "ABC Corp : Processed
                  server:   dfgh123
                  passed = 1250;
                  remaining = 0;

                  DTY Corp : Processed
                  server:   dty123
                  passed = 120;
                  remaining = 1;

                  QRS Corp : Processed
                  server:   qrs123
                  passed = 250;
                  remaining = 0;"

Приведенное выше значение было проанализировано из огромного текстового файла и хранится внутри строки. Теперь я хочу написать функцию, которая сортирует вышеуказанную строку в CSV-файл в следующем формате:

Processed     Server     Passed      remaining   //column name
ABC corp      dfgh123    1250         0
DTY Corp      dty123     120          1 
QRS corp      qrs123     250          0

Вот мой код синтаксического анализа

#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <functional>
#include <string>
#include <algorithm>
#include <stdio.h>
#include "time.h"
#include <ctime>
#include <iomanip>
#include <vector>
#include <numeric>
#include <iterator>
#include <locale> 
#include <codecvt>
#include <map>
#include <utility>
#include <cctype>

#pragma warning(disable: 4996)


using namespace std;
void findAndReplaceAll(std::string& data, std::string toSearch, std::string replaceStr)
{
    // Get the first occurrence
    size_t pos = data.find(toSearch);

    // Repeat till end is reached
    while (pos != std::string::npos)
    {
        // Replace this occurrence of Sub String
        data.replace(pos, toSearch.size(), replaceStr);
        // Get the next occurrence from the current position
        pos = data.find(toSearch, pos + replaceStr.size());
    }
}



int main(int argc, char** argv)
{
    string filecontent;
    wchar_t Path[256] = { 0 };
    wchar_t ExePath[256] = { 0 };
    wchar_t ConfigPath[512] = { 0 };
    GetModuleFileNameW(NULL, Path, sizeof(Path));
    wcscpy(ExePath, Path);
    PathRemoveFileSpecW(Path); //  D:\vstudio\ConsoleApplication3\Debug
    std::ofstream myfile;
    wstring ws1(Path);

    string szfilename(ws1.begin(), ws1.end());
    USES_CONVERSION;
    WIN32_FIND_DATA file;



    string pathtoDataFolder = szfilename + "\\Export_*.txt";


    HANDLE search_handlexml = FindFirstFile(A2W(pathtoDataFolder.c_str()), &file);
    string Path1("");
    string Path2("");

    if (search_handlexml)
    {
        do
        {
            USES_CONVERSION;
            PTSTR pszFileName = file.cFileName;
            //string skippedfilename = T2A(pszFileName);
            TCHAR szBuf[1024], szBuf1[1024];

            //szFileName = szFileName + T2A(pszFileName);       
            Path1 = szfilename + "\\" + T2A(pszFileName); //D:\vstudio\ConsoleApplication3\DebugExport_20190617090328.txt
            Path2 = szfilename + "\\textfile.csv";
            if ((Path1.find(".exe") != string::npos) || (Path1.find(".csv") != string::npos)|| (Path1.find(".ini") != string::npos))
            {
                //Log.WriteLog("Invalid file %s", skippedfilename.c_str());
                bool bret = false;
            }

            string abc = Path1.c_str(); //D:\vstudio\ConsoleApplication3\Release\Export_20190617090328.txt


            std::stringstream ss;
            std::ifstream fin(abc);
            ss << fin.rdbuf(); // dump file contents into a stringstream
            std::string const& s = ss.str();
            if (s.size() % sizeof(wchar_t) != 0)
            {
                std::cerr << "file not the right size\n"; // must be even, two bytes per code unit
                return 1;
            }
            std::wstring ws;
            ws.resize(s.size() / sizeof(wchar_t));
            std::memcpy(&ws[0], s.c_str(), s.size()); // copy data into wstring

            //std::wstring wide(L"Wide");
            std::string content(ws.begin(), ws.end());

            size_t pos = content.find("Summary:");
            content.erase(0, pos + 8);

            std::string the_prefix_you_want = content.substr(0, content.find("Remaining = "));
            the_prefix_you_want.erase(std::remove(the_prefix_you_want.begin(), the_prefix_you_want.end(), '\n'), the_prefix_you_want.end());
            findAndReplaceAll(the_prefix_you_want, ";", " \n");
            findAndReplaceAll(the_prefix_you_want, ":", " : ");
            findAndReplaceAll(the_prefix_you_want, "=", " = ");     
            filecontent =   filecontent + Path1.c_str() + the_prefix_you_want;



        } while (FindNextFile(search_handlexml, &file));

        myfile.open(Path2);     
        myfile << filecontent;
        myfile.close();
    }

    return 0;
        //PathRemoveFileSpecA((LPSTR)Path.c_str());
} 

1 Ответ

0 голосов
/ 06 февраля 2020

Я бы предложил вместо сохранения ваших проанализированных результатов в одной строке сохранять результаты в векторе структур. Это должно работать хорошо, поскольку весь ваш контент имеет одинаковую структуру.

Я привел пример того, как использовать это для хранения ваших данных в векторе и вывода после do, пока l oop закончил синтаксический анализ.

Я предполагаю, что тело l oop выдает информацию из одной строки. Если это не так, вам необходимо соответствующим образом изменить приведенные ниже.

/* All of your includes */

// trim from start (in place)
static inline void ltrim(std::string &s) {
    s.erase(s.begin(), std::find_if(s.begin(), s.end(),
            std::not1(std::ptr_fun<int, int>(std::isspace))));
}

// trim from end (in place)
static inline void rtrim(std::string &s) {
    s.erase(std::find_if(s.rbegin(), s.rend(),
            std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
}

// trim from both ends (in place)
static inline void trim(std::string &s) {
    ltrim(s);
    rtrim(s);
}

struct Row {
  Row() {}
  Row(const std::string& content) {
     std::istringstream ins(content);
     std::string tmp;
     getline(ins, tmp);
     name = tmp.substr(0, tmp.find(":")-1);
     getline(ins, tmp);
     server = tmp.substr(tmp.find(":")+1, tmp.length());
     trim(server);
     ins >> tmp >> tmp >> passed >> tmp >> tmp >> tmp >> remaining;
  }
  std::string name;
  std::string server;
  size_t passed;
  size_t remaining;
};

void findAndReplaceAll(std::string& data, std::string toSearch, std::string replaceStr) {
  // Body elided for brevity
}

int main(int argc, char** argv) {
  // Your setup code.

  if (search_handlexml) {
    vector<Row> rows;
    do {
      // Your parsing code
      // until you assign to filecontent
      filecontent = Path1.c_str() + the_prefix_you_want;
      size_t pos = filecontent.find("\n\n");
      while (pos != std::string::npos) {
        rows.push_back(Row(filecontent.substr(0, pos)));
        filecontent = filecontent.substr(pos+1, filecontent.length());
      }
      rows.push_back(Row(filecontent));
    } while (FindNextFile(search_handlexml, &file));

    // OUTPUT TO CSV FILE (sample code writing to cout in CSV format (comma separated))
    std::cout << "Processed,Server,Passed,remaining" << std::endl;
    for (size_t i = 0; i < rows.size(); ++i) {
      std::cout << "\"" << rows[i].name << "\",";
      std::cout << "\"" << rows[i].server << "\",";
      std::cout << rows[i].passed << "," << rows[i].remaining << endl;
    }
  }
  return 0;
}
...