1

Тема: VBS: чтение и запись бинарных данных

Аналогичная темка уже имеется в Коллекции. Но там - пример на JS и, на мой взгляд, решение, которое я предлагаю вашему вниманию - интереснее. Интереснее, за счет вполне самостоятельных процедур конвертации битового массива в стринг и наоборот (раскопал тут)
В общем - смотрите сами:

' Convert Byte-Array to VBScript ANSI string (c)Paul Randall
Function ByteArray2String(bArr)
    Dim OriginalLocale
    OriginalLocale = SetLocale("en-us")
    With CreateObject("ADODB.Stream")
        .Type = 1 'adTypeBinary
        .Open
        .Write bArr
        .Position = 0
        .Type = 2 'adTypeText
        .Charset = "x-ansi"
        ByteArray2String = .Readtext
    End With
    SetLocale OriginalLocale
End Function

'Convert VBScript ANSI string to Byte-Array (c)Paul Randall
Function String2ByteArray(str)
    Dim OriginalLocale
    OriginalLocale = SetLocale("en-us")
    With CreateObject("ADODB.Stream")
        .Type = 2 'adTypeText
        .Charset = "x-ansi"
        .Open
        .WriteText str, 0
        .Position = 0
        .Type = 1 'adTypeBinary
        String2ByteArray = .Read
    End With
    SetLocale OriginalLocale
End Function

Function ReadBinaryFile(filename)
    Dim bArr
    With CreateObject("ADODB.Stream")
        .Type = 1 'adTypeBinary
        .Open
        .LoadFromFile filename
        bArr = .Read
        .Close
        ReadBinaryFile = bArr
    End With
End Function

Function SaveBinaryData(filename, byteArray)
    Const adSaveCreateOverWrite = 2
    With CreateObject("ADODB.Stream")
        .Type = 1 'adTypeBinary
        .Open
        .Write byteArray
        .SaveToFile filename, adSaveCreateOverWrite
        .Close
    End With
End Function

'============================================================
' Проверка
file = "input.bin"
file_out = "output.bin"

Dim file, file_out, Arr, strArr, strHex, x, i
' Читаем бинарный файл и преобразуем его в строку из hex значений
Arr = ReadBinaryFile(file)
strArr = ByteArray2String(Arr)
strHex = ""
For i = 1 To Len(strArr)
    x = Hex(Asc(Mid(strArr, i, 1)))
    If Len(x) < 2 Then x = "0" & x
    strHex = strHex + x
Next
WScript.Echo strHex

' Читаем строку из hex значений и записываем её в бинарный файл
strArr = ""
For i = 1 To Len(strHex) Step 2
    strArr = strArr & Chr("&H" & Mid(strHex, i, 2))
Next
Arr = String2ByteArray(strArr)
SaveBinaryData file_out, Arr

'Можете сравнить входной и результирующий файл - они равны!

2

Re: VBS: чтение и запись бинарных данных

У меня не сработало. У меня входной и результирующий файлы отличаются, прямо с самого начала (в SciTE это невооружённым глазом видно). Пробовал на картинке JPG (67 Кб), результирующая картинка получается испорченной, уже не открывается.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

3 (изменено: mozers, 2009-11-03 03:25:03)

Re: VBS: чтение и запись бинарных данных

2The gray Cardinal
Думаю что тут все дело в том, что промежуточный результат (только для наглядности) переводится в обычный стринг.
Т.е. если картинка - 67кб, то стринг получится длиной в 137216 байт. А у нас какое ограничение на длину стринга в VBS?

Добавлено:
Нет. Мое предположение - неверно. В непонятках что на твоей машине происходит. Ща эксперементировал, постепенно увеличивая размер. Дошел до 200КБ (скрипт работал почти 200 сек) но результат выдал 1:1.
Если выкинуть циклы с преобразованием в длиннющую строку и обратно, то на преобразование 8МБ файла уходит минута.
Сравниваю исходник и результат, естественно, не визуально (в Total Commander есть инструмент сравнения).

4

Re: VBS: чтение и запись бинарных данных

Прошу проверить скрипт ещё кого-нибудь, кому не лень.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

