• Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе

    «Анализ защищенности веб-приложений»

    🔥 Записаться бесплатно!

  • CTF с учебными материалами Codeby Games

    Обучение кибербезопасности в игровой форме. Более 200 заданий по Active Directory, OSINT, PWN, Веб, Стеганографии, Реверс-инжинирингу, Форензике и Криптографии. Школа CTF с бесплатными курсами по всем категориям.

Проблема с кодировкой в БД Paradox

  • Автор темы SVAN
  • Дата начала
Статус
Закрыто для дальнейших ответов.
S

SVAN

Господа, возникла следующая проблема:

имеется некоторое приложение которое работает с двумя БД (базы соответственно в PARADOX) через BDE, назовем их A_DB и B_DB, с помошью компонента TBatchMove переношу данные из таблицы aTable, которая находится в базе A_DB в таблицу bTable, которая находится в базе B_DB (таблицы имеют одинаковую структуру). При копировании используется функция следующего вида

Код:
bool TDDataModule::copyRecordInArchive(const AnsiString &aliasName, TDataSet *jDS, TJournals j)
{
if (!jDS)
 return false;
if (j == NJournals::JdscCS)
 TabArchive->TableName = "JdscCS";
else
 if (j == NJournals::Jesmc)
 TabArchive->TableName = "Jesmc";
 else
 return;
TabArchive->DatabaseName = aliasName;
BMArchive->Mode = batCopy;
BMArchive->Source = dynamic_cast<TBDEDataSet *>(jDS);
if (!BMArchive->Source)
 return;
BMArchive->Destination = TabArchive;
try
 {BMArchive->Execute();}
catch(...)
 {return false}
return true;
}

Все работает нормально, кроме того что все данные, хранящиеся в таблице aTable в виде строк из русскоязычных символов, например "Объект" переносятся в таблицу bTable в виде "######". С латинскими символами все нормально.
Пробовал вместо TBatchMove использовать оператор INSERT вида

Код:
INSERT INTO ":aliasB_DB:bTable" (Id, Name, Object)
SELECT (Id, Name, Object) FROM ":aliasA_DB:aTable"

таже самая ситуация.
Кто сталкивался, подскажите что можно сделать, чтобы избавиться от проблемы с кодировками.
 
D

DITR

Попробуйте использовать ADO или ODBC - там свои внутренние перекодировщики есть или используйте промежуточный буфер для декодирования из codepage 866 -> 1251 и назад

//(codepage 866 -> 1251)
CString CPlaschadkaDlg::WINConvert( CString m_strDescr )
{unsigned char ch, chVal;

for ( int i=0; i<m_strDescr.GetLength(); i++ )
{chVal = (unsigned char)m_strDescr.GetAt(i);

if(chVal == 44)
m_strDescr.SetAt(i, 46);

if ( chVal >= 128 && chVal <= 159 )
m_strDescr.SetAt(i, chVal + 64 );// += 64;
if ( chVal >= 160 && chVal <= 175 )
m_strDescr.SetAt(i, chVal + 64);// += 64;
if ( chVal >= 224 && chVal <= 239 )
m_strDescr.SetAt(i, chVal + 16);// += 16;
}

return m_strDescr;
}
или
 
G

Guest

Спасибо за совет, надо будет попробовать копировать данные из одной таблицы в другую, используя ADO. Проблему с кодировками я решил следующим образом: У класса TTable есть метод
Код:
InsertRecord(const System::TVarRec * Values, const int Values_Size),
наследуемый от TDataSet. В качестве параметра передаем ему запись, взятую из набора данных, который нужно скопировать (если интересно, можно посмотреть документацию к TDataSet в Builder). Как ни странно, все нормально работает и никаких проблем с кодировками не возникает.
 
D

DITR

Так для работы с любой базой данных я использую ADO - принцип работы - на мой взгляд - очень прост. Приведу код на VC++

Код:
//В stdafx.h 
//полный путь к msado15.dll на диске у меня в data каталоге
#import "data\msado15.dll" \ 
 no_namespace rename("EOF", "EndOfFile")


// в файле реализации 
struct HandleCOM
{
HandleCOM() { ::CoInitialize(NULL); }
~HandleCOM() { ::CoUninitialize();  }
} _HandleCOM_;

