By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,846 Members | 1,588 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,846 IT Pros & Developers. It's quick & easy.

Reading Random Access file

P: 3
Hi All,
I have a Random access file which is written using VB 6.0.
I need to read this file using C#.
The record used in VB to write the Random access file is as follows

Type AA
aa1 As Integer
aa2 As Integer
aa3 As Integer
aa4 As Integer
aa5 As Integer
aa6 As Integer
aa7 As Integer
aa8 As Integer
aa9 As Integer
aa10 As String * 10
aa11 As String * 20
aa12 As String * 20
aa13 As String * 20
aa14 As String * 20
aa15(1 To 20) As String * 150
aa16(1 To 40) As Integer
aa17(1 To 3) As String * 20
aa18 As Byte
aa19 As String * 1
aa20 As Byte
aa21 As Byte
aa22 As Byte
aa23 As Byte
aa24 As Byte
aa25 As Byte
aa26 As Byte
aa27 As Byte
aa28 As Byte
aa29l(1 To 20) As Double
aa30(1 To 20) As Single
aa31 As Byte
aa32 As String * 20
aa33 As Byte
aa34 As Byte
aa35 As Byte
aa36 As Integer
aa37 As Double
aa38 As String * 25
aa39 As String * 25
aa40 As String * 25
aa41 As Byte
aa42 As Integer
aa43 As Integer
aa44 As String * 10
aa45 As String * 15
End Type

This is the structure that i have created in C# to match the record in VB


[StructLayout(LayoutKind.Sequential,Pack =1,CharSet = CharSet.Ansi)]
public struct AAStructure{
public short aa1;
public short aa2;
public short aa3;
public short aa4;
public short aa5;
public short aa6;
public short aa7;
public short aa8;
public short aa9;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =10)]
public char[] aa10;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =20)]
public char[] aa11;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =20)]
public char[] aa12;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =20)]
public char[] aa13;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =20)]
public char[] aa14;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public String150[] aa15;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40,ArraySubType=

UnmanagedType.I2)]
public short[] aa16;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public String20[] aa17;
public byte aa18;
public char aa19;
public byte aa20;
public byte aa21;
public byte aa22;
public byte aa23;
public byte aa24;
public byte aa25;
public byte aa26;
public byte aa27;
public byte aa28;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType =

UnmanagedType.I4)]
public int[] aa29;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType =

UnmanagedType.R4)]
public Single[] aa30;
public byte aa31;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =20)]
public char[] aa32;
public byte aa33;
public byte aa34;
public byte aa35;
public short aa36;
public int aa37;
[MarshalAs(UnmanagedType.ByValArray,SizeConst =25)]
public char[] aa38;

[MarshalAs(UnmanagedType.ByValArray,SizeConst =25)]
public char[] aa39;

[MarshalAs(UnmanagedType.ByValArray,SizeConst =25)]
public char[] aa40;

public byte aa41;
public short aa42;
public short aa43;

[MarshalAs(UnmanagedType.ByValArray,SizeConst =10)]
public char[] aa44;

[MarshalAs(UnmanagedType.ByValArray,SizeConst =15)]
public char[] aa45;

}

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct String150 {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 150)]
public char[] value;

}


[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct String20 {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] value;

}

however, if i read the random access file using the structure, i am not getting the correct values in the structure data members.

Is my structure correct ?
Am i missing any thing ?

Thanks in advance for any help,

regards,
knuckels23
Nov 8 '08 #1
Share this Question
Share on Google+
4 Replies


Expert 100+
P: 190
Are you reading the record using VB6 into a VB6 structure, and then trying to pass that structure to a C# application using COM Interop?

Or are you simply reading the file using C#?

If you are reading the file using C#, you do not need all the COM Interop attributes. C# would not care what application wrote the file and you could read the file and fill the struct using native types and methods.

That said, either way, I see you interpreted all your source integers as C# shorts, which are 16 bit, not 32. Was that your intent? Are the values always less than 32768?

