Archived

This topic is now archived and is closed to further replies.

shawncorn

Visual Basic - saving/loading data from file

Recommended Posts

shawncorn    122
Hi. Sorry if this was already answered somewhere else, but all my searches were of no help. I'm trying to store, via "Put," a byte array (a string) to a file and recover it. Here's a small program that should, afaik, produce these results: Dim saveText() As Byte Dim loadText() As Byte ReDim saveText(11) As Byte ReDim loadText(11) As Byte saveText = "Hello World" Open "test.txt" For Binary As #1 Put #1, , saveText() Close #1 Open "test.txt" For Binary As #1 Get #1, , loadText() Close #1 MsgBox saveText() MsgBox loadText() The output is a msgbox with the caption "Hello World" followed by a msgbox with the caption "Hello." Can someone please tell me wtf is going on here? -Brian -------- EDIT Check out the contents of "test.txt": H e l l o W o r l d Why does it store a character, a blank space, a character, etc.? And why won't it load it like that? Edited by - shawncorn on January 1, 2002 9:36:19 PM

Share this post


Link to post
Share on other sites
ragonastick    134
I think the problem is because VB strings are unicode, so when loaded into the byte array like that, it only gets half of it. Or something like that, I''d never seen a Byte array used as a string like that before, so I''m playing around with it now.

For a function which loads a file to a string, here is a known working one:


Dim Data As String

''Load the file
FileNum = FreeFile
Open "C:\Andy''s Stuff\Pictures\thumbnail.gif" For Binary As FileNum

Do Until EOF(FileNum)
Get FileNum, , Temp

Data = Data & Chr$(Temp)
Loop

Close FileNum


It is not very well written (the string is put together one byte at a time, which will make it slow for larger files), but it works. To speed it up, use LOF to get the length of the file, and then make enough room to store the entire string, then put the data in.

I might have more to say on this in a few moments.


Trying is the first step towards failure.

Share this post


Link to post
Share on other sites
shawncorn    122
Using a bit of your code, I modified this to read every other byte. It works for this example, but I''m afraid to rely on this workaround. Eventually I''m going to read the data using C++... would I have to skip every other byte?

Dim buf As Byte
Dim data As String

Open "test.txt" For Binary As #1
For i = 0 To 22
Get #1, , buf
If (i Mod 2) = 0 Then
data = data & Chr$(buf)
End If
Next
Close #1

Share this post


Link to post
Share on other sites
ragonastick    134
A better way to load the whole thing would be like this:


Dim Data() As Byte
Dim FileNum As Long

FileNum = FreeFile
Open FileName For Binary As FileNum


Redim Data(LOF(FileNum) - 1)

For i = 0 To LOF(FileNum) - 1
Get FileNum, i + 1, Data(i)
Next

Close FileNum


Now, while that will read everything just fine, if you then choose to use that Byte array as a string, you will need to write another function:


Function ByteArrayToString(ByteArray() As Byte) As String
''Takes a byte array and interprets it as an ASCII string
Dim i As Long

ByteArrayToString = Space$(UBound(ByteArray) + 1)

For i = 0 To UBound(ByteArray)
Mid$(ByteArrayToString, i, 1) = Chr$(ByteArray(i))
Next
End Function


Again, this only builds it one byte at a time (which is unavoidable), but the line:

ByteArrayToString = Space$(UBound(ByteArray) + 1)

Will make the string big enough to fit the whole string all without being resized. (I was writing this code from my head, so if Space$ isn''t a function, then sorry... I think there is a function which will fill a string with n characters... try finding that)

Taking a step back though, here are some more simple ways to do it:


Dim Blah As String

Open "c:\test.txt" For Binary As #1

Blah = Space$(LOF(1))

Get #1, 1, Blah

Close #1

Debug.Print Blah


Again, note the Space$, it makes the string so it can fit the file, because otherwise, the Get statement doesn''t know how much to read... update, Space$ is a function , and this code works fine, even with carriage returns.

Or, if you want, you could use text mode:


Dim Blah As String
Open "c:\test.txt" For Input As #1

Line Input #1, Blah

Close #1


That will read a single line and put it into Blah. Use this one with EOF to read an entire file.

So yeah, my recommendation would be to use the last binary mode method I showed, it will be the fastest of all the methods.

Trying is the first step towards failure.

Share this post


Link to post
Share on other sites
ragonastick    134
One final thing: don't be lazy like I was with those last few examples... the "best" code should not assume that the file handle 1 is available, and it should also be written as a proper function:

Function ReadFile(FileName As String) As String
On Error Goto ErrorHandler
Dim FileNum As Long
FileNum = FreeFile

Open FileName For Binary Access Read Lock Read Write As FileNum

ReadFile = Space$(LOF(FileNum))
Get FileNum, 1, ReadFile

Close ReadFile

Exit Function
ErrorHandler:
'Whatever makes you happy here
End Function


Trying is the first step towards failure.

Edited by - ragonastick on January 1, 2002 10:28:09 PM

Share this post


Link to post
Share on other sites
shawncorn    122
Thanks dude, I appreciate the help. Another look at MSDN helped me come up with the solution I''ll probably be using in the practical application that led me to this problem:

Open the file as binary
ByteArrayBuffer = InputB(2 * length of string, FileNum)
Close

It''s still a little weird, I really think Unicode is unnecessary.

Share this post


Link to post
Share on other sites
ragonastick    134
Especially since you cant actually use the extra characters you get, unless you use a dynamic array of bytes that is. So really, there is not much point.

Trying is the first step towards failure.

Share this post


Link to post
Share on other sites