5

Re: VBS: чтение и запись бинарных данных

2mozers: я тут параллельно решаю ту же проблему с чтением бинарных файлов. Основным источником взял это: Convert a binary data (BinaryRead) to a string by VBS (пробовал оттуда пока только улучшенный первый вариант). Я так понимаю, что это, если не то же самое, то очень близко?!

2The gray Cardinal: я пробовал вчера код коллеги mozers'а, тоже на jpeg'е. На одном. У меня отработало нормально, т.е. получившийся итоговый файл совпал с исходным по содержимому.

P.S. У меня глаза на лоб полезли, когда я, пытаясь читать бинарные файлы как текстовые (посредством FSO, «objFile.OpenAsTextStream()»), получил на копиях одного и того же файла (в разных каталогах) разное содержание. Причём, некоторые копии давали одинаковое содержимое, некоторые другие — разное .

6 (изменено: clotd, 2009-11-03 13:31:00)

Re: VBS: чтение и запись бинарных данных

Попробовал приведенный здесь код, файлы не совпадают, также копировал jpeg. Подозреваю проблема связана с локалью и кодировкой. Если убрать циклы с преобразованием в строку, то все работает.

7

Re: VBS: чтение и запись бинарных данных

The gray Cardinal пишет:

Прошу проверить скрипт ещё кого-нибудь, кому не лень.

Проверил для файлов *.exe, *.dll, *.jpg. Не работает.

8

Re: VBS: чтение и запись бинарных данных

Поменял x-ansi на windows-1251 и все заработало

9

Re: VBS: чтение и запись бинарных данных

У меня стоит патч реестра на подмену кодовых таблиц 125x-->1251, может быть с этим что-то связано, что сработало?!

10 (изменено: clotd, 2009-11-03 15:36:09)

Re: VBS: чтение и запись бинарных данных

alexii пишет:

что сработало?!

Файлы совпали. При x-ansi копия коверкалась, это можно хорошо отследить, если дать на вход текстовый файл в ANSI с русскими буквами, проблема появляется на этапе ByteArray2String(bArr). Символы русского алфавита преобразовывались в латиницу и спец знаки, соответственно Asc() уже возвращало не правильные коды и файл на выходе был другой. Попробуйте изменить в скрипте

.Charset = "x-ansi"

на

.Charset = "windows-1251"

в обоих местах, где это встречается.

11

Re: VBS: чтение и запись бинарных данных

Патч на подмену кодовых таблиц 125x-->1251 я завсегда ставлю.
У меня срабатывает и на .Charset = "windows-1251" и на .Charset = "x-ansi". Написал последнее, т.к. сам до конца в эти манипуляции с с кхарсетами не въехал, поэтому посчитал что автор - умнее.
Вообще пока мы все вместе не расставим все точки над i с этими преобразованиями с помощью ADODB.Stream я бы не советовал никому их использовать. Слишком уж от многих факторов зависит результат.
Что же касается расширения преобразуемых файлов, то от него ничего не должно менятся. Однако - меняется! Я думаю что тут виноваты или антивирус или какие то патчи Мелкософта (ну очень они боятся этого объекта, поскольку большинство скриптовых вирусов его активно используют).
Так что вариант, найденный alexii мне очень понравился. И как я, дурак, забыл про существование этой расчудесной функции MidB ?
Ща мы его только подрехтуем маленько...

12

Re: VBS: чтение и запись бинарных данных

При указании "windows-1251" действительно работает, поэтому пусть будет в Коллекции. Если придут ещё какие мысли или усовершенствования, дополнить тему в Коллекции всегда можно.

У меня срабатывает независимо от расширения преобразуемых файлов (bin, jpg, dll). Однако файл скрипта пришлось поставить в исключения антивируснику, иначе код запустить невозможно.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

13

Re: VBS: чтение и запись бинарных данных

OFF: The gray Cardinal, а какой антивирус?

14

Re: VBS: чтение и запись бинарных данных

alexii пишет:

OFF: The gray Cardinal, а какой антивирус?

Avira.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

15

Re: VBS: чтение и запись бинарных данных

Спасибо, ясно.