Maciej Lipski

Maciej Lipski Senior Software
Engineer

Temat: Problem z plikami dbf

Witam.
Mam pewien problem z wyciaganiem i przetwarzaniem danych pochodzacych z plikow .dbf (dBase III plus). Sposob jakim wyciagam wszystkie dane z pliku:


OleDbConnectionStringBuilder lv_build = new OleDbConnectionStringBuilder();
lv_build.Provider = "Microsoft.Jet.OLEDB.4.0";
lv_build.DataSource = directory_name;
OleDbConnection lv_con = new OleDbConnection(lv_build.ToString() + ";Extended Properties=dBASE IV;");
String l_str_query = "SELECT * FROM " + file_name + ""; //file_name - nazwa pliku
OleDbDataAdapter lv_adap = new OleDbDataAdapter(l_str_query, lv_con);
DataSet lv_ds = new DataSet();
lv_adap.Fill(lv_ds);


I niby wszystko ok, dane sa wyciagniete. Tylko ze polskie znaki, ktore sa w nich sa w formie 'krzaczkow'. Musze z tej bazy wyciagac niektore dane, a niektore zmieniac. Ale niestety nie jestem w stanie wyszukiwac poprawnie, w przypadku gdy w klauzuli selekcji pojawiaja sie krzaczki. To znaczy gdy musze porownac "... WHERE col_1='ążńó'" w przypadku gdy col_1 zawiera krzaczaki, znaki nie sa sobie rowne.

Myslalem ze rozwiazalem problem, robiac cos takiego:

class libEncode
{
private const String lv_src = "windows-1250";
private const String lv_dst = "ibm852";

static public String Get(String str)
{
return Encoding.GetEncoding(lv_dst).GetString(Encoding.GetEncoding(lv_src).GetBytes(str));
}
}

Niby dla niektorych przypadkow dzialalo i moglem robic:


String lv_query = "... WHERE col_1='"+ libEncode.Get("ń") +"'";


No ale jak sie okazalo, jednak tylko dla niektorych polskich znakow trafilem w to kodowanie. Problem pozostal, tylko ze nie moge znalezc kodowania, ktore 'trafi' w te, ktore jest wykorzystane w pliku. Nawet po napisaniu:


String l_str_check = "ąćńół"; //string do sprawdzenia wyciagniety z .dbf, przypisanie ma charakter symboliczny zebyscie wiedzieli co tam jest
foreach (EncodingInfo ei1 in Encoding.GetEncodings())
{
foreach (EncodingInfo ei2 in Encoding.GetEncodings())
{
String l_str_compare = "ąćńół";
l_str_compare = Encoding.GetEncoding(el1.CodePage).GetString(Encoding.GetEncoding(el2.CodePage).GetBytes(l_str_compare));
if(l_str_check.Equals(l_str_compare)) MessageBox.Show("El1: "+ el1.CodePage +" El2: "+ el2.CodePage);
}
}


Wybralem sobie kilka przykladowych kolumn z polskimi znakami, tak zeby sprawdzic jak najwiecej. Napisalem ich odpowiedniki (tak jak w powyzszym przykladzie l_str_compare). No i klops - nie moge znalezc tego kodowania.

Moze to jakos naprowadzi kogos z Was: Sciagnalem tez 3 programy do podgladania plikow .DBF (np DBF Viewer czy DBF Lister (do totalcmd)) i wszystkie poprawnie wyswietlaja polskie znaki. Istnieje tam opcja nazywana "DOS/ANSI" lub "Use OEM characters", ktora zamienia widok z krzaczkow, ktore ja widze, na polskie znaki:

Use OEM characters
Hot key: F12
If set ON use OEM characters


Ma ktos jakies podpowiedzi jak mozna rozwiazac problem, tak, bym mogl swobodnie korzystac z polskich znakow w tym .dbf? Dodam ze nie moge konwertowac tego .dbf na inna strone kodowa - plik .dbf i jego strona kodowa musza zostac nieruszone (sa wykorzystywane przez inny, istniejacy juz program ktorego nie moge modyfikowac).
Maciej Lipski

Maciej Lipski Senior Software
Engineer

Temat: Problem z plikami dbf

Z napisaniem wlasnej funkcji tez mam problem...


class libEncode
{
private const String lv_dbase_src = "ąĄćĆęĘłŁńŃóÓżŻźŹ";
private const String lv_dbase_dst2 = "¦ąŠĂŕ¦-ú˝ĐˇË¬»čĆ";
private const String lv_dbase_dst = "¹¥æÆêʳ£ñÑóÓ¿¯Ÿ";

static public String dBase(String str)
{
for (int i = 0; i < lv_dbase_src.Length; i++)
{
str = str.Replace(lv_dbase_src[i], lv_dbase_dst[i]);
}
return str;
}
}


lv_dbase_dst2 to ciag wyciagniety z DBF Viewer
lv_dbase_dst to ciag wyciagniety z DataSetu do wyciagniecia wszystkiego.
Przy okazji Visual poprosil o zmiane strony kodowej bo nie wszystkie znaki mozna zakodowac.. no i znowu.. wybralem inna strone kodowa i znowu klops. Troche mnie to meczy. Musi byc przeciez inny sposob pracy na tych dbf
Maciej Lipski

Maciej Lipski Senior Software
Engineer

Temat: Problem z plikami dbf

Edit 2:
Dotarlem do funkcji CharToOem oraz OemToChar z user32.dll



[DllImport("user32.dll")]
static extern bool CharToOem(byte[] lpszSrc, byte[] lpszDst);

