Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 414
  • Last Modified:

Using C#, How do I read from a binary file into a struct using a file created by a VB6 application?

I am trying to use C# to read the contents of a binary file written by a VB6 application.  I have used the article "Fast Binary Reading" at  http://www.codeproject.com/cs/files/fastbinaryfileinput.asp as a guide, opting to use the BinaryReader to do a ReadString(), ReadInt64(), etc into the members of a struct patterned after the User Defined Types created in the VB6 application.

When I step through the program, I see a truncated version of, say, the invoice number 0071383.  The  VS 2005 express shows me " \0007138" when I place the pointer over the struct member to see what value it is holding.  However, when I test the output in a messagebox, I  get a blank.  Not even the literal strings I put in MessageBox show.  The value in the invoice date shows as:  "\b\020071002\b\0H       ýýýý\0\0ýý\0\0\0\0ýh\0\0\0\0\0ýh\0\0\0\0\0\0\0\0" when I work in debug mode. Iit is a concat of the date and an employee code ('H').  But, like I say, nothing shows up on the message box.

Code snippet:
    fs = new FileStream(FullPath, FileMode.Open,FileAccess.Read,FileShare.Read );
            br = new BinaryReader(fs);          
            /*  Snippet from article */
            try
            {
              while (br.PeekChar() != -1)
              {
                i06.InvoiceNumber = br.ReadString();
                i06.InvoiceDate = br.ReadString();
                    MessageBox.Show(i06.InvoiceNumber + " The invoice date: " + i06.InvoiceDate , "Invoice Number and Date"); // I come up with blanks here
               break;   // i'm just trying to get one or two successful reads before reading whole file
            } // end while
 ...
}
The VB6 Get method will read a binary file's contents into a user defined type quite easily, even if one of the elements is s UDT.  I'm not really finding a C# equivalent to this.

I am trying just to get these two tiny members to fill the struct elements before I go on.  What do I need to know about C# data types and VB6 data types in order to bring the data in ?   I tried changing the binary reader encoding property, but that did not render any helpful results.  I got either gibberish or blanks.  What might I be missing?
0
ventriculor
Asked:
ventriculor
  • 5
  • 3
2 Solutions
 
Jens FiedererTest Developer/ValidatorCommented:
You only want to use
br.ReadString()
for fields that are actually STRINGS, which these probably are not.

If invoice number is, for example, and Int16, you need to do
br.ReadInt16()
If InvoiceDate is, as seems likely, a Date, you need to understand the VB6 date formats and convert the bytes into a Date (I dont know if they are the same as VB.NET, if they are it is easier).

So you need to know EVERYTHING about the data types you are using in VB6 and .NET for this, and you need to know (or discover) the EXACT layout of your datafile.  Using a hex editor can help with the discovery part.
0
 
hdkellyCommented:
'\0' is called the null terminator and it represents the end of a string. The MessageBox class will only display characters up to the first null terminator it encounters. You might remove the null terminators with something like this:

MessageBox.Show(i06.InvoiceNumber.Replace("\0", "") + " The invoice date: " + i06.InvoiceDate.Replace("\0", "") , "Invoice Number and Date");
0
 
Jens FiedererTest Developer/ValidatorCommented:
i06 is NOT going to have anything meaningful INSIDE it to display if he tries to read into it with his current methods.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
ventriculorAuthor Commented:
The User Defined Type in the VB6 code defines the Invoice number and invoice dates as strings:
  Public Type Transaction Info
    InvoiceNumber As String
    InvoiceDate As String
   ' The Rest of the Type is defined . . .
 End Type
By using the Replace() method, I was able to get the following info to show:
InvoiceDate: \b20071002\bH       ýýýýýýýhýh
InvoiceNumber: 007138
The Invoice number is still incomplete, a 3 belongs after the 8.  The date value is there in the InvoiceDate element, but the Employee code is concatenated onto it with other characters.

The Hex editor shows this for the relevant section:  
00000000h: 07 00 30 30 37 31 33 38 33 08 00 32 30 30 37 31 ; ..0071383..20071
00000010h: 30 30 32 08 00 48 20 20 20 20 20 20 20 FF FF FF ; 002..H       ÿÿÿ
00000020h: FF 00 00 FF FF 00 00 00 00 A0 68 06 00 00 00 00 ; ÿ..ÿÿ.... h.....

So, my question remains, what must I do read  the values in the VB6 created binary files with C#?
0
 
Jens FiedererTest Developer/ValidatorCommented:
OK, it looks like the VB6 String is not the same as the VB.NET String.
FIRST, do a
 length = br.ReadInt16()
call to find how many CHARACTERS are in the string (that will use the "07 00" bytes to get 7)

THEN do a
  chars = br.ReadChars(length)
to get the actial data.

If you had written this string in VB.NET, the hex editor would have shown:
07 30 30 37 31 33 38 33

(without the 00)
0
 
Jens FiedererTest Developer/ValidatorCommented:
You can do the same thing with the date, after that, since it is represented as an 8 character string....of course, to get the .NET Datetime, you'll have to parse that out.
0
 
