Convert CSV file to TFDMemTable format JSON file.

by Sep 1, 2017

 

Convert from CSV file to “JSON file” of “TFDMemTable format”.

This program uses C++Builder 10.2 Tokyo Release 1.

include

#include <iostream>
#include <fstream>
#include <string>
#include <codecvt>
#include <FireDAC.Comp.Client.hpp>
#include <FireDAC.Stan.StorageJSON.hpp>
#include <FireDAC.Stan.Intf.hpp>
#include <memory>
#include <vector>
#include <sstream>
#include <mutex>
#include <thread>
#include <chrono>

code

struct _Tcsv_to_memtable
{
    std::mutex mx_;
    std::vector<std::thread> vth_;
    std::unique_ptr<TFDMemTable> mem_table_{std::make_unique<TFDMemTable>(nullptrnullptrvoid create_column(std::vector<String>& v)
    {
        //Field creation of "TFDMemTable"
        //The field name is the first line of CSV File
        for (auto s: v)
        {
            auto fld = mem_table_->FieldDefs->AddFieldDef();
            //Discard the "BOM (Byte Order Mark)" if present.
            fld->Name = StringReplace(s, L'\x0feff', "", TReplaceFlags());
            fld->DataType = TFieldType::ftWideString;
        }
        mem_table_->Active = truevoid create_line(std::vector<String>& v)
    {
        //Add 1 line of "CSV File" to "TFDMemTable"
        int i{0for (auto s: v)
        {
            //One item for one field.
            mem_table_->Fields->operator[](i)->AsWideString = s;
            ++i;
        }
        mem_table_->Post();
    }
    void create_line(std::wstring ws, int line_num)
    {
        std::lock_guard<std::mutex> lk(mx_);
        if (ws.length() > 0)
        {
            //Inserted by dividing one line of CSV File to vector<String>.
            std::vector<String> v1;
            std::wstring column_data;
            std::wistringstream line_data(ws);
            while (std::getline(line_data, column_data, L','))
            {
                v1.push_back(column_data.c_str());
            }
            switch (line_num)
            {
            case 0:
                create_column(v1);
                breakdefault:
                create_line(v1);
            }
        }

    }
    void threads_join()
    {
        //Wait for the termination of all threads.
        for (auto& th: vth_)
        {
            th.join();
        }
    }

};
int _tmain(int argc, _TCHAR* argv[])
{
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    _Tcsv_to_memtable memtable_;
    UnicodeString argv_     = argv[1//Specify CSV Fire for input.
    UnicodeString arg_o_    = argv[2//JSON output destination specification made with "TFDMemTable".
    if (FileExists(argv_))
    {
        std::wfstream file_;
        file_.open(argv_.w_str(), std::ios::in);
        //The CSV file is utf8 format.
        file_.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));

        std::wstring buff;
        int line_num_{0while (std::getline(file_, buff))
        {
            //The append processing to "TFDMemTable" threads line by line.
            memtable_.vth_.push_back(std::thread([&memtable_, &buff, line_num_](){
                memtable_.create_line(buff, line_num_);
                }));
            //Since the command line is multibyte, AnsiString conversion is done.
            AnsiString as_ = buff.c_str();
            std::cout << as_ << std::endl;
            ++line_num_;
        }

        memtable_.threads_join();
        //Finally, save the TFDMemTable contents as a JSON file.
        memtable_.mem_table_->SaveToFile(arg_o_, TFDStorageFormat::sfJSON);

    }
    auto keika =  std::chrono::system_clock::now() - now;
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(keika).count();
    std::cout << " millisecond." << std::endl ;
    return 0

There is a project file in github, you can try it right away.
GitHub - mojeld/csvfstream_to_TFDMemTable: Create json file of TFDMemTable format from CSV file.

f:id:mojeld:20170901174729p:plain