Read and write binary file in VBscript
Asked Answered
S

6

16

I used earlier ADODB.Stream to read and to write binary file here is the link for that

How to concatenate binary file using ADODB.stream in VBscript

it works fine the only problem is ADODB.stream is disabled on windows 2003 server,

Is there another way i can read 3 files in binary mode and concatenate them or store them in one file in VBscript

thank you Jp

Serve answered 19/5, 2011 at 14:49 Comment(0)
O
6

I had a similar problem a year ago. We know that the TextStream objects are intended for ANSI or Unicode text data, not binary data; their .readAll() method produces a corrupted output if the stream is binary. But there is workaround. Reading the characters one by one into an array works fine. This should allow you to read binary data into VB strings, and write it back to disk. When further manipulating such binary strings do not forget that certain operations may result into broken strings because they are intended for text only. I for one always convert binary strings into integer arrays before working with them.

Function readBinary(path)
Dim a
Dim fso
Dim file
Dim i
Dim ts
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.getFile(path)
If isNull(file) Then
    MsgBox("File not found: " & path)
    Exit Function
End If
Set ts = file.OpenAsTextStream()
a = makeArray(file.size)
i = 0
' Do not replace the following block by readBinary = by ts.readAll(), it would result in broken output, because that method is not intended for binary data 
While Not ts.atEndOfStream
    a(i) = ts.read(1)
i = i + 1
Wend
ts.close
readBinary = Join(a,"")
End Function

Sub writeBinary(bstr, path) Dim fso Dim ts Set fso = CreateObject("Scripting.FileSystemObject") On Error Resume Next Set ts = fso.createTextFile(path) If Err.number <> 0 Then MsgBox(Err.message) Exit Sub End If On Error GoTo 0 ts.Write(bstr) ts.Close End Sub

Function makeArray(n) ' Small utility function Dim s s = Space(n) makeArray = Split(s," ") End Function

Ocreate answered 19/5, 2011 at 14:49 Comment(1)
This workaround is not a good practice. It won't work with all codepages. You're really dealing with an edge case here and I would not put this into production.Domitiladomonic
F
6

Based on Luc125 and Alberto answers here are the 2 reworked and simplified functions:

The Read function

Function readBinary(strPath)

    Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")
    Dim oFile: Set oFile = oFSO.GetFile(strPath)

    If IsNull(oFile) Then MsgBox("File not found: " & strPath) : Exit Function

    With oFile.OpenAsTextStream()
        readBinary = .Read(oFile.Size)
        .Close
    End With

End Function

The Write function

Function writeBinary(strBinary, strPath)

    Dim oFSO: Set oFSO = CreateObject("Scripting.FileSystemObject")

    ' below lines pupose: checks that write access is possible!
    Dim oTxtStream

    On Error Resume Next
    Set oTxtStream = oFSO.createTextFile(strPath)

    If Err.number <> 0 Then MsgBox(Err.message) : Exit Function
    On Error GoTo 0

    Set oTxtStream = Nothing
    ' end check of write access

    With oFSO.createTextFile(strPath)
        .Write(strBinary)
        .Close
    End With

End Function
Frazee answered 8/12, 2014 at 23:25 Comment(3)
Do you need this line? Dim oTxtStream: Set oTxtStream = oFSO.createTextFile(strPath)Bacchant
that line is suppose to check the files write access. If you remove it, in some cases the script can crash.Frazee
While this works some of the time, it is generally a bad practice. The FSO is designed for use with standard text streams. This workaround is not bulletproof and it does fail in certain environments. It's best to stick to ADODB which is a native method designed for handling binary streams. There's no additional overhead and it's more efficient anyway. Win-win.Domitiladomonic
D
4

The ADODB stream object is VBScript's only native method of reading binary streams. If ADODB is disabled, you will need to install some other third-party component to provide the same functionality.

Domitiladomonic answered 20/5, 2011 at 14:15 Comment(3)
No need to install any externals; still can be done without ADODB; I've always read/write binaries without itSourwood
@Sourwood The FSO cannot reliably handle binary data. It's designed for text streams. ADODB is the only native method designed for working with binary data streams.Domitiladomonic
Both File & FileSystemObject can process binary data. The question is asking for "another way" without ADODB. I've tested on audio, video, image, zip archives & pdf on Win 10. Your method only works on ADODB without external downloads.Sourwood
M
2

