Solved

How to read and write a binary file.

Posted on 2000-03-30
12
305 Views
Last Modified: 2013-11-13
My problem is this: I have a custom socket server application written in Java. I am writting the client app in VB6. I would like to read a binary file (MS Word Document) from the client into a byte array and simply write it out to the socket using the Winsock control. This seemed simple in the beginning. I started experimenting by reading a file into a byte array and writting it back to the hard drive with a different name. The code is as follows:
  Dim buffer(1024) As Byte
  Open "c:\logo1024.jpg" For Binary Access Read As #1
  Open "c:\logo1024_new.jpg" For Binary Access Write As #2
 
  Get #1, , buffer
  Do While Not EOF(1)
    Put #2, , buffer
    Get #1, , buffer
  Loop
 
  Close #1
  Close #2
 
This only works if I use a single byte as my buffer and not a byte array. Which is very slow! This seems to add one byte to the file for each "Put". You will also probably notice with this logic the last 'partially filled' buffer contents are not written to the new file.  Again, even if I force it to write the last bit, it results in a file larger than the original.

Is there a way to do this? Help?

I also tried getting the file size and making my buffer exactly that size. This resulted in a file that was one byte larger than the original.

Thanks in advance.
0
Comment
Question by:kkennedy65
  • 6
  • 2
  • 2
  • +2
12 Comments
 
LVL 2

Expert Comment

by:bhamilto
Comment Utility
Try this:

Dim buffer() As Byte

  Open App.Path + "\trailer.txt" For Binary Access Read As #1
  Open App.Path + "\new_trailer.txt" For Binary Access Write As #2
   
  ReDim buffer(1 To LOF(1))
  Get #1, , buffer
  Put #2, , buffer

  Close #1
  Close #2
0
 
LVL 2

Expert Comment

by:bhamilto
Comment Utility
Try this:

Dim buffer() As Byte

  Open App.Path + "\trailer.txt" For Binary Access Read As #1
  Open App.Path + "\new_trailer.txt" For Binary Access Write As #2
   
  ReDim buffer(1 To LOF(1))
  Get #1, , buffer
  Put #2, , buffer

  Close #1
  Close #2
0
 
LVL 2

Expert Comment

by:bhamilto
Comment Utility
Sorry for the double post.  Hey what gives - I'm reading a question post time later than my comments.
0
 
LVL 6

Expert Comment

by:VBGuru
Comment Utility
If is a ms word document, then you can't read it as binary file. It is file in a structured storage file. You got to use structure storage APIs to do the rad and write the files. SO you can use APIs to read the file and send it through socket.

For more info on how to read structure storage file check out
http://www.geocities.com/SiliconValley/Foothills/9940/
0
 
LVL 2

Expert Comment

by:bhamilto
Comment Utility
VBGuru

I tried this with a word doc after reading the post and it works fine with VB5.  As far as I know a VB binary file read/write will work on any file.
0
 
LVL 6

Expert Comment

by:VBGuru
Comment Utility
bhamilto
Binary file reading should work with any file. But if you know the format, you can extract what exactly u want to transfer.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 2

Expert Comment

by:bhamilto
Comment Utility
VBGuru

No arguement with your comment but why complicate things if you want to deal with the whole file?
0
 
LVL 2

Expert Comment

by:bhamilto
Comment Utility
kkennedy65

Forgot to mention the source of the problem you were having.  Unless you declare a specific array lower bound (with "Option Base"), it will default to 0.
Your "Dim buffer(1024) As Byte" is actually (0 to 1024), a 1025 byte array.
0
 
LVL 14

Accepted Solution

by:
wsh2 earned 100 total points
Comment Utility
Thumbs up on bhamilto's solution.. <smile>.

One caveat though.. with very large files you may want to thunk your way through the binary file rather than read it all at once. With large reads.. once physical memory gets used up.. Windows swaps the excess out to disk and in effect you end up reading / writing it twice.. <sigh>. Below is an example of thunking.. set the BUFFER_SIZE constant to whatever you think best (10000 works nice) and with large files, you should see better performance.

<----- Code Begin ----->

Private Function xFile_Copy _
(ByVal strFileGet As String, ByVal strFilePut As String) _
As Long

   Const BUFFER_SIZE = 10000 ' Set to whatever you think best
   
   On Error GoTo ErrGet
   Dim intGet As Integer
   intGet = FreeFile
   Open strFileGet For Binary Access Read As intGet
   
   On Error GoTo ErrPut
   Dim intPut As Integer
   intPut = FreeFile
   Open strFilePut For Binary Access Write As intPut
   
   On Error GoTo ErrCopy
   Dim bytBuffer() As Byte
   ReDim bytBuffer(1 To BUFFER_SIZE)
   Dim lngThunk As Long
   Do Until lngThunk >= LOF(intGet)
      If lngThunk + UBound(bytBuffer) > LOF(intGet) _
      Then
         ReDim bytBuffer(1 To LOF(intGet) - lngThunk)
      End If
      lngThunk = lngThunk + UBound(bytBuffer)
      Get intGet, , bytBuffer()
      Put intPut, , bytBuffer()
   Loop
   
   xFile_Copy = lngThunk
   Close intGet
   Close intPut
   GoTo Tag999

