6

I have a binary string that I need to write to a file. I have a feeling that this should be a simple procedure, but then again, VBScript. The FileSystemObject is of no help, since it munges the data. The Stream object looks promising, with it's adBinaryMode and its Write method, but the Write method requires a byte array and won't seem to accept a variant array instead. Since VBScript arrays are all variant arrays, this seems problematic.

So, how do I just write the data to a file?

EDIT: I should add that the whole thing has to be VBScript. No extra components. Sorry, I don't like it either.

Thom Smith
  • 13,916
  • 6
  • 45
  • 91

5 Answers5

9

It's also possible with the ordinary FileSystemObject, here is code I'm using in custom upload script that I wrote long time ago using code I found online that converts binary string to ASCII:

Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("file path here")
objFile.Write(RSBinaryToString(strBinaryContents))
objFile.Close
Set objFile=Nothing
Set objFSO=Nothing

Private Function RSBinaryToString(xBinary)
    'Antonin Foller, http://www.motobit.com
    'RSBinaryToString converts binary data (VT_UI1 | VT_ARRAY Or MultiByte string)
    'to a string (BSTR) using ADO recordset

    Dim Binary
    'MultiByte data must be converted To VT_UI1 | VT_ARRAY first.
    If vartype(xBinary)=8 Then Binary = MultiByteToBinary(xBinary) Else Binary = xBinary

    Dim RS, LBinary
    Const adLongVarChar = 201
    Set RS = CreateObject("ADODB.Recordset")
    LBinary = LenB(Binary)

    If LBinary>0 Then
        RS.Fields.Append "mBinary", adLongVarChar, LBinary
        RS.Open
        RS.AddNew
        RS("mBinary").AppendChunk Binary 
        RS.Update
        RSBinaryToString = RS("mBinary")
    Else  
        RSBinaryToString = ""
    End If
End Function

Function MultiByteToBinary(MultiByte)
    '© 2000 Antonin Foller, http://www.motobit.com
    ' MultiByteToBinary converts multibyte string To real binary data (VT_UI1 | VT_ARRAY)
    ' Using recordset
    Dim RS, LMultiByte, Binary
    Const adLongVarBinary = 205
    Set RS = CreateObject("ADODB.Recordset")
    LMultiByte = LenB(MultiByte)
    If LMultiByte>0 Then
        RS.Fields.Append "mBinary", adLongVarBinary, LMultiByte
        RS.Open
        RS.AddNew
        RS("mBinary").AppendChunk MultiByte & ChrB(0)
        RS.Update
        Binary = RS("mBinary").GetChunk(LMultiByte)
    End If
    MultiByteToBinary = Binary
End Function
Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
  • I've been butting my head against the wall over this whole ASP file upload issue, this is finally something that just works :-). I can't believe that something this essential needs that such an amount of third party fiddling :-/. Thank you veeeeery much!!!! – mfeineis Jun 22 '16 at 14:37
  • @mfeineis lol, glad this oooold code was of such a great help! :) – Shadow The GPT Wizard Jun 22 '16 at 14:40
  • Awesome, right now i have to fight with this ancient stuff also and this seems to be the only solution that just works after endless hours of fiddling / testing / searching. – ViRuSTriNiTy Jul 20 '16 at 10:53
  • The question is asking to write a binary file in VBS without external downloads. – Zimba Apr 25 '20 at 12:51
  • @Zimba true, and my answer is pure VBScript. No external downloads. Copy and paste, and it works. Cheers. – Shadow The GPT Wizard Apr 25 '20 at 12:54
  • @ShadowWizardisEarForYou: isn't `ADODB` external? – Zimba Apr 25 '20 at 19:23
  • @Zimba no it's not. External libraries are stuff like upload via third party, e.g. the component mentioned [here](https://stackoverflow.com/questions/9805661/asp-upload-component-classic-asp). It's compiled into a DLL and you have no control over it. – Shadow The GPT Wizard Apr 26 '20 at 08:11
2

Writing to a binary file in VBScript is simple but requires you to write one byte at a time. As a demonstration, here is a simple script that creates a single pixel GIF file. The resulting file has exactly the binary content written to it, nothing more, and is a valid GIF file.

Dim GifFile : Set GifFile = CreateObject("Scripting.FileSystemObject").CreateTextFile("SinglePixel.gif")

With GifFile
    .write chr(&h47) 'GIF87a
    .write chr(&h49)
    .write chr(&h46)
    .write chr(&h38)
    .write chr(&h37)
    .write chr(&h61)
    .write chr(&h01) 'Width
    .write chr(&h00)
    .write chr(&h01) 'Height
    .write chr(&h00)
    .write chr(&h80) 'Use global color map
    .write chr(&h00) 'Background
    .write chr(&h00) 'End of header
    .write chr(&h00) 'Color map color #1 in RGB
    .write chr(&h00)
    .write chr(&h00)
    .write chr(&hFF) 'Color map color #2 in RGB
    .write chr(&hFF)
    .write chr(&hFF)
    .write chr(&h2C) 'Image descriptor
    .write chr(&h00) 'Left
    .write chr(&h00)
    .write chr(&h00) 'Top
    .write chr(&h00)
    .write chr(&h01) 'Width
    .write chr(&h00)
    .write chr(&h01) 'Height
    .write chr(&h00)
    .write chr(&h40) 'Use global color map / seq order / 1 bit per pixel
    .write chr(&h02) 'Code size
    .write chr(&h02) 'Blok byte count
    .write chr(&h44) 'LZW data
    .write chr(&h01)
    .write chr(&h00) 'Terminate data stream
    .write chr(&h3B) 'Gif terminator
End With

GifFile.Close
Regis Desrosiers
  • 537
  • 3
  • 13
2

Here are several options. The most interesting variant described there converts the binary data to a string with the help of a custom function BinaryToString.

Helge Klein
  • 8,829
  • 8
  • 51
  • 71
0

To write a (hex encoded) binary string to file with FileSystemObject:

Dim File : Set File = CreateObject("Scripting.FileSystemObject").CreateTextFile("Binary.gif")

data = "47 49 46 38 37 61 07 00 07 00 80 F0 00 FF 00 00 00 FF FF 2C 00 00 00 00 07 00 07 00 40 02 02 44 01 00 3B"
data = Split (data)

for each x in data
File.write chr("&H" & x)
next

File.Close
Zimba
  • 2,854
  • 18
  • 26
0

Here is an example using System.IO.MemoryStream to get "bytes" which is required by ADODB.Stream.

Function ArrToBytes(byteArr)
    dim mem,i,v
    Set mem = Server.CreateObject("System.IO.MemoryStream")
    mem.SetLength 0
    For Each v in byteArr 
        mem.WriteByte v
    Next
    ArrToBytes = mem.ToArray()
    Set mem = Nothing
End Function

dim stm
Set stm = Server.CreateObject("ADODB.Stream")
With stm
    .Type = 1
    .Open
    .Write ArrToBytes(Array(&H80, &H81))
    .Write ArrToBytes(Array(&H82, &H83, &H84, &H85))
    .SaveToFile Server.MapPath("test.bin"), 2
    .Close
End With
Set stm = Nothing

Inspired by this answer.

cuixiping
  • 24,167
  • 8
  • 82
  • 93