Just to check, are all the source strings fixed length? That is, is a VB source string * 10 guaranteed to occupy 10 characters or blanks in the file, or is there a chance they could be shorter?

Any issues with encoding?

Have a read through Default Marshalling For Strings and Default Marshalling For Arrays

Sometimes StringBuffer and not char[] is needed for the unmanaged code to fill with fixed string data.

Perhaps post a sample snippet of how you are filling the C# structure...please do not post every field: that is overkill when posting for problem solving.

Also, please describe what you mean when you say you are not getting correct values: are they blank, are there exceptions thrown, are they all off by one, are they complete garbage data, etc.

Finally, USE THE "CODE" tags when posting code, out of courtesy to the forum.

Thanks,

Mike
Nov 9 '08 #2

P: 3
Are you reading the record using VB6 into a VB6 structure, and then trying to pass that structure to a C# application using COM Interop?

Or are you simply reading the file using C#?

If you are reading the file using C#, you do not need all the COM Interop attributes. C# would not care what application wrote the file and you could read the file and fill the struct using native types and methods.

That said, either way, I see you interpreted all your source integers as C# shorts, which are 16 bit, not 32. Was that your intent? Are the values always less than 32768?

Just to check, are all the source strings fixed length? That is, is a VB source string * 10 guaranteed to occupy 10 characters or blanks in the file, or is there a chance they could be shorter?

Any issues with encoding?

Perhaps post a sample snippet of how you are filling the C# structure...please do not post every field: that is overkill when posting for problem solving.

Also, please describe what you mean when you say you are not getting correct values: are they blank, are there exceptions thrown, are they all off by one, are they complete garbage data, etc.

Finally, USE THE "CODE" tags when posting code, out of courtesy to the forum.

Thanks,

Mike
Hi Mike,

Thanks for the reply.
I apologize for posting all the fields and not using the code tags.

1. I am simply reading the file using C# .
2."C# would not care what application wrote the file and you could read the file and fill the struct using native types and methods." - I may be wrong here, but I still have to specify the interop attributes for Array and fixed string's ??
3. " That said, either way, I see you interpreted all your source integers as C# shorts, which are 16 bit, not 32. Was that your intent? Are the values always less than 32768?" - I may be wrong here too, but I think Integers in VB means 2 BYTES, that's why I mapped it to a C# Short.
4. The document based on which i am working states that all the source strings will be of fixed length, how ever i will double check it.
5.The data is not encoded, so i believe there should not be any issues of encoding.
6. I will Post the code that i am using to populate the Structure in C#, how ever before that i need to know whether the my C# structure maps the VB structure.
STRIPED DOWN VB STRUCTURE
Expand|Select|Wrap|Line Numbers
  1. Type AA   aa1 As Integer   aa10 As String * 10       aa15(1 To 20) As String * 150   aa16(1 To 40) As Integer     aa17(1 To 3) As String * 20          aa18 As Byte            aa19 As String * 1        aa29(1 To 20) As Double      aa30(1 To 20) As Single        aa37 As Double       End Type
MATCHING C# STRUCTURE
Expand|Select|Wrap|Line Numbers
  1.         [StructLayout(LayoutKind.Sequential,Pack =1,CharSet = CharSet.Ansi)]               public struct AAStructure{             public short aa1;             [MarshalAs(UnmanagedType.ByValArray,SizeConst =10)]             public char[] aa10;             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]             public String150[] aa15;             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40,ArraySubType=UnmanagedType.I2)]             public short[] aa16;             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]             public String20[] aa17;             public byte aa18;             public char aa19;             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType =UnmanagedType.I4)]             public int[] aa29;             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType =UnmanagedType.R4)]             public Single[]  aa30;             public int aa37;         }          [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]         public struct String150 {             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 150)]             public char[] value;          }          [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]         public struct String20 {             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]             public char[] value;          } 
Can you please check the above code ??

Thanks a ton again for the swift response and thanks in advance again for any further help .
regards,
knuckels23
Nov 9 '08 #3

Expert 100+
P: 190
If the VB integers are two bytes, then you were correct to use short.

