Hi Chris,
I have now made two different applications: a VO Console application that creates a DBF and reads all DLL files from a directory into a DBF, and a X# application that reads the DBF and compares with the data on the disk.
Unfortunately there are differences. Since I have to stop now until later today, I attach a zip file with both applications.
If you have time, maybe you can find my error.
Wolfgang
Converting VO memo field data to a SQL Db
Converting VO memo field data to a SQL Db
- Attachments
-
- WriteBinary.zip
- (3.31 KiB) Downloaded 45 times
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Converting VO memo field data to a SQL Db
Hi Wolfgang,
That's because the dbf is generated in OEM mode, so you will need to use the appropriate codepage. Just add this in the beginning of your x# code and it should work correctly now (it does on my machine, hopefully it does on yours, too):
LOCAL nCodePage AS INT
nCodePage := (INT)Vulcan.Runtime.State.DosCodePage
AdjustBinaryData.Initialize(Encoding.GetEncoding(nCodepage))
as I said, if everything else works as expected, you will not need to do this manually, the code can read the codepage directly from the dbf instead.
Btw, I just realized that most of the code in the AdjustBinaryData class is redundant and it can be written in a lot more simple way:
#using System.Text
STATIC CLASS AdjustBinaryData
STATIC PRIVATE enc AS Encoding
STATIC CONSTRUCTOR()
Initialize(Encoding.Default)
RETURN
STATIC METHOD Initialize(oEncoding AS Encoding) AS VOID
enc := oEncoding
RETURN
STATIC METHOD BeforeSaveBytes(abInput AS BYTE[]) AS STRING
RETURN enc:GetString(abInput)
STATIC METHOD AfterReadToBytes(cInput AS STRING) AS BYTE[]
RETURN enc:GetBytes(cInput)
END CLASS
Chris
That's because the dbf is generated in OEM mode, so you will need to use the appropriate codepage. Just add this in the beginning of your x# code and it should work correctly now (it does on my machine, hopefully it does on yours, too):
LOCAL nCodePage AS INT
nCodePage := (INT)Vulcan.Runtime.State.DosCodePage
AdjustBinaryData.Initialize(Encoding.GetEncoding(nCodepage))
as I said, if everything else works as expected, you will not need to do this manually, the code can read the codepage directly from the dbf instead.
Btw, I just realized that most of the code in the AdjustBinaryData class is redundant and it can be written in a lot more simple way:
#using System.Text
STATIC CLASS AdjustBinaryData
STATIC PRIVATE enc AS Encoding
STATIC CONSTRUCTOR()
Initialize(Encoding.Default)
RETURN
STATIC METHOD Initialize(oEncoding AS Encoding) AS VOID
enc := oEncoding
RETURN
STATIC METHOD BeforeSaveBytes(abInput AS BYTE[]) AS STRING
RETURN enc:GetString(abInput)
STATIC METHOD AfterReadToBytes(cInput AS STRING) AS BYTE[]
RETURN enc:GetBytes(cInput)
END CLASS
Chris
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Converting VO memo field data to a SQL Db
Hi Chris,
a short note: it works!
I'll complete it that it recognizes the ansi flag of the DBF and post both applications here and on my server. Of course I will add your copyright to the class.
Wolfgang
a short note: it works!
I'll complete it that it recognizes the ansi flag of the DBF and post both applications here and on my server. Of course I will add your copyright to the class.
Wolfgang
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Converting VO memo field data to a SQL Db
Hi Chris,
again: thank you very, very much!
Attached to this message you can find a corrected application for both VO and X# (XIDE export). The XIDE program checks the Ansi flag of the DBF file and initalizes the converter class accordingly.
The only thing I'm missing now is a VO compatible Crypt function that takes and returns a byte array.
And I have uploaded the same zip file to my webserver: https://riedmann.it/download/XS_DBFBinaryRead.zip, completed with your message as readme.
Wolfgang
again: thank you very, very much!
Attached to this message you can find a corrected application for both VO and X# (XIDE export). The XIDE program checks the Ansi flag of the DBF file and initalizes the converter class accordingly.
The only thing I'm missing now is a VO compatible Crypt function that takes and returns a byte array.
And I have uploaded the same zip file to my webserver: https://riedmann.it/download/XS_DBFBinaryRead.zip, completed with your message as readme.
Wolfgang
- Attachments
-
- XS_DBFBinaryRead.zip
- (4.46 KiB) Downloaded 45 times
-
- DBFBinaryRead.zip
- (3.32 KiB) Downloaded 45 times
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Converting VO memo field data to a SQL Db
Hi Wolfgang,
You're welcome, and thanks for testing! Glad to see after so many years that there's an easy solution for that after all.
Btw, the code I posted previously for getting the codepage was a quick and dirty way to do it, assuming the dbf was created in the same machine. Proper way to do it, by using a DBServer obejct is:
#define DBI_CODEPAGE 41
nCodePage := oServer:Info(DBI_CODEPAGE)
AdjustBinaryData.Initialize(Encoding.GetEncoding(nCodepage))
as for a VO-compatible Crypt() that works with a byte array, here it is below:
Chris
FUNCTION CryptByteArray(aBytes AS BYTE[] , cKey AS STRING) AS BYTE[]
LOCAL pKey := String2Psz(cKey) AS PSZ
LOCAL aRet AS BYTE[]
aRet := BYTE[]{aBytes:Length}
FOR LOCAL n := 1 AS INT UPTO aBytes:Length
aRet[n] := aBytes[n]
NEXT
// just make sure the GC does not move the array around
BEGIN FIXED LOCAL pBytes := aRet AS BYTE PTR
Crypt4(pBytes , pKey , (DWORD)aRet:Length , (DWORD)cKey:Length)
END
RETURN aRet
You're welcome, and thanks for testing! Glad to see after so many years that there's an easy solution for that after all.
Btw, the code I posted previously for getting the codepage was a quick and dirty way to do it, assuming the dbf was created in the same machine. Proper way to do it, by using a DBServer obejct is:
#define DBI_CODEPAGE 41
nCodePage := oServer:Info(DBI_CODEPAGE)
AdjustBinaryData.Initialize(Encoding.GetEncoding(nCodepage))
as for a VO-compatible Crypt() that works with a byte array, here it is below:
Chris
FUNCTION CryptByteArray(aBytes AS BYTE[] , cKey AS STRING) AS BYTE[]
LOCAL pKey := String2Psz(cKey) AS PSZ
LOCAL aRet AS BYTE[]
aRet := BYTE[]{aBytes:Length}
FOR LOCAL n := 1 AS INT UPTO aBytes:Length
aRet[n] := aBytes[n]
NEXT
// just make sure the GC does not move the array around
BEGIN FIXED LOCAL pBytes := aRet AS BYTE PTR
Crypt4(pBytes , pKey , (DWORD)aRet:Length , (DWORD)cKey:Length)
END
RETURN aRet
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Converting VO memo field data to a SQL Db
FWIW, "Crypt4" ? If that's no typo, the name is rather "burned", as google knows this as a probably undecryptable trojan <g>Crypt4(pBytes , pKey , (DWORD)aRet:Length , (DWORD)cKey:Length)
END
RETURN aRet
Karl
Regards
Karl
(on Win8.1/64, Xide32 2.20, X#2.20.0.3)
Karl
(on Win8.1/64, Xide32 2.20, X#2.20.0.3)
Converting VO memo field data to a SQL Db
Hi Chris,
great! Thank you!
I have to check the crypt() function next week, or maybe tomorrow, because now I have VO work to do.
Regarding the right encoding: I have added a second static Initialize method the the AdjustBinaryData class:
and have put that class into my VulcanInterface library.
The adjusted sample is both attached to this message and on my download page (it may be easier to find than down here in the forums).
Wolfgang
great! Thank you!
I have to check the crypt() function next week, or maybe tomorrow, because now I have VO work to do.
Regarding the right encoding: I have added a second static Initialize method the the AdjustBinaryData class:
Code: Select all
static method Initialize( oServer as Vulcan.VO.DbServer ) as void
local nCodePage as int
nCodePage := oServer:Info( DBI_CODEPAGE )
_oEncoding := Encoding.GetEncoding( nCodepage )
return
The adjusted sample is both attached to this message and on my download page (it may be easier to find than down here in the forums).
Wolfgang
- Attachments
-
- XS_DBFBinaryRead.zip
- (4.4 KiB) Downloaded 53 times
-
- XS_DBFBinaryRead.zip
- (4.52 KiB) Downloaded 45 times
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Converting VO memo field data to a SQL Db
Hi Karl,
Heh, didn't know that! No, it's just the Crypt() function, but the strongly typed version with 4 params, thus the "4" in the name. Similar to SubStr2(), SubStr3() etc.
Chris
Heh, didn't know that! No, it's just the Crypt() function, but the strongly typed version with 4 params, thus the "4" in the name. Similar to SubStr2(), SubStr3() etc.
Chris
Chris Pyrgas
XSharp Development Team
chris(at)xsharp.eu
XSharp Development Team
chris(at)xsharp.eu
Converting VO memo field data to a SQL Db
Hi Karl,
this function is defined in the VulcanRTFuncs library (says at least XIDE...)
Wolfgang
I was curious too, and XIDE showed me the prototype:
this function is defined in the VulcanRTFuncs library (says at least XIDE...)
Wolfgang
I was curious too, and XIDE showed me the prototype:
Wolfgang Riedmann
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
Meran, South Tyrol, Italy
wolfgang@riedmann.it
https://www.riedmann.it - https://docs.xsharp.it
-
- Posts: 248
- Joined: Fri Oct 14, 2016 7:09 am
Converting VO memo field data to a SQL Db
Hi Chris,
Thanks for your input in this. I seem to have a slightly different issue as well.
For some unknown reason the original developers of our app chose to use RDDINFO(_SET_MEMOBLOCKSIZE,31). I include a call to this in my XSharp code, but I get a runtime error from the Vulcan assemblies when I try to do a FieldGet on the memo field. If I edit the DBF to use memoblock size 32 and remove the call to RDDINFO, then I can read the memofield correctly. The error is not very informative...
Vulcan.NET Runtime Error
Error Code: 0 [Unknown error]
Subsystem:
Function: FIELDGET
Call Stack:
at Vulcan.Error.Throw(__Usual[] $args)
at VulcanRTFuncs.Functions.DefError(Error oError)
at Codeblocks.$CB_$Error$_930_22.Eval(__Usual[] <evalargs>)
at VulcanRTFuncs.Functions.Eval(Codeblock cbCodeBlock, __Usual[] args)
at Vulcan.VO.DbServer.Error(__Usual[] $args)
at Vulcan.VO.DbServer.FIELDGET(__Usual[] $args)
at TestQW10.Exe.Functions.Start() in: C:UsersNickDocuments.....
Any ideas? Thanks
Nick
Thanks for your input in this. I seem to have a slightly different issue as well.
For some unknown reason the original developers of our app chose to use RDDINFO(_SET_MEMOBLOCKSIZE,31). I include a call to this in my XSharp code, but I get a runtime error from the Vulcan assemblies when I try to do a FieldGet on the memo field. If I edit the DBF to use memoblock size 32 and remove the call to RDDINFO, then I can read the memofield correctly. The error is not very informative...
Vulcan.NET Runtime Error
Error Code: 0 [Unknown error]
Subsystem:
Function: FIELDGET
Call Stack:
at Vulcan.Error.Throw(__Usual[] $args)
at VulcanRTFuncs.Functions.DefError(Error oError)
at Codeblocks.$CB_$Error$_930_22.Eval(__Usual[] <evalargs>)
at VulcanRTFuncs.Functions.Eval(Codeblock cbCodeBlock, __Usual[] args)
at Vulcan.VO.DbServer.Error(__Usual[] $args)
at Vulcan.VO.DbServer.FIELDGET(__Usual[] $args)
at TestQW10.Exe.Functions.Start() in: C:UsersNickDocuments.....
Any ideas? Thanks
Nick