Как получить некоторую текстовую информацию из нетекстового файла с помощью пакетных команд в Windows? - PullRequest
2 голосов
/ 18 февраля 2011

ребята.Я пытаюсь получить версию файла из некоторых нетекстовых файлов.В каждой из них (примерно в начале) есть несколько текстовых строк, содержащих информацию о файле.Например:

[some nontext data (very few)]
version: 455467
build date: 23.11.2010
.....
[rest of the nontext data]

Если хотите, я попытаюсь создать такой файл, но я не могу показать вам исходные файлы (моя компания не допустит этого).Извините ...

Я попробовал этот код:

@echo off
for /f "tokens=1,2" %%A in (file.dat) do if %%A==version: (set version=%%B
goto found)
echo not found
goto end
:found
echo found: %version%
:end
pause

Но это работает, только если "file.dat" является текстовым файлом, если нет, я получаю "не найден".Если я заменю file.dat на «type file.dat», он не вернется (загрузка процессора 100%).Если я заменю file.dat на 'find / i' version: "file.dat ', это будет работать, но очень, очень медленно (минуты).Поскольку мне приходится обрабатывать много файлов, и у меня мало времени, я не могу его использовать.Это работает намного быстрее, если я ввожу каждый файл вручную с помощью средства просмотра и копирую номер версии;но дело в том, что я хочу сделать это с помощью cmd ...

О, и я не могу установить другие программы на компьютер, на котором я работаю ....

ОС Windows XP x86.

Пожалуйста, помогите мне.Спасибо.

С наилучшими пожеланиями, Cosmin

Позднее редактирование: у меня есть "сборка" тестового файла, чтобы все могли видеть и тестировать: http://www.mediafire.com/download.php?r0x5702lkv14jro Он очень маленький (реальные файлы имеютдесятки, некоторые даже сотни МБ).

Позже, позже отредактируйте: тестовый файл полезен для проверки, ЕСЛИ код находит число, но, будучи очень маленьким, он не дает представление о том, сколько временинужен для реального файла данных.Но вы можете сделать это: измерить время сканирования тестового файла и умножить на «100 МБ / 2088 байт» = 50 219. Например, это работает с «найти».С «типом» еще медленнее (я думаю, что это экспоненциально, а не линиарно).

Ответы [ 2 ]

2 голосов
/ 16 ноября 2011

Я использовал упрощенную версию двоичного метода считывания FC в jeb, чтобы прочитать первые 1024 байта файла DAT. ( преобразование двоичного файла в представление HEX с использованием пакетного файла ) Я сохраняю только печатные символы ASCII и , остальные я выбрасываю. Я использовал файл сравнения, содержащий 1024 символов, чтобы мне не приходилось беспокоиться о пробелах в выводе FC.

Я использую карту, разработанную для моей подпрограммы hexDump.bat (http://www.dostips.com/forum/viewtopic.php?p=7038), чтобы преобразовать шестнадцатеричное представление обратно в символы ASCII.

Тогда все, что осталось - это некоторые прямые манипуляции со строками для разбора версии. Я ищу <LF>version:, убирая начальные пробелы, а затем беру все печатные символы до следующего <LF> в качестве значения версии.

В этом решении предполагается, что версия находится в пределах первых 1024 символов. Его можно расширить для поддержки первых 8 КБ, просто увеличив размер файла сравнения.

Решение кажется достаточно быстрым, и размер файла DAT не должен влиять на производительность.

@echo off
setlocal enableDelayedExpansion

:: Build a binary file containing 1024 <backSpace> characters
set compareFile="BS1024.DAT"
if not exist %compareFile% (
  for /f "tokens=1 delims=# " %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
    <nul set/p"=%%a" >%compareFile%
  )
  for /l %%n in (1 1 10) do type %compareFile% >>%compareFile%
)

:: Create a variable containing <lineFeed> character (0x0A)
set lf=^


:: Above 2 blank lines are critical - do not remove.

:: Grab the first 1024 bytes, preserving only printable ASCII characters and <lineFeed>
set map= ^^^!^"#$%%^&'^(^)*+,-./0123456789:;^<=^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
set datFile="test.dat"
set "dat="
for /f "eol=F usebackq tokens=2 skip=1 delims=:[] " %%A in (`fc /b %datFile% %compareFile%`) do (
  if "%%A"=="0A" (set "dat=!dat!!lf!") else (
    set /a "n=0x%%A-32"
    if !n! geq 0 if !n! leq 94 for %%n in (!n!) do set "dat=!dat!!map:~%%n,1!"
  )
)

:: Find the version line and get the value
set "version="
for %%C in ("!lf!") do set "dat2=!dat:*%%~Cversion:=!"
if "!dat2!" neq "!dat!" (
  for /f "tokens=* eol= delims= " %%A in ("!dat2!") do (
    set "version=%%A"
    goto :done
  )
)
:done
set version
0 голосов
/ 18 февраля 2011

Если перед «версией» есть двоичные данные, то ваш IF не может работать.
Поскольку содержимое %% A является чем-то вроде «{двоичной} версии:»

.попробуйте, он проверяет, находится ли строка "версия" где-нибудь в строке.Если у вас есть "!"в ваших двоичных данных он может потерпеть неудачу, тогда решение должно быть pimped.

setlocal EnableDelayedExpansion
for /f "tokens=* delims=" %%A in ('type file.dat') do (
    set "line=%%A"
    set "version=!line:*version=!"
    if "!line!" NEQ "!version!" (
        goto found
    )
)
echo not found
goto end
:found
echo found: %version%
:end

РЕДАКТИРОВАТЬ:

for /f "tokens=* delims=" %%A in (file.dat) do (...

В обычном цикле for,основная проблема заключается в шестнадцатеричном коде 0x00, так как он находится в строке, чтение файла немедленно останавливается.

Но type или more может подавить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...