-
Feb 13th, 2015, 10:23 AM
#1
Thread Starter
Hyperactive Member
[RESOLVED] How to convert a byte array ?
Hi,
I have a small text file with 2 columns (tab delimited) which was stored as resource file. When I try to get back the file, its content is provided as byte array using the native function LoadResData
Code:
myByteArray() = LoadResData(102, "Custom")
I know how to load a simple text file from disk into a 2D array but once I already have the file as array how could I convert it in a 2D variant array for example? Thank you.
-
Feb 13th, 2015, 10:37 AM
#2
Re: How to convert a byte array ?
You can use the StrConv() method for this:
Code:
Dim byteArray() As Byte
Dim sInput As String
Dim sOutput As String
' Just a normal string
sInput = "Hello world"
' Store it in an byte array
byteArray = StrConv(sInput, vbFromUnicode)
' Convert byte array to string
sOutput = StrConv(byteArray, vbUnicode)
Debug.Print sInput, sOutput
-
Feb 13th, 2015, 11:11 AM
#3
Thread Starter
Hyperactive Member
Re: How to convert a byte array ?
Thanks for reply, Arno. As I mentioned above I need a 2D array as result because my flexgrid requires a 2D variant array for its LoadArray method. Let's say I would split further the byte array as below
Code:
myText = StrConv(myByteArray, vbUnicode)
strArray = Split(myText, vbNewLine)
However, in this case I will get an 1D array instead with all column data grouped on each row. Maybe including again each row in a other loops could do the task but I am not really sure if it is the most straightforward way for this kind of conversion.
-
Feb 13th, 2015, 11:26 AM
#4
Re: How to convert a byte array ?
Originally Posted by Daniel Duta
Maybe including again each row in a other loops could do the task but I am not really sure if it is the most straightforward way for this kind of conversion.
Process the myText variable same as if it were the actual text file, which you already have code for.
-
Feb 13th, 2015, 01:06 PM
#5
Thread Starter
Hyperactive Member
Re: How to convert a byte array ?
After many attempts I have managed to solve my issue avoiding the byte array conversion. Knowing the FlexGrid control has a useful Clip property I preferred to transfer my text file from the vb Resource file directly using the Clipboard object. For this purpose I have written the following routine that worked as I wanted and could be useful for others:
Code:
Private Sub FillFlexFromResFile()
Dim myByteArray() As Byte, myText As String
myByteArray() = LoadResData(102, "Custom")
myText = StrConv(myByteArray, vbUnicode)
Clipboard.Clear
Clipboard.SetText myText
With fg
.Redraw = flexRDNone 'Avoid the flickering effect
.Row = 1 'Paste starting with second row (first is header usually)
.Col = 1 'Paste starting with second column (or other)
.Rows = UBound(Split(myText, vbNewLine)) + 1 'Recalculate the max nb of fg rows considering the text file nb of rows
.RowSel = .Rows - 1 'Extend the row selection to maximum allowed
.ColSel = .Cols - 1 'Select the all range of columns
.Clip = Clipboard.GetText 'Paste the clipboard content over selection
.Col = 1 'Remove the fg body selection
.Redraw = True 'Resume redrawing
End With
Clipboard.Clear 'Clears the clipboard content
End Sub
Thank you all for your suggestions.
-
Feb 13th, 2015, 01:52 PM
#6
Re: [RESOLVED] How to convert a byte array ?
You don't need the Clipboard, just assign the string directly to the .Clip property
Last edited by Arnoutdv; Feb 13th, 2015 at 01:56 PM.
-
Feb 13th, 2015, 02:07 PM
#7
Re: [RESOLVED] How to convert a byte array ?
Not sure why the Clipboard is involved in the above code,
since you could simply use the myText-content also directly...:
fg.clip = myText
I personally prefer, to store such Data-related resources in a
"Non-GUI-Control-dependent" format...
E.g. ADO-Recordsets come to mind (in case one needs to serialize Multi-
Column-Data into a ByteArray) - and those ADO-Rs could then also be used
"free-standing" (without any underlying DB-Engine).
Serialization-features of "Non-GUI-Data-Container-Classes" are common
nowadays in many class-libraries - so, beside the already mentioned ADO-
Recordset, VB6-users could also use the vbRichClient5-Container-Objects,
which all support Unicode-capable serialization/deserialzation into ByteArrays:
Multi-Column-Data:
e.g. the (SQLite-DB-derived - from InMemory-or File-Connection)
- cRecordset (over its Read and Write .Content Property which accepts/hands out ByteArrays)
- cConnection.CreateTableFromRsContent (could also directly make an InMemory-Table or FileDB-Table from such Content)
- cConnection.CreateTableFromADORs (can do the same SQLite-InMemory-Table-Creation in one Line, but from an ADO-Rs as the source
Key-Value-Pairs:
- cCollection (ByteArrray-serialization/deserialization of Key-Value-Pairs over its .Content-Property)
- cCollection.SerializeToJSONString (is alternatively also available ...)
- cCollection.SerializeToJSONUTF8 (...as well as UTF8-ByteArray-Serialization...)
all of the above 3 methods work also hierarchically (on a nested Tree, in case a Value is another cCollection).
1D-Arrays of all simple Types (Long, String, Currency, Double, etc.):
- cArrayList (in the same way as the other two above, supports a Read-Write .Content-Property)
So, in your concrete case you could e.g. store your ByteArray-Content, derived from
an ADO-Rs (e.g. a free-standing one, which you created per Rs.Fields.Append, etc.)
And deserializing it on App-LoadTime from your resource, then being able
to "hang it in" with one line of code, not only into a HFlexGrid, but also into an
editable VB.DataGrid - or bind it against TextFields etc. - I guess what I mean to
say is, that it's a good idea to use data-serializations, which can be deserialized into
Containers which are more flexible and "bindable" to all sorts of GUI-controls.
Olaf
-
Feb 13th, 2015, 03:54 PM
#8
Re: [RESOLVED] How to convert a byte array ?
Originally Posted by Schmidt
I personally prefer, to store such Data-related resources in a
"Non-GUI-Control-dependent" format...
I assume this is an issue of locale-dependent formatting of things like fractional numbers, currency values, date/time values, boolean values, etc.
Text formats don't have to be a barrier to data interchange, they just need to be formatted using the "invariant" locale's formatting. For example in XML it is never legal to use "1,23" to mean "1.23" even if your system or user account is set for a German UI. if you do that then it isn't XML, but a nonconformat look-alike.
The same is true for CSV or other delimited text data. While for convenience German language users may be able to use semicolons in place of the commas, allowing goofy punctuation in their numbers, the result isn't really "CSV" at all. You certainly wouldn't want to use it as a data interchange format.
Most code that can process data seriaized as XML, JSON, etc. is smart enough to always use the invariant locale. However not all software can do this for a format like CSV.
ADO or example, when fed text as data, will always apply the current user UI locale when "deformatting" the text back to a binary representation. If your user account is set for a German language UI, feeding "1.23" to ADO for a Single field gets you 123 instead of 1.23 in your Recordset. Feeding it "1,23" when your UI language is English gets you 123 in the same way. I have not found any override for this.
So CSV is hazardous, conceived in early times before the Internet was widely available. It's legacy is all over the place.
That's why binary formats are safer. To use text you want to stick to XML or JSON and software that conforms to the standards. This is probably a bigger problem for JSON than XML, though there are plenty of incorrect parsers and serializers for both of them that assume the UI locale is always U.S. English.
In the U.S. people are lucky in a way. Even when you lump in Canada, which is close enough that most things will just work. As long as they can get away with treating N. America as its own universe everything mostly works with no fiddling.
Of course Canada has French as well, and the U.S. has a ton of Spanish speakers... not to forget Mexico and friends to the south. But you are still mostly safe until you deal with true/false values or dates with month names in them.
-
Feb 13th, 2015, 03:57 PM
#9
Re: [RESOLVED] How to convert a byte array ?
BTW: my new TabularParse seems to work for this sort of thing.
-
Feb 13th, 2015, 05:15 PM
#10
Re: [RESOLVED] How to convert a byte array ?
I was just reminded that binary formats pose risks of their own.
Quite a few are proprietary, and those that aren't can present platform portability woes (big vs. little endian, date/time representation, 1's complement vs. 2's complement, etc.).
-
Feb 13th, 2015, 07:05 PM
#11
Re: [RESOLVED] How to convert a byte array ?
Originally Posted by dilettante
I assume this is an issue of locale-dependent formatting of things like fractional numbers, currency values, date/time values, boolean values, etc.
Yes, that's one of the reasons, since such "non-GUI-containers" (aka "common List-Structures")
support correct storage of different (native) datatypes, according to their Field-Definition -
(in a truly portable format, which works locale-independent - no matter if "binary formatted",
or as alternatively possible with e.g. ADO-Rs, per XML-based serialization-format).
These containers will always "serialize/deserialize" correctly - at least on any current
Win-machine, since we have no Endianness-problems to take into account on these OSes.
Same thing with powerful Container-Objects which store Key/Value-pairs - when both,
the Keys and the Values are "native-Type-aware" - e.g. when they (as in VB5/6) are
based on the selfdescribing Variant-Type, often damned - but it really *is* a powerful
Struct(ure), especially in these Serialization/Deserialization-scenarios (which e.g. COM-
Marshalling + IDispatch is a larger part of - and one of the reasons, the Variant-Type was
"invented" or "needed").
So these (native serializing) List-Structures are useful not only in storage-scenarios - but also
in RPCs (Remote-Procedure-Calls) - no matter if across Thread- or Process-boundaries -
or across Machine-boundaries (per Pipes or sockets).
But I also was trying to make my point with regards to larger convenience in daily programming-
scenarios - since those Containers usually also support sorting and filtering (which will reduce
your efforts with certain GUI-Bindings, since not each and every GUI-Control supports Filtering,
Sorting, or has built-in search-mechanisms).
Especially when such containers are used against "Virtual List-Controls" (as you recently posted a
nice one in the CodeBank), you will be able to keep your Data in your non-GUI-containers, and
then sort + filter them there - your changes easily reflectable in the (few, only currently visual)
Lines of your Virtual-ListControl-Rendering-Update.
Olaf
-
Feb 15th, 2015, 07:20 PM
#12
Thread Starter
Hyperactive Member
Re: [RESOLVED] How to convert a byte array ?
Originally Posted by Arnoutdv
You don't need the Clipboard, just assign the string directly to the .Clip property
You are absolutely right, Arno, the Clipboard usage is redundant in this case. Just fg.Clip = myText does all the work.
Originally Posted by Schmidt
Not sure why the Clipboard is involved in the above code
Me neither I tested an idea, it worked and I thought that it is the right way... You know, when people get married they have a similar behavior. So, take it as a lack of maturity. It is the first time when I use the Clip property and I didn't find any example about how a resource file could be loaded in a flexgrid directly. Anyway, these days I want to see how the vbRichClient5 library works on the database side, especially with SQLight because I hope to find more degrees of freedom than with Access - tsql query syntax, bulk insert data, speed and many other.
Originally Posted by dilettante
BTW: my new TabularParse seems to work for this sort of thing.
I found both your functions from codebank very useful to me. The TabularParse does convert a binary text file in a variant array, taking into account a multidimensional structure and the Null values. The PutString function is useful when we try to load data with ADO but now I try to adapt your function to a 2D array because when we get data from excel usually we have a 2D variant. This array cannot be loaded in Access db directly (bulk insert) using the ADO AddNew method but I have noted that you succeeded to insert 8 columns and 5000 rows in a fast way (avoiding the Update method) calling the AddNew method only at the end of the each row. I didn't write a small benchmark but your approach is visible faster. Thank you all.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|