Looking over the two structs, it certainly looks correct to me, but of course one would have to test and verify. Not sure about 29 and 37 where you call the VB Double a C# int, but I assume you determined it was the correct match.

OK, I may be missing something, but if indeed you are simply reading a file, be it binary or ascii, using C#, you do not need the Interop attributes.

Interop means a .net (managed) application is talking directly to a non-.NET (unmanaged) application and exchanging data via structures, such as you created.

Although the VB app wrote the data to a file where each record represents the VB type you posted, ONCE IT IS WRITTEN the file has no concept of those structures. It is simply character or binary data.

Now, in order to read it, the .Net IO classes only see a file with a series of bytes. IF the content is text, the TextReaders need to know the encoding and what the EndOfLine character is, and they are happily off reading it.

If the content is binary, which is probably your case, then yes, the BinaryReader has read methods which need to know the data type it is reading. For example: ReadInt16() will read two bytes from the stream and output a short which you can than store or use however you want.

However, it does not need to know about String150[] for example, or any other types beyond primitive. If there are 20 strings each 150 characters, then you can either call ReadChars(150) 20 times, or even ReadChars(3000). Once you have that data, then yes, you can store it in a struct like the one you created in order to emulate the VB source. But the binary reader only needs to know primitive types.

Finally, even if you do create your own struct and fill it using the BinaryReader, as long as you are not trying to send it back to the VB application, or get it from the VB application, THERE IS NO INTEROP, and hence you do not need those attributes.

I suppose they don't really hurt either (I am not sure if the compiler treats the struct any differently with the Interop attributed declared...it might)...but they certainly are not needed.

Does that clear things up? I guess bottom line, we can simplify your code, remove unecessary attributes, remove the custom structs (for now...just to get through the reading part) and concentrate on the problems with reading the data correctly.

PS. I may not get to respond again until monday. Apologies.
Nov 9 '08 #4

P: 3
If the VB integers are two bytes, then you were correct to use short.

Looking over the two structs, it certainly looks correct to me, but of course one would have to test and verify. Not sure about 29 and 37 where you call the VB Double a C# int, but I assume you determined it was the correct match.

OK, I may be missing something, but if indeed you are simply reading a file, be it binary or ascii, using C#, you do not need the Interop attributes.

Interop means a .net (managed) application is talking directly to a non-.NET (unmanaged) application and exchanging data via structures, such as you created.

Although the VB app wrote the data to a file where each record represents the VB type you posted, ONCE IT IS WRITTEN the file has no concept of those structures. It is simply character or binary data.

Now, in order to read it, the .Net IO classes only see a file with a series of bytes. IF the content is text, the TextReaders need to know the encoding and what the EndOfLine character is, and they are happily off reading it.

If the content is binary, which is probably your case, then yes, the BinaryReader has read methods which need to know the data type it is reading. For example: ReadInt16() will read two bytes from the stream and output a short which you can than store or use however you want.

However, it does not need to know about String150[] for example, or any other types beyond primitive. If there are 20 strings each 150 characters, then you can either call ReadChars(150) 20 times, or even ReadChars(3000). Once you have that data, then yes, you can store it in a struct like the one you created in order to emulate the VB source. But the binary reader only needs to know primitive types.

Finally, even if you do create your own struct and fill it using the BinaryReader, as long as you are not trying to send it back to the VB application, or get it from the VB application, THERE IS NO INTEROP, and hence you do not need those attributes.

I suppose they don't really hurt either (I am not sure if the compiler treats the struct any differently with the Interop attributed declared...it might)...but they certainly are not needed.

Does that clear things up? I guess bottom line, we can simplify your code, remove unecessary attributes, remove the custom structs (for now...just to get through the reading part) and concentrate on the problems with reading the data correctly.

PS. I may not get to respond again until monday. Apologies.
Hi,

Apologies for the delayed updation.
The issue was with the Double Data type.
I have managed to fix the problem.
Thanks for you help.
regards,
karthik
Nov 12 '08 #5

Post your reply

Sign in to post your reply or Sign up for a free account.