function void Bum() {
ArrayList done = new ArrayList();
foreach (EncodingInfo ei1 in Encoding.GetEncodings())
{
foreach (EncodingInfo ei2 in Encoding.GetEncodings())
{
foreach (String cur in al) //al zawiera stringi, ktore sam napisalem z polskimi znakami na zasadzie al.Add("ąćń") etc., a ktore odpowiadaja ciagom z .dbf
{
byte[] byt_1 = Encoding.GetEncoding(ei1.CodePage).GetBytes(cur.ToUpper());
byte[] byt_2 = new byte[byt_1.Length];
CharToOem(byt_1, byt_2);
String str = Encoding.GetEncoding(ei2.CodePage).GetString(byt_2);
done.Add(str);
}
}
}
foreach (DataRow cur in ds.Tables[0].Rows) //wartosci z polskimi znakami z DataSet
{
String value = ((String)cur[0]);
if(!done.Contains(value)) {
MessageBox.Show("BRAK: "+ value);
}
else MessageBox.Show("Jest: " + value);
}
}


Ponownie dalem zagniezdzone petle bo juz mi nerwy puszczaja... kolejny raz klapa. Posrod 176 400 roznie zapisanych wersji tych slow, nie znalazly sie takie, ktore by pasowaly...

konto usunięte

Temat: Problem z plikami dbf

nie wiem czy mnie pamiec nie myli ale moze pomoge ci tym troszke
kiedys mialem problem z dbf i polskimi znakami. po ciezkich walkach okazalo sie ze rozwiazaniem byl konwerter mazovia-iso. wiem ze nie mozesz zmienic pliku ale zawsze mozesz konwertowac znaki w locie. jedna rada - sprawdz czy to nie jest mazovia - to moze ci sie przydac dbf_convArtur Słomski edytował(a) ten post dnia 28.11.07 o godzinie 18:29
Maciej Lipski

Maciej Lipski Senior Software
Engineer

Temat: Problem z plikami dbf

Dzieki za odpowiedz, ale niestety nie podzialalo.
Sprobowalem kazda z mozliwosci :P
Zrobilem juz nawet sobie cos takiego:


foreach (EncodingInfo ei1 in Encoding.GetEncodings())
{
foreach (EncodingInfo ei2 in Encoding.GetEncodings())
{
foreach (String cur in al)
{
byte[] byt_1 = Encoding.GetEncoding(ei1.CodePage).GetBytes(cur.ToUpper());
byte[] byt_2 = new byte[byt_1.Length];
CharToOem(byt_1, byt_2);
String str = Encoding.GetEncoding(ei2.CodePage).GetString(byt_2);
done.Add(str);
done.Add(lib.libEncode.Get(cur, ei1.CodePage, ei2.CodePage));
}
}
}


Zebym mial wszystkie rozne mozliwosci zarowno kodowania, jak i tego ChartoOem w jednej liscie i tylko porownuje dane zczytane z .dbf z nimi. Ale jak na razie bezskutecznie...

Byc moze jest lepszy sposob pracy na plikach .dbf. W koncu jakos te zewnetrzne programy dzialaj i to nawet skutecznie. We wszystkich jest ten pstryczek 'OEM (DOS) => ANSI' i spowrotem. Tylko jak to przelozyc na implementacje w C# yhm.

Jakis pomysly?
Tomasz Poradowski

Tomasz Poradowski Specjalista od
wytwarzania
oprogramowania

Temat: Problem z plikami dbf

Maciej Lipski:
Jakis pomysly?
Zajrzyj na http://www.ia.pw.edu.pl/~jurek/js/kody/ i spróbuj dopasować jakie kodowanie zostało użyte. Ew. użyj jakiegoś "detektora" typu tego dołączonego do "iconv".

edit: Z innych pomysłów - użyj innego sterownika.Tomasz Poradowski edytował(a) ten post dnia 28.11.07 o godzinie 22:06

konto usunięte

Temat: Problem z plikami dbf

Co do dbf to:

http://www.clicketyclick.dk/databases/xbase/format/dbf... (żeby sprawdzić kodowanie znaków, prawdopodobnie Mazovia).

Jeżeli chodzi o konwersje w locie, to może Ci się to przydać:
http://en.wikipedia.org/wiki/Mazovia_encoding

Mógłbyś jeszcze poszukać opcji kodowania w "connection stringu" dla danego providera, ale wydaje mi się mało prawdopodobne, żeby była tam możliwość obsługi tak egzotycznego standardu jak Mazovia.

Pozdrawiam,
Tomasz Rolewski

Tomasz Rolewski GET IT Tomasz
Rolewski

Temat: Problem z plikami dbf

Maciej Lipski:
Dzieki za odpowiedz, ale niestety nie podzialalo.
Sprobowalem kazda z mozliwosci :P
Zrobilem juz nawet sobie cos takiego:
Witam ! Walczyłem dziś z podobnym problemem, tylko, że w vb.net. Mam pliki w dbf zakodowane Mazovia. Mam krótki kod ktory zmienia Mazovię na WINDOWS 1250 (podstawia znaki), zainteresowanym wyślę mailem. Jeśli plik dbf otworzę przez providera Provider=vfpoledb.1 to wszystko działa ok, konwersja przechodzi bez problemu. Dla tego providera należy zainstalować VFPOLEDB (darmowy komponent MS). Jeśli natomiast otworzę przez Provider=Microsoft.Jet.OLEDB.4.0 muszę najpierw wykonać konwersję stringu z DBF funkcją z user32.dll CharToOem i moja normalna konwersja z Mazovii na stronę Windows 1250 działa bez problemu.

Następna dyskusja:

problem z serializacja cdata




Wyślij zaproszenie do