inline void TESTHR(HRESULT _hr) { if FAILED(_hr) _com_issue_error(_hr); }
void PrintComErrorCh(_com_error &e);
void PrintProviderErrorCh(_ConnectionPtr pConnection);

void PrintComErrorCh(_com_error &e)
{int iCur = 0;
char chError[MAX_PATH];
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());

iCur += wsprintf(chError + iCur, "Error\n");
iCur += wsprintf(chError + iCur, "\tCode = %08lx\n", e.Error());
iCur += wsprintf(chError + iCur, "\tCode meaning = %s\n", e.ErrorMessage());
iCur += wsprintf(chError + iCur, "\tSource = %s\n", (LPCSTR) bstrSource);
iCur += wsprintf(chError + iCur, "\tDescription = %s\n", (LPCSTR) bstrDescription);

AfxMessageBox(chError);

}

void PrintProviderErrorCh(_ConnectionPtr pConnection)
{int iCur = 0;
char chError[MAX_PATH];
// Print Provider Errors from Connection object.
// pErr is a record object in the Connection's Error collection.
ErrorPtr pErr = NULL;
if( (pConnection->Errors->Count) > 0)
{
long nCount = pConnection->Errors->Count;
// Collection ranges from 0 to nCount -1.
for(long i = 0; i < nCount; i++)
{
pErr = pConnection->Errors->GetItem(i);
wsprintf(chError, "Error number: %x\t%s\n", pErr->Number,
 (LPCSTR) pErr->Description);
AfxMessageBox(chError);
}
}
};


//Connection string
//для аксеса
m_Conn=_T("Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/<path>/store.mdb");
//для DBF
m_Conn=_T("Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277; Dbq=E:\\<path>\\GrodnoOnLine_1");
//для SQL Server 
m_Conn=_T("Provider=SQLOLEDB.1;Data Source=(local);"
   "Initial Catalog=myDatabaseName;"
   "User ID=myUsername;Password=myPassword;");

//функция запроса
AnyFonction
{_RecordsetPtr pRs = NULL;
int i = 0;
float fTatal = 0, fPr = 0;
m_Qry = _T("SELECT* FROM ITEMS");

try
{
TESTHR(pRs.CreateInstance(__uuidof(Recordset))); 
pRs->CursorType = adOpenStatic;
pRs->CursorLocation = adUseClient;
pRs->Open(m_Qry, m_Conn, adOpenStatic, adLockBatchOptimistic, adCmdText);

while(!(pRs->EndOfFile))
{
 m_lIDDept 	= pRs->GetFields()->GetItem("IDDept")->GetValue();
 m_lIDItem 	= pRs->GetFields()->GetItem("IDItem")->GetValue();
 m_strBarCode = (char*) ((_bstr_t) pRs->GetFields()->GetItem("BarCode")->GetValue());
 m_strEcrCode = (char*) ((_bstr_t) pRs->GetFields()->GetItem("EcrCode")->GetValue());
 m_strInternalCode	= (char*) ((_bstr_t) pRs->GetFields()->GetItem("InternalCode")->GetValue());
 m_strDescription	= (char*) ((_bstr_t) pRs->GetFields()->GetItem("Description")->GetValue());
 m_strDescriptionCR	= (char*) ((_bstr_t) pRs->GetFields()->GetItem("DescriptionCR")->GetValue());
 m_iCondition = pRs->GetFields()->GetItem("Condition")->GetValue();
 m_fPrice1 	= pRs->GetFields()->GetItem("Price1")->GetValue();
//  m_fQuantity 	= pRs->GetFields()->GetItem("Quantity")->GetValue();

 m_ctrlItemEdit.AddSearchString(m_strBarCode);
 pRs->MoveNext();
}

pRs->Close();

}
catch(_com_error &e)
{_variant_t vtConnect;

vtConnect = pRs->GetActiveConnection();

switch(vtConnect.vt)
{
 case VT_BSTR:
 	PrintComErrorCh(e);
 break;
 case VT_DISPATCH:
 	PrintProviderErrorCh(vtConnect);
 break;
 default:
 	printf("Errors occured.");
 break;
}
}
}

юзайте тег
Код:
 
