Thank you Lee for those links.
Well, this is turning out to be quite a --==={challenge}===-- for me.
First I had quite some trouble finding a Zlib dll that would register with regsvr32.exe. But I was able to register this one:
http://www.dogma.net/markn/ZlibOCX2.dllIt is mentioned on
http://www.zlib.net/ as "unsupported VB5 binary".
This dll reads and writes files.
Second problem: reading the binary file, removing the first 60 bytes, and then writing the result to a new binary file that the dll can then decompress. I have checked out code from Lee Mac and MP. See below.
Lee's read function produces a variant of the type 8209(?). But MP's code will only read the first portion of the stb file. So I am using Lee's (LM:ReadBinaryStream) function for reading.
As I am not able to recreate a variant of the type 8209 I am not able to use Lee's code for writing. So I am using MP's (_WriteStream). But somehow the conversion to text that his write function requires causes trouble. In my test only 290 bytes instead of 440 - 60 = 380 bytes were written.
Basically I am stuck here. Any and all insights are welcome!
My code:
(setq data (vlax-safearray->list (vlax-variant-value (LM:ReadBinaryStream "default.stb" 0)))) ; List of integers. Length 440 (equals 440 bytes).
(setq txt (substr (vl-list->string data) 61)) ; Chop off first 60.
(_WriteStream (strcat (getvar 'dwgprefix) "default_Minus_60_Bytes.stb") txt "w") ; Write as text. Only 290 bytes are written?
(setq zlibIF (vlax-create-object "zlibIF.zlibIF.1"))
(vlax-put zlibIF 'inputfilename (strcat (getvar 'dwgprefix) "MANUAL_default_Minus_60_Bytes.stb"))
(vlax-put zlibIF 'outputfilename (strcat (getvar 'dwgprefix) "MANUAL_default_Minus_60_Bytes.txt"))
(vlax-invoke zlibIF 'decompress)
(if zlibIF (vlax-release-object zlibIF))
Lee Mac's code:
http://www.cadtutor.net/forum/archive/index.php/t-57294.html?s=5868f10b6c04f0c55def20c8e85e764e;;-----------------=={ Read Binary Stream }==-----------------;;
;; ;;
;; Uses the ADO Stream Object to read a supplied file and ;;
;; returns a variant of bytes. ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2011 - www.lee-mac.com ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; filename - filename of file to read. ;;
;; len - number of bytes to read ;;
;; (if non-numerical, less than 1, or greater than the size ;;
;; of the file, everything is returned). ;;
;;------------------------------------------------------------;;
;; Returns: ;;
;; Variant of Binary data which may be converted to a list ;;
;; bytes using the relevant VL Variant functions or used ;;
;; with LM:WriteBinaryStream. ;;
;;------------------------------------------------------------;;
(defun LM:ReadBinaryStream ( filename len / ADOStream result )
(vl-load-com)
(setq result
(vl-catch-all-apply
(function
(lambda ( / size )
(setq ADOStream (vlax-create-object "ADODB.Stream"))
(vlax-invoke ADOStream 'Open)
(vlax-put-property ADOStream 'type 1)
(vlax-invoke-method ADOStream 'loadfromfile filename)
(vlax-put-property ADOStream 'position 0)
(setq size (vlax-get ADOStream 'size))
(vlax-invoke-method ADOStream 'read (if (and (numberp len) (< 0 len size)) (fix len) -1))
)
)
)
)
(if ADOStream (vlax-release-object ADOStream))
(if (not (vl-catch-all-error-p result))
result
)
)
;;-----------------=={ Write Binary Stream }==----------------;;
;; ;;
;; Uses the ADO Stream Object to write a variant of bytes to ;;
;; a specified file. File is created if non-existent or ;;
;; overwritten if found. ;;
;;------------------------------------------------------------;;
;; Author: Lee Mac, Copyright © 2011 - www.lee-mac.com ;;
;;------------------------------------------------------------;;
;; Arguments: ;;
;; filename - filename of file to read. ;;
;; data - variant of binary data to write to the file. ;;
;; (as returned by LM:ReadBinaryStream) ;;
;;------------------------------------------------------------;;
;; Returns: Filename of specified file, else nil. ;;
;;------------------------------------------------------------;;
(defun LM:WriteBinaryStream ( filename data / ADOStream result )
(vl-load-com)
(setq result
(vl-catch-all-apply
(function
(lambda ( )
(setq ADOStream (vlax-create-object "ADODB.Stream"))
(vlax-put-property ADOStream 'type 1)
(vlax-invoke ADOStream 'open)
(vlax-invoke-method ADOStream 'write data)
(vlax-invoke ADOStream 'savetofile filename 2)
)
)
)
)
(if ADOStream (vlax-release-object ADOStream))
(if (not (vl-catch-all-error-p result))
file
)
)
MP's code:
http://www.theswamp.org/index.php?topic=17465.0(defun _ReadStream ( path len / fso file stream result )
;; If the file is successful read the data is returned as
;; a string. Won't be tripped up by nulls, control chars
;; including ctrl z (eof marker). Pretty fast (feel free
;; to bench mark / compare to alternates).
;;
;; If the caller wants the result as a list of byte values
;; simply use vl-string->list on the result:
;;
;; (setq bytes
;; (if (setq stream (_ReadStream path len))
;; (vl-string->list stream)
;; )
;; )
;;
;; Arguments:
;;
;; path <duh>
;; len Number of bytes to read. If non numeric, less
;; than 1 or greater than the number of bytes in
;; the file everything is returned.
(vl-catch-all-apply
'(lambda ( / iomode format size )
(setq
iomode 1 ;; 1 = read, 2 = write, 8 = append
format 0 ;; 0 = ascii, -1 = unicode, -2 = system default
fso (vlax-create-object "Scripting.FileSystemObject")
file (vlax-invoke fso 'GetFile path)
stream (vlax-invoke fso 'OpenTextFile path iomode format)
size (vlax-get file 'Size)
len (if (and (numberp len) (< 0 len size)) (fix len) size)
result (vlax-invoke stream 'read len)
)
(vlax-invoke stream 'Close)
)
)
(if stream (vlax-release-object stream))
(if file (vlax-release-object file))
(if fso (vlax-release-object fso))
result
)
(defun _WriteStream ( path text mode / fso stream file result )
;; Return the file size if the file is successfully written
;; to, otherwise nil. Will write all ascii chars to file
;; including nulls. If the caller wants to pass a list of
;; byte values to the function just call it like so:
;;
;; (_WriteStream
;; path
;; (vl-list->string '(87 111 111 116 33))
;; mode
;; )
;;
;; Arguments:
;;
;; path <duh>
;; text <duh>
;; mode "a" to create/append,
;; "w" to create/overwrite (default)
(setq mode (if (member mode '("a" "A")) "a" "w"))
(vl-catch-all-apply
'(lambda ( / format )
(setq fso (vlax-create-object "Scripting.FileSystemObject"))
(cond
( (or (null (findfile path)) (eq "w" mode))
(setq stream
(vlax-invoke
fso
'CreateTextFile
path
-1 ;; 0 (false) = don't overwrite , -1 (true) = overwrite
0 ;; 0 (false) = ascii, -1 (true) = unicode
)
)
(setq file (vlax-invoke fso 'GetFile path))
)
( (setq file (vlax-invoke fso 'GetFile path))
(setq stream
(vlax-invoke
file
'OpenAsTextStream
8 ;; 1 = read, 2 = write, 8 = append
0 ;; 0 = ascii, -1 = unicode, -2 system default
)
)
)
)
(vlax-invoke stream 'Write text)
(vlax-invoke stream 'Close)
(setq result (vlax-get file 'Size))
)
)
(if file (vlax-release-object file))
(if stream (vlax-release-object stream))
(if fso (vlax-release-object fso))
result
)
The attached zip contains 5 files:
default.stb
(STB that comes with Bricscad 440 bytes)default_Minus_60_Bytes.stb
(STB created by my code: only 290 bytes)default_Minus_60_Bytes.txt
(default_Minus_60_Bytes.stb after decompression)MANUAL_default_Minus_60_Bytes.stb
(STB created "manually" with correct file size)MANUAL_default_Minus_60_Bytes.txt
(MANUAL_default_Minus_60_Bytes.stb after decompression)