 |
|
 |
I have to say, this is the best chance I have at getting my code to work with a Paradox 7 database. One thing I really need is support for boolean data types. It pulls all booleans out as false. Any chance you or anyone know anything about how to add this to this already awesome dll?
|
|
|
|
 |
|
 |
I updated the db class to change the way the code evaluates booleans:
case ParadoxFieldTypes.Logical:
val = Convert.ToBoolean(this.block.data[(int)buff.Position] - 128);
buff.Position += dataSize;
break;
|
|
|
|
 |
|
 |
Hi there,
I am implementing a synchronization tool that reads records from a Paradox 7 database and adds them to an Oracle database. Your Paradox reader has been a great help so far, as I did not find any other way to access the paradox data.
With one table of the Paradox database I have some problems.
a big table with more than 600000 entries is read fine except there are 20 rows in between where there is an error like this:
ERROR in pLogData: processParadoxQuery failed: System.InvalidCastException: Specified cast is not valid.
at ParadoxReader.ParadoxPrimaryKey.d__b.MoveNext() in C:\Users\####\Desktop\visualstudio\ParadoxReader\Index.cs:line 47
at ParadoxReader.ParadoxPrimaryKey.d__b.MoveNext() in C:\Users\####\Desktop\visualstudio\ParadoxReader\Index.cs:line 48
at ParadoxReader.ParadoxDataReader.Read() in C:\###\ParadoxReader\Impl.cs:line 192
at ParadoxSync.ParadoxTableOracle.processParadoxQuery(ParadoxDataReader rdr) in
################
I am wondering if either you, Petr, or someone else could help me investigating this further. I could give away a copy of the database, too.
Warm regards,
Johannes
modified 21 May '12.
|
|
|
|
 |
|
 |
My Vote of 5 - the first .NET application I have seen to actually get some data out of my Paradox databases.
|
|
|
|
 |
|
 |
Although it does not work on all of my Paradox tables.
|
|
|
|
 |
|
 |
if to extend this function:
private void ReadHeader()
{
.....
for (int i = 0; i < 0x64; i++)
{
if (r.ReadChar() == 'D')
{
break;
}
}
r.ReadBytes(8); var indexNameBuff = r.ReadBytes(16); indexName = Encoding.ASCII.GetString(indexNameBuff, 0, Array.FindIndex(indexNameBuff, b => b == 0));
}
Then indexName can have the name of secondary index
modified 13 Mar '12.
|
|
|
|
 |
|
 |
From an old delphi project I need to read encrypted paradox 7 tables. Any idea how to implement encoding algorithm for a known password?
With best regards - Ulrich
|
|
|
|
 |
|
 |
Hi,
I had an issue with the codepage / character encoding used in my Paradox DB and could fix it.
I was trying to open a DB with german umlauts and special characters (ß,ö,ü,ä etc.). When trying to so the
while ((ch = r.ReadChar()) != '\x00') fldNameBuff.Append(ch);
command in DB.cs (around line 240 in ReadHEader()) threw an ArgumentException from somewhere deep down.
I could fix this by providing the BinaryReader() constructor inside the ParadoxFile() constructor with the encoding of the DB I used.
It looks like this:
public ParadoxFile(Stream stream)
{
this.stream = stream;
this.reader = new BinaryReader(stream,Encoding.GetEncoding("Windows-1252"));
stream.Position = 0;
this.ReadHeader();
}
Perhaps somebody needs this.
And now for the praise
This is real great work of yours. I spent 3-4 hours fighting against connection strings and googling for a solution for reading my Paradox DB without OleDB in .NET or delivering Borland DLLs. You saved my day.
Thanks a lot!
Ben
|
|
|
|
 |
|
 |
First of all, thank you for the great work!
I’m trying to read a table using its index file (.PX) and find some problems (perhaps some bugs).
1. I wondered why the field ParadoxCondition.Compare.IndexFieldIndex is never used. So, I think that the array indexes in the lines 96 and 101 of the file Index.cs are not DataFieldIndex but IndexFieldIndex instead.
2. My table has a SortOrder = 0x4C (? not documented). In this SortOrder the word “cwClaTit” comes before “cwacerel”, i.e. “Z” comes before “a”. So the method used to compare the value to search with the value in the index table does not work. I change the Comparer.Default.Compare(val1, this.Value) with CultureInfo.InvariantCulture.CompareInfo .Compare(val1.ToString(), this.Value.ToString(), CompareOptions.Ordinal) and it works as expected. I think that this part of the code must be specific to each possible SortOrder.
|
|
|
|
 |
|
 |
Thanks, great work!
But I found one bug
GetString method currently seeks end of string by finding first zero byte from start of the string.
In my tests it worked incorrectly finding end of string far to long after its end.
I changed this method in my copy with this:
public string GetString(byte[] data, int from, int len)
{
string res= Encoding.GetEncoding(866).GetString(data, from, len);
return res;
}
and its usage changed to:
val = this.block.file.GetString(this.block.data, (int)buff.Position, dataSize);
|
|
|
|
 |
|
 |
I have to put this on your "fix" or i'm getting |||||||||||||||||||||| in my string blob
string res= Encoding.GetEncoding(0).GetString(data, from, len);
int i = res.IndexOf('\0');
if (i > 0){
res = res.Substring(0,i);
}
return res;
I have to change to GetEncoding(0) because i'm losing accent of my french data !
thanks to all for this great library.
|
|
|
|
 |
|
|
 |
|
 |
Actually I addressed this bug back on Jan 1. Check out the comments below, there have been lots of fixes and additions made to this project. I think the author may have abandoned it though.
Here was my original fix.
public string GetString(byte[] data, int from, int maxLength)
{
int stringLength = Array.FindIndex(data, from, b => b == 0) - from;
if (stringLength > maxLength)
stringLength = maxLength;
return Encoding.Default.GetString(data, from, stringLength);
}
|
|
|
|
 |