ADODB stream object is VBScript's only native method of reading binary streams

Const TypeBinary = 1
Const ForReading = 1, ForWriting = 2, ForAppending = 8

Function readBytes(file)

     Dim inStream: Set inStream = WScript.CreateObject("ADODB.Stream") ' ADODB stream object used

     inStream.Open ' open with no arguments makes the stream an empty container 
     inStream.type= TypeBinary
     inStream.LoadFromFile(file)
     readBytes = inStream.Read()

End Function

Sub writeBytes(file, bytes)

    Dim binaryStream: Set binaryStream = CreateObject("ADODB.Stream")

    binaryStream.Type = TypeBinary
    binaryStream.Open 'Open the stream and write binary data
    binaryStream.Write bytes
    binaryStream.SaveToFile file, ForWriting 'Save binary data to disk

End Sub
Misbehavior answered 13/3, 2019 at 2:51 Comment(0)
H
1

It is possible to read all bytes together:

Set FS = CreateObject("Scripting.FileSystemObject")
Set fil = FS.GetFile(filename)
fpga = fil.OpenAsTextStream().Read(file.Size)
Hebron answered 11/11, 2014 at 16:23 Comment(5)
you mean Read(fil.Size)?Sourwood
FSO does not reliably handle binary data.Domitiladomonic
@Nilpo: How come you only voted on my answer? And what tests have you done to make your claim?Sourwood
The behavior of .read and .write is known to depend on the system locale. It works reliably in anglophone countries using the EN locales. In other countries, it doesn't work.Formwork
Tested the code with a simple pdf file and the code didn't work for me. Agreed with Nilpo and David, FileSystemObject does not reliably handle binary data.Morris
S
1

Read 3 files & join to one file (without ADODB):

Dim oFSO : Set oFSO = CreateObject("Scripting.FileSystemObject")
If oFSO.FileExists("out.bin") Then oFSO.DeleteFile("out.bin")
Dim outFile : Set outFile = oFSO.OpenTextFile("out.bin", 8, true)

' 3 input files to concatenate
Dim oFS1 : Set oFS1 = oFSO.GetFile("in1.bin")
Dim oFS2 : Set oFS2 = oFSO.GetFile("in2.bin")
Dim oFS3 : Set oFS3 = oFSO.GetFile("in3.bin")

Dim read1 : Set read1 = oFS1.OpenAsTextStream()
Dim read2 : Set read2 = oFS2.OpenAsTextStream()
Dim read3 : Set read3 = oFS3.OpenAsTextStream()

Dim write1 : write1 = read1.Read(oFS1.Size)
read1.Close
outFile.write(write1)

Dim write2 : write2 = read2.Read(oFS2.Size)
read2.Close
outFile.write(write2)

Dim write3 : write3 = read3.Read(oFS3.Size)
read3.Close
outFile.write(write3)

outFile.Close

Tested on audio, video, image, zip archives & pdf (binaries) on Win 10 for binary file copy, edit, split, join, patching & (byte level) encryption, encoding & compression.

See example (answer) here for binary file patching.

Sourwood answered 27/10, 2020 at 13:11 Comment(6)
The native FSO object's OpenAsTextStream method doesn't support binary streams. It does not work reliably with binary files.Domitiladomonic
@Nilpo: of course it supports binaries; I've tested on audio, video, image, zip archives & pdf on Win 10Sourwood
The behavior of .read and .write is known to depend on the system locale. It works reliably in anglophone countries using the EN locales. In other countries, it doesn't work.Formwork
@david:fso can "write binary files" but text string functions won't work because "Nulls truncate strings", and binary data contains strings. The question refers to binary files (single byte ASCII/ANSI characters), which fso can handle. Errors arise from missing codepoints in multi-byte/unicode codepages that are character extensions to cater for other languages.Sourwood
A "high-level, easy-to-use interface" ADODB was developed for abstraction & locale mapping/detection for these locales (may also be done with GetLocale & WMI (released after VBS)). VBScript is restricted from local file system access.Sourwood
@Zimba. fso is a BSTR implementation, not a c string implementation. Nulls do not truncate BSTR strings. FSO does not truncate strings on Nulls.Formwork

© 2022 - 2024 — McMap. All rights reserved.