ErrGet:
   MsgBox (strFileGet & " ERROR")
   GoTo Tag999

ErrPut:
   MsgBox (strFilePut & " ERROR")
   Close intGet
   GoTo Tag999

ErrCopy:
   MsgBox ("ERROR Copying " & strFileGet & " To " & strFilePut)
   Close intGet
   Close intPut
   Kill strFilePut
   GoTo Tag999

Tag999:
   On Error GoTo 0

End Function

<----- Code End ----->
0
 

Author Comment

by:kkennedy65
Comment Utility
Thanks to all for your comments. Thanks bhamilto for all your input. I guess I've been working in Java too long and forgot how VB handles the initialization of arrays. I have to give the points to wsh2. Thanks wsh2 for the exact funtion I was looking for! This experts exchange really does work!
0
 

Author Comment

by:kkennedy65
Comment Utility
It was exactly what I was looking for.
0
 

Expert Comment

by:newmembername
Comment Utility
here's anotherway to read/write (copy)
it reads only 64k (max) at a time


Free = FreeFile
maxsel = FileLen("C:\file.exe")
 
Dim dat1 As String * 1: Dim dat2 As String * 2
Dim dat3 As String * 4: Dim dat4 As String * 8
Dim dat5 As String * 16: Dim dat6 As String * 32
Dim dat7 As String * 64: Dim dat8 As String * 128
Dim dat9 As String * 256: Dim dat10 As String * 512
Dim dat11 As String * 1024: Dim dat12 As String * 2048
Dim dat13 As String * 4096: Dim dat14 As String * 8192
Dim dat15 As String * 16384: Dim dat16 As String * 32768
Dim dat17 As String * 65526
Dim dat
 
  Open "C:\filewrite.exe" For Output As #2
  Open "C:\fileread.exe" For Binary Access Read Lock Read As #1
   
  Do
    orgmaxsel = maxsel
    If maxsel = 1 Then
      Get #1, , dat1
      maxsel = maxsel - 1
      dat = dat1
    ElseIf maxsel >= 2 And maxsel < 4 Then
      Get #1, , dat2
      maxsel = maxsel - 2
      dat = dat2
    ElseIf maxsel >= 4 And maxsel < 8 Then
      Get #1, , dat3
      maxsel = maxsel - 4
      dat = dat3
    ElseIf maxsel >= 8 And maxsel < 16 Then
      Get #1, , dat4
      maxsel = maxsel - 8
      dat = dat4
    ElseIf maxsel >= 16 And maxsel < 32 Then
      Get #1, , dat5
      maxsel = maxsel - 16
      dat = dat5
    ElseIf maxsel >= 32 And maxsel < 64 Then
      Get #1, , dat6
      maxsel = maxsel - 32
      dat = dat6
    ElseIf maxsel >= 64 And maxsel < 128 Then
      Get #1, , dat7
      maxsel = maxsel - 64
      dat = dat7
    ElseIf maxsel >= 128 And maxsel < 256 Then
      Get #1, , dat8
      maxsel = maxsel - 128
      dat = dat8
    ElseIf maxsel >= 256 And maxsel < 512 Then
      Get #1, , dat9
      maxsel = maxsel - 256
      dat = dat9
    ElseIf maxsel >= 512 And maxsel < 1024 Then
      Get #1, , dat10
      maxsel = maxsel - 512
      dat = dat10
    ElseIf maxsel >= 1024 And maxsel < 2048 Then
      Get #1, , dat11
      maxsel = maxsel - 1024
      dat = dat11
    ElseIf maxsel >= 2048 And maxsel < 4096 Then
      Get #1, , dat12
      maxsel = maxsel - 2048
      dat = dat12
    ElseIf maxsel >= 4096 And maxsel < 8192 Then
      Get #1, , dat13
      maxsel = maxsel - 4096
      dat = dat13
    ElseIf maxsel >= 8192 And maxsel < 16384 Then
      Get #1, , dat14
      maxsel = maxsel - 8192
      dat = dat14
    ElseIf maxsel >= 16384 And maxsel < 32768 Then
      Get #1, , dat15
      maxsel = maxsel - 16384
      dat = dat15
    ElseIf maxsel >= 32768 And maxsel < 65526 Then
      Get #1, , dat16
      maxsel = maxsel - 32768
      dat = dat16
    ElseIf maxsel >= 65526 Then
      Get #1, , dat17
      maxsel = maxsel - 65526
      dat = dat17
    End If
    DoEvents
   
    Me.Caption = Format(maxsel, "000,000,000") & " bytes remaining"
    Print #2, dat
 
  Loop Until maxsel = 0

Close #1
Close #2
 
dat = ""
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now