G

Guest

Большое спасибо за пример. Обязательно попробую использовать, а я в Builder обычно использую TADOConnection, TADODataSet и другие классы для работы с ADO.
 
S

Shader88

Для: SVAN

Привет! :)

Я тут не много запоздало..... :(

Вообще у меня есть модуль писанный правда на Pascale, но читает все без косяков..... :)

Если надо обращайся солью..... :)

Успехов! :)
 
G

Guest

Привет, если не можешь, вышли пожалуйста пожалуйста исходники на SVAN@pochtamt.ru. Интересно очень посмотреть, заранее благодарен.
 
G

Guest

<!--QuoteBegin-Guest+9:02:2006, 15:21 -->
<span class="vbquote">(Guest @ 9:02:2006, 15:21 )</span><!--QuoteEBegin-->Привет, если не можешь, вышли пожалуйста пожалуйста исходники на SVAN@pochtamt.ru. Интересно очень посмотреть, заранее благодарен.
[snapback]30391" rel="nofollow" target="_blank[/snapback]​
[/quote]

То есть, если можешь :)
 
B

bpiter

Так для работы с любой базой данных я использую ADO - принцип работы - на мой взгляд - очень прост. Приведу код на VC++

Хочю успокоить :rolleyes:. Это класно расписано. Но в Билдере всё проще.
Никаких путе прописывать ненужно.

В ADOConnection компоненте указываешь Build->Melkosoft Jet 4.0 OLE DB Provider.
Это дает твоему приложению мультисовместимость со всеми версиями Винды. Даже 95.
Я сам проверял - подключил MDB-файл базы Access 2003 без установленого Офиса или Аксеса.
Глюков нет вообще. Правда ключи (после ввода) обновлять нужно почаще, а то начинает таблица сыпаться - то данных не запоминает, то непонятные ошибки выдает. А если это основное правило соблюдать, то не будет ни глюков, ни головной боли. Кстати я очень уважаю Мелкософт за такой подарок всем программистам. В базе/файле можно создавать немеряное количество таблиц. Я делал около 50 шт. и всё работало без тормозов. Каждая таблица может содержать более 10 млн. записей (этого я не проверял, но люди говорят, что это вранье). Также необходимо иногда делать компрессию таблиц в Аксесе. Это ускоряет работу. Кстати, я видел несколько функций как делать сжатие, но из моих программ этого добиться не смог. Так, что если кто знает как это делать, киньте мне на мыло исходничек. Буду очень благодарен. :)

