<[CDATA[O F F T O P
Прошло довольно много лет с тех времен, когда я ну прямо-таки "ИЗЗоВСЕХсИЛЛ" самостоятельно учил WINAPI/WTL/ATL/STL/Boost и т.д, короче учился программировать на C++ под Win32. В те дни я ваще понять не мог нафига нужна Java, если клиентское приложение грузится дольше Windows... В общем по сути это было время когда я о серверах вообще не задумывался, я думал только о том как угодить хотя бы какому-нибудь пользователю с "суперидейным" "десктопным" "велосипедом".
Говоря короче - я только и занимался, что писал крохотные приложения на Visual C++ (в основном GUI)... Данное "введение" я веду к тому, что моя мечта пару недель назад осуществилась и не так давно мне наконец-то предоставилась возможность написать еще одну "кроху", причем теоретически полезную не только мне, но и кому-то еще.
]]>
Описание приложения:
Эта программа предназначена для загрузки данных из текстового фала в файлы базы данных dbase.
Достоинства:
Конечно, я не силен в С++, поэтому просьба особо критично не оценивать (и сразу извиняюсь за недостаток комментариев в исходном коде, как-нибудь обязательно займусь).
Кроме основного исполняемого-файла понадобятся файл инициализации, пустой файл таблицы, ну и конечно же сам текстовый файл с данными.
Для примера я выкладываю полный архив включающий все что только можно:
Скачать собранный проект (14 Кб) (включает в себя также скомпилированную программу)
добавлю еще пару замечаний к "проекту" :)
Прошло довольно много лет с тех времен, когда я ну прямо-таки "ИЗЗоВСЕХсИЛЛ" самостоятельно учил WINAPI/WTL/ATL/STL/Boost и т.д, короче учился программировать на C++ под Win32. В те дни я ваще понять не мог нафига нужна Java, если клиентское приложение грузится дольше Windows... В общем по сути это было время когда я о серверах вообще не задумывался, я думал только о том как угодить хотя бы какому-нибудь пользователю с "суперидейным" "десктопным" "велосипедом".
Говоря короче - я только и занимался, что писал крохотные приложения на Visual C++ (в основном GUI)... Данное "введение" я веду к тому, что моя мечта пару недель назад осуществилась и не так давно мне наконец-то предоставилась возможность написать еще одну "кроху", причем теоретически полезную не только мне, но и кому-то еще.
]]>
Описание приложения:
Эта программа предназначена для загрузки данных из текстового фала в файлы базы данных dbase.
Достоинства:
- Полный исходник
- Достаточно подробная настройка (через параметры коммандной строки можно передавать вплоть до строки с настройками драйвера и др.)
- программа писалась примерно столько же времени сколько я пишу этот пост, поэтому, в частности ей не хватает токования ошибок ODBC.
- #include "stdafx.h"
- //#undef _UNICODE
- #include <windows.h>
- #include <shlwapi.h>
- /* we'll using standart C++ library */
- #include <iostream>
- #include <fstream>
-
- #include <tchar.h>
- #include <sqltypes.h>
- #include <sqlext.h>
- #include <sql.h>
-
- #include <odbcinst.h>
- #pragma comment(lib, "odbccp32")
- #pragma comment(lib, "shlwapi")
-
- // execution options
-
- #define EXEC_SQL
- //#define DONT_CREATE_DSN
- //#define DONT_REMOVE_DSN
-
- using namespace std;
-
- enum SQL_DATA_TYPES { SDT_VARCHAR, SDT_NUMBER, SDT_DATE };
-
- #ifdef _UNICODE
- #define mcout wcout
- #define mstring wstring
- #else
- #define mcout cout
- #define mstring string
- #endif
-
- #define N_TYPE _T("type")
- //#define SZ_NAME _T("name")
- #define N_SIZE _T("size")
- #define N_COLUMN _T("order")
- #define SZ_T_COPYRIGHT_INFO _T("CSV(text) to DBF universal converter / (c) stash, 2009")
- #define TABLE_NAME "export01\0"
- #define DELETE_DATA_QUERY "DELETE FROM "TABLE_NAME
-
- //#define szUser _T("")
- //#define szPass _T("")
-
- #define LPRECINFO RECINFO*
-
- #define T_DEFAULT_TABLE_NAME _T("export01")
- #define T_DEFAULT_OUTPUT_NAME _T("export01.dbf")
- #define T_DEFAULT_DSN _T("text2dbase3tmp")
- #define T_DEFAULT_DRV _T("Microsoft dBase Driver (*.dbf)")
- #define T_DEFAULT_DSN_PARAMS _T("DSN=%WORKDSN%;Fil=dBase III;DriverID=21;DefaultDir=%TARGETDIR%")
- #define T_WORKDIR _T("%WORKDIR%")
- #define T_TARGETDIR _T("%TARGETDIR%")
-
- #define T_WORKFILE _T("%WORKFILE%")
- #define T_WORKDSN _T("%WORKDSN%")
- #define T_TABLENAME _T("%TABLENAME%")
- #define T_DEFAULT_SKIP_BEFORE 0
- #define T_DEFAULT_SKIP_AFTER 2
-
- #define N_INIT_ERROR -1
- #define SQL_ERROR_HANDLE_ENV -2
- #define SQL_ERROR_HANDLE_DBC -3
- #define SQL_DSN_CONFIG_ERROR -4
- #define SQL_ERROR_HANDLE_STMT -5
- #define IO_CANNOT_ALLOC_MEMORY -6
- #define IO_CANNOT_INPUT_STREAM -7
- #define IO_FILE_NOT_FOUND -8
- #define N_ENOUGH_PARAMETERS -9
- #define WRONG_ARGS -10
-
- #ifdef _DEBUG
- #define DEVELOPPER_STAGE // additional debug option
- #endif
-
- #define RECINFO_DEFAULT_SIZE 0x000000FF
- #define RECINFO_DEFAULT_ORDER 0x00000001
- #define RECINFO_DEFAULT_SQL_TYPE SDT_VARCHAR
- #define RECINFO_DEFAULT_SQL_TYPE_INT 1
- struct RECINFO
- {
- SQL_DATA_TYPES m_nSqlDataType;
- int m_nColumn, m_nLength;
- std::mstring m_name; // TCHAR
- std::string m_value; // char only
- void setValue(char *val) {
- //cout << " source: " << val << endl;
-
- for (size_t i=0; i<strlen(val); i++)
- if (val[i]=='\''/* || val[i]=='\x0A'*/)
- val[i]='"';
-
- //cout << " after replacements: [[[ " << val << "]]]" << endl;
- m_value = val;
- //m_value.replace("
- }
- void set( SQL_DATA_TYPES nType = RECINFO_DEFAULT_SQL_TYPE,
- int data_size = RECINFO_DEFAULT_SIZE,
- int nColumnNum = 1,
- TCHAR* strName = _T("ID")) {
-
- m_nSqlDataType = nType;
- m_nColumn = nColumnNum;
- m_name = strName;
- m_nLength = data_size;
- }
- RECINFO(int nType = RECINFO_DEFAULT_SQL_TYPE_INT, int data_size = RECINFO_DEFAULT_SIZE, int nColumnNum = 1, TCHAR* strName = _T("ID")) {
- SQL_DATA_TYPES sql_data_type_fellow = SDT_VARCHAR;
- switch(nType) {
- case 0:
- case 2:
- sql_data_type_fellow = SDT_NUMBER;
- break;
- case 3:
- sql_data_type_fellow = SDT_DATE;
- break;
- }
- set(sql_data_type_fellow, data_size, nColumnNum, strName);
- }
- /* RECINFO ( SQL_DATA_TYPES nType = SDT_VARCHAR,
- int data_size = RECINFO_DEFAULT_SIZE,
- int nColumnNum = RECINFO_DEFAULT_ORDER,
- TCHAR* strName = _T("ID")) {
- set(nType, data_size, nColumnNum, strName);
- }; */
- void check() {
- mcout << _T("Column N") << m_nColumn << _T(" (\"") << m_name.c_str() << _T("\"), length=") << m_nLength << endl;
- }
- //~RECINFO() { name=delete string(_T("")); }
- };
-
- struct APPLICATION {
-
- protected:
- int m_nTOTAL_COLUMNS_DONT_TRY_CHANGE_THIS_VALUE; // total readed columns
- LPRECINFO m_lpRecinfo[1024]; // all columns
- SQLHENV m_henv;
- SQLHDBC m_hdbc;
- SQLHANDLE m_hstmt;
- int m_nTotalRecordSize;
- public:
- int m_nErrorCode;
- mstring m_strError;
- mstring m_strDSN, m_strLogin, m_strPassword;
- mstring m_strIniFile;
- mstring m_strEmptyDbf;
- mstring m_strTargetFilename;
- //mstring m_strDSNName;
- mstring m_strDSNDriver;
- mstring m_strDSNParams;
- mstring m_strSourceProcFile;
- mstring m_strTableName;
- mstring m_strOutputDirectory;
- mstring m_strSourceDirectory;
-
- int m_nSkipBytesAfterEachRecord;
- int m_nSkipBytesBeforeEachRecord;
-
- // -- methods
- int status() {
- if (m_nErrorCode>=0)
- return S_OK;
- return E_FAIL;
- }
- APPLICATION(int c_argc, _TCHAR* c_argv[]) { /* default constructor was called */
- m_nTOTAL_COLUMNS_DONT_TRY_CHANGE_THIS_VALUE = 0;
- m_henv = NULL;
- m_hdbc = NULL;
- m_hstmt = NULL;
- m_nErrorCode = 0;
- if (c_argc < 2) {
- ShowUsage();
- setLastErrorIndex(_T("Not enough of application arguments"), N_ENOUGH_PARAMETERS);
- }
- else {
- ReadCommandLine(c_argc, c_argv);
- }
- };
- private:
- void setLastErrorIndex(TCHAR *szError, int lastErrorIndex = N_INIT_ERROR) {
- m_strError = szError;
- m_nErrorCode = lastErrorIndex;
- }
- public:
- int reportError(bool quitRightNow = true) {
- mcout << _T("Error: ") << this->m_strError.c_str() << endl;
- return m_nErrorCode;
- }
- bool ReadConfig( mstring str_inifile ) {
- TCHAR* d = new TCHAR[0x7fff];
- memset(d, 0, sizeof(d));
- DWORD dw = GetPrivateProfileSectionNames(d, 0x7fff, str_inifile.c_str());
- if (dw < 5) {
- setLastErrorIndex( _T("too short or empty ini-file -> application will now quit, bye-bye") );
- return false;
- }
- bool quit = false;
- int counter = 0;
- int nColumn = 0;
- m_nTotalRecordSize = 0;
- while (!quit && counter < (int)dw) {
- mcout << "adding column = " << d+counter << endl;
- m_lpRecinfo[nColumn++] = new RECINFO( GetPrivateProfileInt(d+counter, N_TYPE, 1, str_inifile.c_str()),
- GetPrivateProfileInt(d+counter, N_SIZE, 255, str_inifile.c_str()),
- GetPrivateProfileInt(d+counter, N_COLUMN, 1, str_inifile.c_str()),
- d+counter);
- m_nTotalRecordSize += GetPrivateProfileInt(d+counter, N_SIZE, 255, str_inifile.c_str());
- //lpRecinfo[nColumn++] = new ;
- //memset(e,0,sizeof(e));
- counter += lstrlen(d+counter)+1;
- }
- /*final*/m_nTOTAL_COLUMNS_DONT_TRY_CHANGE_THIS_VALUE = nColumn;
- delete d;
- return true;
- }
-
- bool InitODBC(TCHAR *szDSN = NULL, TCHAR *szLogin = _T(""), TCHAR *szPass = _T(""))
- {
- if (szDSN!=NULL)
- m_strDSN = szDSN;
- m_strLogin = szLogin;
- m_strPassword = szPass;
-
- if (SQLAllocHandle(SQL_HANDLE_ENV, NULL, &m_henv) == SQL_ERROR) { // Alloc env handle
- setLastErrorIndex(_T("AllocHandle on ENV failed."), SQL_ERROR_HANDLE_ENV);
- return false;
- }
-
- SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, SQL_IS_INTEGER);
-
- if (SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &m_hdbc) == SQL_ERROR) {
- setLastErrorIndex(_T("AllocHandle on DBC failed."), SQL_ERROR_HANDLE_DBC);
- return false;
- }
- if ( SQLConnect(m_hdbc, (SQLTCHAR*)m_strDSN.c_str(), SQL_NTS,
- (SQLTCHAR*)m_strLogin.c_str(), m_strLogin.length(), (SQLTCHAR*)m_strPassword.c_str(),
- m_strLogin.length() ) == SQL_ERROR ) {
- setLastErrorIndex(_T("Connect to ODBC failed."), SQL_DSN_CONFIG_ERROR);
- return false;
- }
- if (::SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &m_hstmt) == SQL_ERROR) { // Get a statement handle
- setLastErrorIndex(_T("AllocHandle on STMT failed."), SQL_ERROR_HANDLE_STMT);
- return false;
- }
- return true;
- }
-
- void construct_insert_query(TCHAR *output, int nMaxLength, LPRECINFO cols[], int length_r) {
- memset(output, 0, nMaxLength*sizeof(TCHAR));
- lstrcpy(output, _T("INSERT INTO "));
- lstrcat(output, m_strTableName.c_str());
- lstrcat(output, _T(" ("));
- for (int i=0; i<length_r; i++) {
- if (cols[i]->m_value.length()>0) {
- if (i) lstrcat(output, _T(","));
- output[lstrlen(output)] = _T('`');
- lstrcat(output, cols[i]->m_name.c_str());
- output[lstrlen(output)] = _T('`');
- }
- }
- lstrcat(output, _T(") VALUES ("));
- for (int i=0; i<length_r; i++) {
- if (cols[i]->m_value.length()>0) {
- if (i) lstrcat(output, _T(","));
- if ( cols[i]->m_nSqlDataType != SDT_NUMBER)
- output[lstrlen(output)] = _T('\'');
- lstrcat(output, cols[i]->m_value.c_str());
- if ( cols[i]->m_nSqlDataType != SDT_NUMBER)
- output[lstrlen(output)] = _T('\'');
- }
- }
- lstrcat(output, _T(")"));
- }
-
- bool processSqlReturn( SQLRETURN ret, SQLHANDLE sql_handle)
- {
- bool is_it_success = false;
-
- if (sql_handle == NULL)
- mcout << _T(" hstmt is NULL! ") << endl;
-
- if ( ret == 0 ) {
- is_it_success = true;
- mcout << _T("success!") << endl;
- }
- else
- mcout << _T("failed, with return code: ") << ret << endl;
- return is_it_success;
- }
- int getTotalCols() { return m_nTOTAL_COLUMNS_DONT_TRY_CHANGE_THIS_VALUE; }
-
- bool ProcessTextFile( const TCHAR* szFilename ) {
- fstream ifile(szFilename, ios_base::in | ios_base::binary);
- char *ibuff = new char[m_nTotalRecordSize];
- char *obuff = new char[0x7fff];
- char *buf = new char[0x1000];
- char *buf2 = new char[0x1000];
- char trim[] = ("\x20\x09\0");
-
- if(!ifile.is_open()) {
- setLastErrorIndex(_T("Cannot open input text stream"), IO_CANNOT_INPUT_STREAM);
- return false;
- }
- if(!ibuff || !obuff || !buf) {
- ifile.close();
- setLastErrorIndex(_T("Cannot Allocate buffers"), IO_CANNOT_ALLOC_MEMORY);
- return false;
- }
- int nOff = 0;
- //cout << _T("Executing query: ") << DELETE_DATA_QUERY << endl;
- //return 0;
- //if (!processSqlReturn(SQLExecDirect(hstmt, (SQLCHAR*)DELETE_DATA_QUERY, SQL_NTS),hstmt))
- // reportError(_T("Cannot drop data from ")TABLE_NAME);
-
- while(!ifile.eof()) {
- memset(ibuff, 0, m_nTotalRecordSize); // why? :-/
- if (m_nSkipBytesBeforeEachRecord>0) {
- ifile.seekg( m_nSkipBytesBeforeEachRecord, ios_base::cur );
- if(ibuff[0] == 0 && ifile.eof()) break; // just exit from loop
- }
- ifile.read(ibuff, m_nTotalRecordSize);
- if(ibuff[0] == 0 && ifile.eof()) break; // just exit from loop
- if (m_nSkipBytesAfterEachRecord>0) {
- ifile.seekg( m_nSkipBytesAfterEachRecord, ios_base::cur );
- if(ibuff[0] == 0 && ifile.eof()) break; // just exit from loop
- }
- nOff = 0;
- //mcout << _T("---[ RECORD ]---------------") << endl;
- for (int j=0; j < getTotalCols(); j++) {
- memcpy(buf, ibuff+nOff, m_lpRecinfo[j]->m_nLength);
- buf[ m_lpRecinfo[j]->m_nLength - 1 ] = '\x0';
- StrTrimA(buf,trim);
- /* if ())
- cout << "Trimmed: " << buf << endl;
- else
- cout << "NOT Trimmed: " << buf << endl; */
- // for construct "insert" query
- /* if ( CharToOem( buf, buf2 ) ) {
- m_lpRecinfo[j]->setValue( buf2 );
- buf2[ m_lpRecinfo[j]->m_nLength ] = '\x0';
- }
- else { */
- m_lpRecinfo[j]->setValue( buf );
- //}
- nOff += m_lpRecinfo[j]->m_nLength;
- }
- construct_insert_query(obuff, 0x7fff, m_lpRecinfo, getTotalCols());
- mcout << _T("executing query: \"") << obuff << _T("\"...");
- #ifdef EXEC_SQL
- processSqlReturn( SQLExecDirect(m_hstmt, (SQLCHAR*)obuff, SQL_NTS), m_hstmt );
- #else
- mcout << _T("execution skipped") << endl;
- #endif
- }
- ifile.close();
- delete obuff;
- delete ibuff;
- delete buf;
- delete buf2;
- return true;
- }
- void FreeAllThatPossible() {
- while (m_nTOTAL_COLUMNS_DONT_TRY_CHANGE_THIS_VALUE-->0)
- delete m_lpRecinfo[m_nTOTAL_COLUMNS_DONT_TRY_CHANGE_THIS_VALUE];
- /* odbc deinit */
- if (m_hstmt != NULL)
- SQLFreeHandle(SQL_HANDLE_STMT, m_hstmt);
- if (m_hdbc != NULL) {
- SQLDisconnect(m_hdbc);
- SQLFreeHandle(SQL_HANDLE_DBC, m_hdbc);
- }
- if (m_henv != NULL)
- SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
- }
- ~APPLICATION() {
- FreeAllThatPossible();
- mcout << _T(" \\--> Application will now exit -> bye-bye") << endl;
- }
- #define T_BY_DEFAULT_START _T(" (e.g. ")
- #define T_BY_DEFAULT_END _T(")")
- #define T_DBF_EXTENSION _T(".dbf")
- void ShowUsage()
- {
- mcout << _T(" Usage: text2dbase.exe input.text [output.dbf] [output table name]]") << endl
- << _T(" [DSN [DSN driver] [DSN parameters] ") << endl << endl
- << _T(" Where \"input.text\" is a name of input text file with data") << endl << endl
- << _T(" Optional: ") << endl
- << _T(" \x1A output.dbf - output dbase-filename") << T_BY_DEFAULT_START << T_DEFAULT_OUTPUT_NAME << T_BY_DEFAULT_END << endl
- << _T(" \x1A output table - name of the output table, where we'll store values") << T_BY_DEFAULT_START << T_DEFAULT_TABLE_NAME << T_BY_DEFAULT_END << endl << endl
- << _T(" \x1A DSN - windows ODBC data source name") << T_BY_DEFAULT_START << T_DEFAULT_DSN << T_BY_DEFAULT_END << endl
- << _T(" \x1A DSN driver - windows ODBC driver name") << T_BY_DEFAULT_START << T_DEFAULT_DRV << T_BY_DEFAULT_END << endl
- << _T(" \x1A DSN parameters - ODBC DSN parameters") << T_BY_DEFAULT_START << T_DEFAULT_DSN_PARAMS << T_BY_DEFAULT_END << endl
- << _T("This application need ini-file, named csv2dbase.ini") << endl
- << _T("with fields descriptions, formatted as examle below:") << endl
- << _T(" [column_name]") << endl
- << _T(" size = 32") << endl
- << _T(" order = 3") << endl
- << _T(" type = 1") << endl;
- }
- bool ReadCommandLine(int argc, _TCHAR* argv[])
- {
- TCHAR pathBuff[0xff];
- memset(pathBuff, 0, sizeof(pathBuff));
- GetModuleFileName(NULL, pathBuff, MAX_PATH);
- m_strIniFile = pathBuff;
- m_strEmptyDbf = m_strIniFile;
-
- m_strEmptyDbf[m_strEmptyDbf.length()-1] = _T('f');
- m_strEmptyDbf[m_strEmptyDbf.length()-2] = _T('b');
- m_strEmptyDbf[m_strEmptyDbf.length()-3] = _T('d');
-
- m_strIniFile[m_strIniFile.length()-1] = _T('i');
- m_strIniFile[m_strIniFile.length()-2] = _T('n');
- m_strIniFile[m_strIniFile.length()-3] = _T('i');
-
- m_strEmptyDbf += _T(".empty");
-
- while (lstrlen(pathBuff)>1 && pathBuff[lstrlen(pathBuff)-1]!=_T('\\'))
- pathBuff[lstrlen(pathBuff)-1] = 0;
-
- m_strSourceDirectory = pathBuff;
-
- m_strTargetFilename = m_strSourceDirectory;
- m_strSourceProcFile = m_strTargetFilename;
-
- string str;
-
-
- m_strSourceProcFile += argv[1];
-
-
- str = (argc > 2 ? argv[2] : T_DEFAULT_OUTPUT_NAME);
- m_strTargetFilename += str;
-
- memset(pathBuff, 0, sizeof(pathBuff));
- lstrcpy(pathBuff, m_strTargetFilename.c_str());
-
- while (lstrlen(pathBuff)>1 && pathBuff[lstrlen(pathBuff)-1]!=_T('\\'))
- pathBuff[lstrlen(pathBuff)-1] = 0; // uotput directory
-
- m_strOutputDirectory = pathBuff;
-
- if ( StrStr( str.c_str(), T_DBF_EXTENSION)==NULL ) {
- setLastErrorIndex(_T("Wrong params"), WRONG_ARGS);
- return false;
- }
-
- m_strTableName = str.substr(0, str.length()-4);//m_strTargetFilename.substr(0, m_strTargetFilename.
- if (argc > 3)
- m_strTableName = argv[3];// : T_DEFAULT_TABLE_NAME);
-
- m_strDSN = (argc > 4 ? argv[4] : T_DEFAULT_DSN);
- m_strDSN += m_strTableName;
- m_strDSNDriver = (argc > 5 ? argv[5] : T_DEFAULT_DRV);
- m_strDSNParams = (argc > 6 ? argv[6] : T_DEFAULT_DSN_PARAMS);
-
-
- m_nSkipBytesBeforeEachRecord = (argc > 6 ? atol(argv[7]) : T_DEFAULT_SKIP_BEFORE);
- m_nSkipBytesAfterEachRecord = (argc > 7 ? atol(argv[8]) : T_DEFAULT_SKIP_AFTER);
-
-
- // replacing %WORKDIR% template
- if ( StrStr( m_strDSNParams.c_str(), T_WORKDIR)!=NULL )
- m_strDSNParams.replace(m_strDSNParams.find( T_WORKDIR ), lstrlen(T_WORKDIR), m_strSourceDirectory);
-
- if ( StrStr( m_strDSNParams.c_str(), T_TARGETDIR)!=NULL )
- m_strDSNParams.replace(m_strDSNParams.find( T_TARGETDIR ), lstrlen(T_TARGETDIR), m_strOutputDirectory);
-
- if ( StrStr( m_strDSNParams.c_str(), T_WORKDSN)!=NULL )
- m_strDSNParams.replace(m_strDSNParams.find( T_WORKDSN ), lstrlen(T_WORKDSN), m_strDSN.c_str());
- //if ( StrStr( m_strDSNParams.c_str(), T_TABLENAME)!=NULL )
- // m_strDSNParams.replace(m_strDSNParams.find( T_TABLENAME ), lstrlen(T_TABLENAME), m_strTableName.c_str());
-
- // and now we showing all our options "verbosely"
- mcout << _T("Source file: ") << m_strSourceProcFile.c_str() << endl;
- mcout << _T("Target file: ") << m_strTargetFilename.c_str() << endl;
- mcout << _T("DSN: ") << m_strDSN.c_str() << endl;
- mcout << _T("Driver: ") << m_strDSNDriver.c_str() << endl;
- mcout << _T("Parameters: ") << m_strDSNParams.c_str() << endl;
- mcout << _T("Table: ") << m_strTableName.c_str() << endl;
-
- if (!CopyFile(m_strEmptyDbf.c_str(), m_strTargetFilename.c_str(), false) ) {
- mcout << _T("Source: ") << m_strEmptyDbf.c_str() << endl;
- mcout << _T("Target: ") << m_strTargetFilename.c_str() << endl;
- setLastErrorIndex(_T("Cannot create default file from empty file"), IO_FILE_NOT_FOUND);
- return false;
- }
-
- return true;
- }
- };
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- mcout << SZ_T_COPYRIGHT_INFO << endl;
-
- APPLICATION application(argc, argv);
- if (application.status()!=S_OK) {
- return application.reportError();
- // application.m_nErrorCode;
- }
-
- //return 0;
-
- // readCommandLine called
- if (! SQLConfigDataSource(NULL, ODBC_ADD_DSN, application.m_strDSNDriver.c_str(), application.m_strDSNParams.c_str()) ) {
- mcout << _T("Cannot create specified dsn") << endl;
- return SQL_DSN_CONFIG_ERROR;
- }
-
- mcout << _T("Loading ") << application.m_strIniFile.c_str() << _T("...") << endl;
-
- if (!application.ReadConfig( application.m_strIniFile ))
- return application.reportError();
-
- if (!application.InitODBC( ))
- return application.reportError();
-
- _ASSERT(argv[2]);
- mcout << _T("\tProcessing: ") << application.m_strSourceProcFile.c_str() << endl;
-
- if (!application.ProcessTextFile( application.m_strSourceProcFile.c_str() ))
- return application.reportError();
-
- // exit(0);
- #ifndef DONT_REMOVE_DSN
- if (! SQLConfigDataSource(NULL, ODBC_REMOVE_DSN, application.m_strDSNDriver.c_str(), application.m_strDSNParams.c_str()) )
- mcout << _T("Cannot remove specified dsn") << endl;
- // else
- // mcout << _T("User's DSN successfully removed") << endl;
- #endif
- #ifdef DEVELOPPER_STAGE
- wint_t ch;
- cout << "done" << endl;
- ch = NULL;
- ch = getwchar();
- #endif
-
- //int retCode = application->m_nErrorCode;
- return 0;}
Конечно, я не силен в С++, поэтому просьба особо критично не оценивать (и сразу извиняюсь за недостаток комментариев в исходном коде, как-нибудь обязательно займусь).
Кроме основного исполняемого-файла понадобятся файл инициализации, пустой файл таблицы, ну и конечно же сам текстовый файл с данными.
Для примера я выкладываю полный архив включающий все что только можно:
Скачать собранный проект (14 Кб) (включает в себя также скомпилированную программу)
добавлю еще пару замечаний к "проекту" :)
- из-за спешки я не отлаживал UNICODE-вариант компиляции
- если вы собираетесь компилировать ее свободным компилятором GNU или используя бесплатную IDE DevCpp ну или что-то подобное - у вас могут возникнуть сложности:
- Если проект не работает с precompiled header - нунжо убрать включение файла "stdafx"
- Если линковщик ругается на отсутствующую функцию main - переименуйте "_tmain" в "main"
- Возможно, придется избавится от блоков директив "ifdef UNICODE..." и таким образом полностью избавиться от использования tchar/TCHAR/-типов wchar и макросов _T/TEXT/L и пр. Проще всего сменить их все char наверное :)

0 коммент.:
Отправить комментарий