Discussion:
Fast Byte array creation?
(too old to reply)
JJ
2019-07-21 21:14:59 UTC
Permalink
With `ADODB.Stream` object, it's possible to create a byte array. i.e. an
actual array of bytes, instead of an array of variants of byte (`TypeName()`
is `Byte()`, instead of `Variant()`).

e.g. below code creates 100 bytes of a byte array.

set stream = createobject("adodb.stream")
stream.type = 2 'text type
stream.charset = "windows-1252"
stream.open
stream.writetext string(100, chr(0))
stream.position = 0
stream.type = 1 'binary type
array = stream.read 'the result
stream.close

However, because the array needs to be written in order to set its length,
it's slow for creating large array. So, is there a faster way to create a
byte array?

Also... What other COM objects can create an array of non variant types?
Mayayana
2019-07-21 21:52:51 UTC
Permalink
"JJ" <***@vfemail.net> wrote

| With `ADODB.Stream` object, it's possible to create a byte array. i.e. an
| actual array of bytes, instead of an array of variants of byte
(`TypeName()`
| is `Byte()`, instead of `Variant()`).
|
| e.g. below code creates 100 bytes of a byte array.
|
| set stream = createobject("adodb.stream")
| stream.type = 2 'text type
| stream.charset = "windows-1252"
| stream.open
| stream.writetext string(100, chr(0))
| stream.position = 0
| stream.type = 1 'binary type
| array = stream.read 'the result
| stream.close
|
| However, because the array needs to be written in order to set its length,
| it's slow for creating large array. So, is there a faster way to create a
| byte array?
|

You didn't say what you're trying to do. I use VBS
arrays and strings for most things in VBS. They can be very
fast when handled carefully. I've only used Stream when
I'm getting byte data that I have to handle, like the
result from a winhttp call. Since VBS can't deal with direct
byte data like that, it's hard to guess what you might be
trying to accomplish.

| Also... What other COM objects can create an array of non variant types?

Why not write your own VB Ax? WIA has some binary
data functionality, designed to work with ADO, but I
don't remember offhand how it works. You can have a Vector
and fill that with BinaryData, but again, VBS can't handle
that directly.

I wrote an Ax for scripters to handle binary data more
directly than VBS can do. (It can do it using Textstream,
but it's clunky.) But I only did that for people who can't
wtire compiled software. For people who can, it's hard
to see the point of using script for binary operations.
JJ
2019-07-22 10:04:34 UTC
Permalink
Post by Mayayana
You didn't say what you're trying to do. I use VBS
arrays and strings for most things in VBS. They can be very
fast when handled carefully. I've only used Stream when
I'm getting byte data that I have to handle, like the
result from a winhttp call. Since VBS can't deal with direct
byte data like that, it's hard to guess what you might be
trying to accomplish.
A generic data container for use with remote process memory access. An
uncommon IPC.
Post by Mayayana
Why not write your own VB Ax?
The idea having to download/install third party software is not preferred.
Using resources which are guaranteed to be available in all or most Windows
installations would make the script more reliable.
Post by Mayayana
WIA has some binary data functionality, designed to work with ADO, but I
don't remember offhand how it works. You can have a Vector
and fill that with BinaryData, but again, VBS can't handle
that directly.
Unfortunately WIA.Vector is same as ADODB.Stream in terms of array data
allocation. Array elements needs to be added manually in order to have a
specific array length.

While VBScript can't access the elements of non variant array, I can use
ADODB.Stream or WIA.Vector as an interface to access it.
Post by Mayayana
I wrote an Ax for scripters to handle binary data more
directly than VBS can do. (It can do it using Textstream,
but it's clunky.) But I only did that for people who can't
wtire compiled software. For people who can, it's hard
to see the point of using script for binary operations.
Well, this is not for common operations.
Mayayana
2019-07-22 13:59:03 UTC
Permalink
"JJ" <***@vfemail.net> wrote

|> Since VBS can't deal with direct
| > byte data like that, it's hard to guess what you might be
| > trying to accomplish.
|
| A generic data container for use with remote process memory access. An
| uncommon IPC.
|

:) I meant what the code is trying to accomplish, not
the aim of the software. Since you can only write to the
stream from a byte array, and presumably you have a
byte array coming in, I don't get the problem.

I was all the more curious because, given the limitations,
I've only use Stream a couple of times. I needed it recently
to write a byte array to disk coming from a winhttp image
download. But of course, that's all I could do. VBS can't
handle the winhttp byte array. If I wanted to edit the bytes
I'd have to save to disk and then open as a Textstream.

Microsoft seem to have gone out of their way to prevent
scripters from being able to edit/write binary data. I usually
do it with Textstream. (Which works as long as the local
codepage is not a multibyte language, like Japanese, Chinese,
or Korean.)

I tried just setting the stream Position to 2000, which should
be fine, according to the docs. But it tells me that's an invalid
operation. "The parameter is incorrect." Yet the docs for
Position say this:

"The current position can be moved to a point after the end of the stream.
If you specify the current position beyond the end of the stream, the Size
of the Stream object will be increased accordingly. Any new bytes added in
this way will be null."

On the other hand, using your method of writing a string
and then converting to binary, returns 0.0625 seconds when
I time how long that takes to create a 10 MB stream. I'd call
that pretty fast. So then you have your byte array, created
almost instantly, but you can't write bytes to it using VBS.
And if you have a byte array coming in then you don't need
to fill the Stream first.
R.Wieser
2019-07-22 10:15:40 UTC
Permalink
JJ,
So, is there a faster way to create a byte array?
I'm not at all sure about this, but would positioning the stream pointer to
the last-to-be-used byte and writing a single one do the trick (having the
stream clear out all bytes in between) ?

Regards,
Rudy Wieser
JJ
2019-07-23 06:30:05 UTC
Permalink
Post by R.Wieser
I'm not at all sure about this, but would positioning the stream pointer to
the last-to-be-used byte and writing a single one do the trick (having the
stream clear out all bytes in between) ?
Unfortunately, ADODB.Stream's Position property is read only. So, it can not
set the stream length directly.
Mayayana
2019-07-23 13:45:06 UTC
Permalink
"JJ" <***@vfemail.net> wrote

| Unfortunately, ADODB.Stream's Position property is read only. So, it can
not
| set the stream length directly.

Not according to the docs:

https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/position-property-ado?view=sql-server-2017

But according to the typelib, the single Position parameter is
a long. Type ADO_LONGPTR. That seems to indicate
a long that's actually a pointer to the stored value,
which seems odd. In any case, the problem seems to
be with VBS. That would explain why it returns "the
parameter is incorrect" when I try to set it. It's expecting
a long.


This morning I came across a rant from Eric Lippert.
Remember him? He used to post condescending, hammy
advice about scripting. Microsoft breaks links to recent
docs and patches, yet Eric Lippert's rants from many years
ago are still online:

http://blogs.msdn.com/ericlippert/comments/410127.aspx

He expresses the basic philosophy that Microsoft had
with Windows Script Host: Provide simple things that
coprporate IT needs, but don't make it too functional.
If all else fails, obfuscate the docs and give obfuscating
advice. Part of that philosophy was to block any file
access other than text, mainly for the purpose of logs.
From the linked page:

"I have been asked many times over the years if I know of a scriptable
object that can read-write true binary files in all locales. I do not."
Loading...