Ну, дальше я покажу код подключения базы (отлаженный листинг формы с календарем "Unit2.cpp" - вводиш дату создается база за год методом копирования из резервного файла):

Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm2::Button1Click(TObject *Sender)
{
Form1->Panel3->Caption=FormatDateTime("dd.mm.yyyy",CDate->Date);

AnsiString sFDB=ExtractFileDir(ParamStr(0))+"\\"+FormatDateTime("yyyy",CDate->Date)+".mdb";
AnsiString sFDef=ExtractFileDir(ParamStr(0))+".\\p_default.mdb";

if(!FileExists(sFDB))
{
if(!FileExists(sFDef))Application->Terminate();
else
{
if(!CopyFile(sFDef.c_str(), sFDB.c_str(), true))
{
ShowMessage("Не можу створити нову базу даних!");
Application->Terminate();
}
else
{
Form1->TNew->Active=false;
Form1->TLists->Active=false;
Form1->TFilters->Active=false;
Form1->QBaza->Active=false;
Form1->TMKX->Active=false;
Form1->TConf->Active=false;

Form1->ADOConnection1->Connected=false;

Form1->ADOConnection1->ConnectionString=  "Provider=Microsoft.Jet.OLEDB.4.0;"
"Password=;User ID=Admin;Data Source="+sFDB+";"
"Mode=ReadWrite;Extended Properties=;"
"Jet OLEDB:System database=;Jet OLEDB:Registry Path=;"
"Jet OLEDB:Database Password=;Jet OLEDB:Engine Type=4;"
"Jet OLEDB:Database Locking Mode=0;"
"Jet OLEDB:Global Partial Bulk Ops=2;"
"Jet OLEDB:Global Bulk Transactions=1;"
"Jet OLEDB:New Database Password=;"
"Jet OLEDB:Create System Database=False;"
"Jet OLEDB:Encrypt Database=False;"
"Jet OLEDB:Don't Copy Locale on Compact=False;"
"Jet OLEDB:Compact Without Replica Repair=False;"
"Jet OLEDB:SFP=False";

Form1->ADOConnection1->Connected=true;

Form1->TNew->Active=true;
Form1->TLists->Active=true;
Form1->QBaza->Active=true;
Form1->TFilters->Active=true;
Form1->TMKX->Active=true;
Form1->TConf->Active=true;

Form1->Panel5->Caption=IntToStr(Form1->QBaza->RecordCount);
}
}
}
else
{
Form1->TNew->Active=false;
Form1->TLists->Active=false;
Form1->TFilters->Active=false;
Form1->QBaza->Active=false;
Form1->TMKX->Active=false;
Form1->TConf->Active=false;

Form1->ADOConnection1->Connected=false;

Form1->ADOConnection1->ConnectionString=  "Provider=Microsoft.Jet.OLEDB.4.0;"
"Password=;User ID=Admin;Data Source="+sFDB+";"
"Mode=ReadWrite;Extended Properties=;"
"Jet OLEDB:System database=;Jet OLEDB:Registry Path=;"
"Jet OLEDB:Database Password=;Jet OLEDB:Engine Type=4;"
"Jet OLEDB:Database Locking Mode=0;"
"Jet OLEDB:Global Partial Bulk Ops=2;"
"Jet OLEDB:Global Bulk Transactions=1;"
"Jet OLEDB:New Database Password=;"
"Jet OLEDB:Create System Database=False;"
"Jet OLEDB:Encrypt Database=False;"
"Jet OLEDB:Don't Copy Locale on Compact=False;"
"Jet OLEDB:Compact Without Replica Repair=False;"
"Jet OLEDB:SFP=False";

Form1->ADOConnection1->Connected=true;

Form1->TNew->Active=true;
Form1->TLists->Active=true;
Form1->QBaza->Active=true;
Form1->TFilters->Active=true;
Form1->TMKX->Active=true;
Form1->TConf->Active=true;

Form1->Panel5->Caption=IntToStr(Form1->QBaza->RecordCount);
}

if (Form1->TConf->Active==true)
{
Form1->TConf->First();

while(!Form1->TConf->Eof)
{
if(Form1->TConf->FieldByName("Command")->AsString=="RAYON")
{
if(Form1->TConf->FieldByName("Name")->AsString!="")
{
Form1->Panel8->Caption=Form1->TConf->FieldByName("Name")->AsString;
Form1->Panel6->Caption=Form1->TConf->FieldByName("Size")->AsString;
//Form1->Panel5->Caption=IntToStr(Form1->QBaza->RecordCount);
}
else
{
Form1->Panel8->Caption="Не вибрано район!";

}
}

Form1->TConf->Next();
}
Form1->Panel5->Caption=IntToStr(Form1->QBaza->RecordCount);
Form1->TConf->First();
}

if (Form1->TNew->Active==true)
{
Form1->TNew->First();
int i=0;
while(!Form1->TNew->Eof)
{
if(Form1->TNew->FieldByName("Table")->AsString!="")
{
Form1->QBaza->Fields->Fields[i]->DisplayLabel=Form1->TNew->FieldByName("Name")->AsString;
Form1->QBaza->Fields->Fields[i]->Visible=Form1->TNew->FieldByName("Visible")->AsBoolean;
Form1->QBaza->Fields->Fields[i]->DisplayWidth=Form1->TNew->FieldByName("Table_SIZE")->AsInteger;
}
//else Form1->QBaza->Fields->Fields[i]->Visible=false;
Form1->TNew->Next();
i++;
}
Form1->TNew->First();
}

Close();
}
//---------------------------------------------------------------------------
 
M

malor