ventriculorAuthor Commented:
Thank you very much!  That works for the string values.   Youv'e certainly given me somewhere to go with this.  
The User Defined type in VB contains an assortment of Bookean, string, currenct and integer types.
Here is an expanded excerpt from the User Defined Type in VB6 with some question about VB6 data compared to C#:
Public Type TransactionInfo
    InvoiceNumber As String
    InvoiceDate As String
    EmpCode As String
    InProgress As Boolean   ' will I be able to use br.ReadBoolean() to extract these values?
    Completed As Boolean
    Cancelled As Boolean
    Pullup As Boolean
    Find As Boolean
    ARCode As String
    SubTotal As Currency  ' In VB6 an 8 byte value, would ReadDouble() do the job? Or  ReadInt64()?
    Total As Currency
    TotalTax As Currency
    TotalDiscount As Currency
    ChangeDue As Currency
    OnAccountAmount As Currency
    ItemCount As Integer    ' in VB6, a two byte value, so I take it br.ReadInt16() will do the trick?
        ' More elements follow
End Type
How closely do these match their respective types in C#?  

Here is the hex code from a recovery file with just one record in it:
00000000h: 07 00 30 30 30 30 30 30 33 08 00 32 30 30 37 31 ; ..0000003..20071
00000010h: 30 30 35 08 00 48 20 20 20 20 20 20 20 FF FF FF ; 005..H       ÿÿÿ
00000020h: FF 00 00 00 00 00 00 00 00 80 1A 06 00 00 00 00 ; ÿ........¬......
00000030h: 00 68 9B 06 00 00 00 00 00 E8 80 00 00 00 00 00 ; .h:......è¬.....
00000040h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000050h: 00 00 00 00 00 00 00 00 00 01 00 01 00 00 00 00 ; ................
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000070h: 00 00 00 00 00 00 00 04 00 31 32 30 39 00 00 00 ; .........1209...
00000080h: 00 00 00 01 00 01 00 06 00 00 00 00 00 00 00 00 ; ................
00000090h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000000c0h: 00 00 00 00 00 00 02 00 68 9B 06 00 00 00 00 00 ; ........h:......
000000d0h: 32 34 36 38 20 20 20 20 20 20 20 20 20 20 20 20 ; 2468            
000000e0h: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ;                
000000f0h: 20 20 20 20 20 20 20 20 00 00 00 00 00 00 00 00 ;         ........
00000100h: 00 00 00 00 00 00 00 20 20 20 20 20 20 20 20 20 ; .......        
00000110h: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ;                
00000120h: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 00 ;                .
00000130h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000140h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000150h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000160h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000170h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000180h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000190h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000001a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000001b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000001c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
000001d0h: 00 00 00 00 00 00 00 00 00 01 00 00 00 04 41 80 ; ..............A¬
000001e0h: 1A 06 00 00 00 00 00 E8 80 00 00 00 00 00 00 00 ; .......è¬.......
000001f0h: 00 80 BF 00 00 00 00 00 00 00 00 00 00 00 00 00 ; .¬¿.............
00000200h: 00 00 00 00 00 80 BF 00 00 00 00 00 00 00 00 00 ; .....¬¿.........
00000210h: 00 00 00 00 00 00 00 00 00 80 BF 00 00 00 00 00 ; .........¬¿.....
00000220h: 00 00 00 00 00 00 00 00 00 00 00 00 00 80 BF 00 ; .............¬¿.
00000230h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000240h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000250h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000260h: 00 00 00 80 3F 00 00 80 3F 00 00 00 00 80 1A 06 ; ...¬?..¬?....¬..
00000270h: 00 00 00 00 00 00 00 00 00 08 00 20 20 20 37 36 ; ...........   76
00000280h: 31 38 20 0F 00 20 20 20 20 20 20 20 20 20 20 20 ; 18 ..          
00000290h: 37 36 31 38 1E 00 20 20 20 20 20 20 20 34 20 46 ; 7618..       4 F
000002a0h: 4F 4F 54 50 52 49 4E 54 20 20 20 20 20 20 20 20 ; OOTPRINT        
000002b0h: 20 20 20 20 E8 80 00 00 00 00 00 00 01 00 41 01 ;     è¬........A.
000002c0h: 00 41 80 1A 06 00 00 00 00 00 0B 00 31 31 37 2E ; .A¬.........117.
000002d0h: 30 30 30 2E 30 30 30 0F 00 30 38 31 41 20 20 20 ; 000.000..081A  
000002e0h: 20 20 20 20 20 20 20 20 01 00 4E 90 59 02 00 00 ;         ..NY...
000002f0h: 00 00 00 80 1A 06 00 00 00 00 00 14 00 20 20 20 ; ...¬.........  
00000300h: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ;                
00000310h: 20 01 00 4E 01 00 4E 08 00 48 20 20 20 20 20 20 ;  ..N..N..H      
00000320h: 20 00 00 E8 80 00 00 00 00 00 00 00 00 00 00 00 ;  ..è¬...........
00000330h: 00 00 00 00 00 01 00 02 00 00 00 00 00 00 00 00 ; ................
00000340h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000350h: 00 00 00 00 00 00 00 00 00 00 00 01 00 20 00 00 ; ............. ..
00000360h: 00 00 01 00 4E 00 00 01 00 30 00 00 00 00 05 00 ; ....N....0......
00000370h: 20 20 20 20 20                                  ;  
   
0
 
Jens FiedererTest Developer/ValidatorCommented:
I have read a boolean is a 16 bit integer - with 0 being false, so br.ReadInt16() should do the trick for both.  I believe br.ReadInt64() would be the better choice for Currency (naturally you will get 100* the original value, since an Int of any size has its "decimal point" all the way at the right rather than two digits over).
0
 
ventriculorAuthor Commented:
It's working much better now.  I'm able to produce discernable values.  Thanks.
I think I will be able to produce the utility I need now.
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now