|
 |
Thank you for you GetString fixes, I will use the last one in the article.
|
|
|
|
 |
|
 |
If some one is interested, email me.
|
|
|
|
 |
|
 |
I received an email from Christopher and I'll post my code when it's done because now I have to concentrate in other things.
|
|
|
|
 |
|
 |
I am trying to solve the problem with the BLOB Binary fields but I can't solve it.
I will appreciate any help with this issue.
Thanks a lot in advance.
|
|
|
|
 |
|
 |
I have this data in .DB about BLOB field: 63 16 0 0 74 4 0 0 1 0 in hex is 3F 10 0 0 4A 4 0 0 1 0 if I reverse:
0 0 10 3F 0 0 4 4A 0 1
44A=1098 length of the BLOB data (type 03. suballocated ) and the index is 103F??? that is my cuestion because if I have this index it doesn't fix with the address of the fisrts data in .MB, where it is in 1150hex address.
I need any help to see the light.
Thanks a lot in advance.
|
|
|
|
 |
|
 |
I remember that when I followed that link for the paradox4.txt file, I googled a bit and found a pretty good C library to read paradox files. In there was code that helped mevwitg memo fields, and should have blob ad well.
Here we go, it has a function called PX_GET_DATA_BLOB.
Here is the link: http://pxlib.sourceforge.net/index.php
|
|
|
|
 |
|
 |
I saw that lib, I solved. The lib was realy usefull.
|
|
|
|
 |
|
 |
Cool! Maybe you can post your code in the comments here as well. Perhaps over time we can all develop this into a full .net library.
|
|
|
|
 |
|
 |
I will do when I have fully tested, but my solution is only for type 3, suballocated blob type.
|
|
|
|
 |
|
 |
First of all, this is cool library. Thank you guys.
I fought with blob too and solution for Suballocated block is below.
It is not fully error resistant but hope helps.
public byte[] ReadBlob(byte[] blobInfo)
{
if (blobInfo.Length < 10)
return null;
uint OffsetAndIndex = BitConverter.ToUInt32(blobInfo, blobInfo.Length-10); //was 0
uint index = OffsetAndIndex & 0x000000ff;
uint Offset = OffsetAndIndex & 0xffffff00;
int size = BitConverter.ToInt32(blobInfo, blobInfo.Length - 6); //was 4
int hsize = 9;
int mod_nr = BitConverter.ToInt16(blobInfo, blobInfo.Length - 2); //was 8
if (size > 0)
{
this.stream.Position = Offset;
byte[] head;
head = new byte[6];
this.reader.Read(head, 0, 3);
//first byte B
//00 - Header block
//02 - Single blob block
//03 - Suballocated block
//04 - Free block
//following short is number of 4K blocks
//based on _px_get_data_blob in paradox.c library http://pxlib.sourceforge.net/index.php
if (head[0] == 3) //Suballocated block
{
int checks = BitConverter.ToUInt16(head, 1);
byte[] rest;
rest = new byte[9];
this.reader.Read(rest, 0, 9); //read remaining 9 bytes of 12 bytes header
this.stream.Position = Offset + 12 + index * 5; //jump to blob data (header first)
this.reader.Read(head, 0, 5); //read header
if (size != ((int)head[1] - 1) * 16 + head[4])
return null; //Blob does not have expected size
byte[] blobdata;
blobdata = new byte[size];
this.stream.Position = Offset + head[0] * 16;
this.reader.Read(blobdata, 0, size);
return blobdata;
}
viliam
|
|
|
|
 |
|
 |
Hi Petr,
This is a great little class library. Only thing still missing from it is Memo field support but I will see if I can add it myself.
Years ago, I wrote something very similar for xBase. It was a reader/writer with memo field support. You have inspired me to put up an article about it.
I wanted to point out a bug I just found while testing against a database I have. The ParadoxFile class, GetString() method does not respect the maximum string length set by the field. Here is a fix I put in for this.
public string GetString(byte[] data, int from, int maxLength)
{
int stringLength = Array.FindIndex(data, from, b => b == 0) - from;
if (stringLength > maxLength)
stringLength = maxLength;
return Encoding.Default.GetString(data, from, stringLength);
}
UPDATE:
I have figured out how to Parse Logical types, and have a very crude Memo field read, I am embarrassed to even include it, but maybe it helps someone... Unfortunately my database only has a 1 Memofield of size 250 bytes so I can't test large memo reads.
Inside of ParadoxRecord.DateValues {get;}
case ParadoxFieldTypes.MemoBLOb:
val = _block.File.GetStringFromMemo(_block._data, (int) buff.Position, dataSize);
buff.Position += dataSize;
break;
case ParadoxFieldTypes.Logical:
val = (_block._data[(int)buff.Position] - 128) > 0;
buff.Position += dataSize;
break;
and inside of ParadoxFile
public string GetStringFromMemo(byte[] data, int from, int size)
{
var memoBufferSize = size - 10;
var memoDataBuffer = new byte[memoBufferSize];
var memoMetaData = new byte[10];
Array.Copy(data, from, memoDataBuffer, 0, memoBufferSize);
Array.Copy(data, from + memoBufferSize, memoMetaData, 0, 10);
var memoSize = BitConverter.ToInt32(memoMetaData, 4);
return GetString(memoDataBuffer, 0, memoSize);
}
modified on Sunday, January 2, 2011 5:59 AM
|
|
|
|
 |
|
 |
Any help with BLOB fields?
|
|
|
|
 |