Я создаю строку ConnectionString у компонента ADOConnection. На вкладке поставщик данных выбрал Microsoft Jet 4.0 OLE DB Provider. Жму 'Далее', 'Выберите или введите имя базы данных:' - жму кнопку с троеточием, иду по дереву каталогов до того места, где у меня лежит табличка Paradox(создавал в Database Desktop). Но добравшись до нужной папки файла там нет, т.к. внизу в Типе файлов(подлежащих отображению) написано 'Базы данных Microsoft Access (*.mdb)'. Если сменить на 'Все файлы', то конечно я увижу файлы моей таблицы. Если выберу свой файл namefile.db, затем стеру слово Admin в графе 'Пользователь' и нажму 'Проверить подключение', то выдаст:"Не выполнена проверка подключения при инициализации поставщика. Нераспознаваемый формат базы данных:'C:\pathtofile\namefile.db'"
Что делать?

Delphi 7, WinXP
 
B

bpiter

Я создаю строку ConnectionString у компонента ADOConnection. На вкладке поставщик данных выбрал Microsoft Jet 4.0 OLE DB Provider. Жму 'Далее', 'Выберите или введите имя базы данных:' - жму кнопку с троеточием, иду по дереву каталогов до того места, где у меня лежит табличка Paradox(создавал в Database Desktop). Но добравшись до нужной папки файла там нет, т.к. внизу в Типе файлов(подлежащих отображению) написано 'Базы данных Microsoft Access (*.mdb)'. Если сменить на 'Все файлы', то конечно я увижу файлы моей таблицы. Если выберу свой файл namefile.db, затем стеру слово Admin в графе 'Пользователь' и нажму 'Проверить подключение', то выдаст:"Не выполнена проверка подключения при инициализации поставщика. Нераспознаваемый формат базы данных:'C:\pathtofile\namefile.db'"
Что делать?

Delphi 7, WinXP

Хм... Мой метод пригоден только для Аксесовских таблиц... Даный тип таблиц я рекомендую использовать исключитьельно из своего жизненного опыта. Так-как Парадоксовские таблицы очень капризные и часто сыпятся с полной потерей данных. Тем более, что нет методов и компонентов, которые делали бы Парадоксовскую баз автономной на компьютерах, где отсутствуют необходимые драйвера. Короче, на каждый комп, куда ставишь базу, нужно тянуть 50 Мб дров, которые "геморно" нужно устанавливать прописывая каждую длл-ку... мдя... если есть желание, то работайте и дальше с Парадоксом. Для подключения таблицы нужно всего два компонента "Table" и "DataSource". Если таблица и программа в одной папке то путь к базе можно сделать относительным... хотя... это срабатывает в Парадоксе не очень часто...
 
B

bpiter

Я создаю строку ConnectionString у компонента ADOConnection. На вкладке поставщик данных выбрал Microsoft Jet 4.0 OLE DB Provider. Жму 'Далее', 'Выберите или введите имя базы данных:' - жму кнопку с троеточием, иду по дереву каталогов до того места, где у меня лежит табличка Paradox(создавал в Database Desktop). Но добравшись до нужной папки файла там нет, т.к. внизу в Типе файлов(подлежащих отображению) написано 'Базы данных Microsoft Access (*.mdb)'. Если сменить на 'Все файлы', то конечно я увижу файлы моей таблицы. Если выберу свой файл namefile.db, затем стеру слово Admin в графе 'Пользователь' и нажму 'Проверить подключение', то выдаст:"Не выполнена проверка подключения при инициализации поставщика. Нераспознаваемый формат базы данных:'C:\pathtofile\namefile.db'"
Что делать?

Delphi 7, WinXP

Хм... Мой метод пригоден только для Аксесовских таблиц... Даный тип таблиц я рекомендую использовать исключитьельно из своего жизненного опыта. Так-как Парадоксовские таблицы очень капризные и часто сыпятся с полной потерей данных. Тем более, что нет методов и компонентов, которые делали бы Парадоксовскую баз автономной на компьютерах, где отсутствуют необходимые драйвера. Короче, на каждый комп, куда ставишь базу, нужно тянуть 50 Мб дров, которые "геморно" нужно устанавливать прописывая каждую длл-ку... мдя... если есть желание, то работайте и дальше с Парадоксом. Для подключения таблицы нужно всего два компонента "Table" и "DataSource". Если таблица и программа в одной папке то путь к базе можно сделать относительным... хотя... это срабатывает в Парадоксе не очень часто...
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!