Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Циклическое повторение данных в файле (http://forum.oszone.net/showthread.php?t=338776)

Profile 17-01-2019 18:33 2852932

Циклическое повторение данных в файле
 
Здравствуйте.
Помогите создать скрипт или батник.
...что требуется?
есть файл "A" размером, допустим, 208байт, нужно создать файл "B", гораздо большего размера, например 127139792байта , циклично заполненного содержимым из файла "A"
т.е. проще говоря повторить файл "A" 611249 раз в файле "B".
Подкиньте идею)
Всю голову сломал

Iska 17-01-2019 19:23 2852946

Код:

>nul copy nul "b.txt" & for /l %i in (1, 1, 611249) do @>nul copy /b "b.txt"+"a.txt" "b.txt"
Сразу говорю, что этот подход категорически не эффективен — заморитесь ждать Ваших 127,139,792 результирующих байт. Но заниматься оптимизацией вычислений такой ерундой на пакетных файлах не вижу ни малейшего смысла.

Profile 17-01-2019 19:36 2852951

Цитата:

Цитата Iska
Сразу говорю, что этот подход категорически не эффективен — заморитесь ждать Ваших 127,139,792 результирующих байт. Но заниматься оптимизацией вычислений такой ерундой на пакетных файлах не вижу ни малейшего смысла. »

...то что нужно. Спасибо)

alpap 17-01-2019 20:14 2852965

Цитата:

Цитата Profile
создать файл "B", гораздо большего размера, например 127139792байта , циклично заполненного содержимым из файла "A" »

если закрыть на это глаза, то проще конечно так:
Код:

fsutil file createnew "B.txt" 127139792

Profile 17-01-2019 20:53 2852981

Цитата:

Цитата alpap
если закрыть на это глаза, то проще конечно так: »

да!
но как его заполнить файлом A?)

Iska 17-01-2019 21:52 2852998

Цитата:

Цитата Profile
но как его заполнить файлом A?) »

Никак. Чудес не бывает.

На WSH:
Скрытый текст
Код:

Option Explicit

Dim strSourceFile
Dim strDestFile

Dim strContent
Dim i


strSourceFile = "C:\Мои проекты\0238\a.txt"
strDestFile  = "C:\Мои проекты\0238\b.txt"

With WScript.CreateObject("Scripting.FileSystemObject")
        If .FileExists(strSourceFile) Then
                With .OpenTextFile(strSourceFile)
                        strContent = .ReadAll()
                        .Close
                End With
               
                With .CreateTextFile(strDestFile, True)
                        For i = 1 To 611249
                                .Write strContent
                        Next
                       
                        .Close
                End With
        Else
                WScript.Echo "Can't find source file [" & strSourceFile & "]."
                WScript.Quit 1
        End If
End With

WScript.Quit 0


YuS_2 17-01-2019 22:28 2853008

Цитата:

Цитата Iska
На WSH »

до кучи на powershell:
Код:

$cnt = 611249
$tmp = [io.file]::readalltext('a.txt',[text.encoding]::getencoding("windows-1251"))
#вариант для версии PoSh 3.0 и выше:
#$tmp = gc a.txt -raw -enc default
$str = new-object text.stringbuilder
for ($i = 0; $i -le $cnt; $i++){
        $null = $str.append($tmp)
}
$str.tostring()|sc b.txt -enc default

формируется примерно:
первичный запуск:
TotalSeconds : 16,5885417
повторный:
TotalSeconds : 5,4562804

конечно, скорость от железа может зависеть, но вполне приемлемое время, имхо.

Iska 17-01-2019 23:00 2853023

YuS_2, я бы всё-таки вынес [io.file]::readalltext('a.txt') за пределы цикла. Понятно, что по сути повторное чтение будет идти из кэша, но всё же, всё же, всё же…

Цитата:

Цитата YuS_2
формируется примерно:
TotalSeconds : 157,7945136 »

Что-то многовато. У меня на WSH — примерно 4-5 секунд занимает.

На мой взгляд, здесь лучше зараз писать в файл: конкатенация строк очень ресурсоёмкая операция.

Busla 17-01-2019 23:33 2853035

Код:

for /L %%i in (1, 1, 611249) do @type a.txt >> b.txt
Цитата:

Цитата YuS_2
~12 мин формируется»

потому что вы шаблон с диска читаете 611249 раз

mwz 18-01-2019 00:26 2853039

Цитата:

Цитата Busla
потому что вы шаблон с диска читаете 611249 раз »

Помнится, в бытность студеном на практических занятиях учились составлять программы на машине Мир-2 (транзисторные модули, перфолента, УВВ "Консул", язык — "русский бейсик").
Скрытый текст
Составили программку: тысячи циклов, включающих конструкция типа:

ЦИКЛ
...
ГДЕ A=3
ГДЕ B=5
...
КОНЦИКЛ

Чуем — что-то долго считает... Остановили, пустили на дальнейшее пошаговое исполнение с распечаткой каждого шага. Сначала ошалели, потом долго смеялись: 50% распечатки заняли строки
A=3
B=5

Ну заменили эти "ГДЕ" на константы, определив их перед циклом — и сразу программа задышала. :)

megaloman 18-01-2019 01:08 2853047

VBS: попробовал соптимизировать немного. На старинном ноуте 2-3 сек
Прямой вариант от Iska 11-13 сек
Код:

T1 = CStr(Now)
FileIn = "Z:\Box_In\FileIn.txt"
FileOut = "Z:\Box_In\FileOut.txt"
NMax = 611249
   
Set FSO = CreateObject("Scripting.FileSystemObject")

On Error Resume Next
Set fIn = FSO.OpenTextFile(FileIn, 1, False)

If Err.Number <> 0 Then
    MsgBox "File  " + FileIn + vbCrLf + Err.Description + "(" + CStr(Err.Number) + ")"
    WScript.Quit 2
End If
On Error GoTo 0

Alls = fIn.ReadAll
fIn.Close

S1 = Alls
S10 = Multi(S1, 10)
S100 = Multi(S10, 10)
S1000 = Multi(S100, 10)
S10000 = Multi(S1000, 10)
S100000 = Multi(S10000, 10)

N100000 = Int(NMax / 100000)

NN = NMax - N100000 * 100000
N10000 = Int(NN / 10000)

NN = NN - N10000 * 10000
N1000 = Int(NN / 1000)

NN = NN - N1000 * 1000
N100 = Int(NN / 100)

NN = NN - N100 * 100
N10 = Int(NN / 10)

N1 = NN - N10 * 10

Set F = FSO.OpenTextFile(FileOut, 2, True)
For i = 1 To N100000
    F.Write S100000
Next
F.Write Multi(S10000, N10000) + Multi(S1000, N1000) + Multi(S100, N100) + Multi(S10, N10) + Multi(S1, N1)
F.Close
MsgBox T1 + vbCrLf + CStr(Now)

'----------------------------------------------
Function Multi(SS, M)
    If M = 0 Then
        Multi = ""
        Exit Function
    End If
    SSM = SS
    For i = 2 To M
        SSM = SSM + SS
    Next
    Multi = SSM
End Function

Интересно всё-таки придумать на CMD ...

Profile 18-01-2019 03:18 2853055

кое что получилось вот таким образом:

Код:

@echo off
set symbol=FB7DB47D8BF0AC9840740C487413B40EBB0700CD10EBEFA0FD7DEBE6A0FC7DEBE1CD16CD19268B551A52B001BB0000E83B0072E85B8A5624BE0B7C8BFCC746F03D7DC746F4297D8CD9894EF2894EF6C606967DCBEA030000200FB6C8668B46F86603461C668BD066C1EA10EB5E0FB6C84A4A8A460D32E4F7E20346FC1356FEEB4A525006536A016A10918B4618969233D2F7F691F7F64287CAF7761A8AF28AE8C0CC020ACCB80102807E020E7504B4428BF48A5624CD136161720B40750142035E0B497506F8C341BB000060666A00EB
set file=bin
<nul set /p x=>%file%
for /L %%A IN (1,1,611249) DO (<nul >>%file% set /p x=%symbol%)
msg * "Done!"
exit /b

засунул свои 208байт прямо в команду, но все это дело сохраняется как текст, как сохранить это в бинарном виде?

YuS_2 18-01-2019 09:25 2853063

Цитата:

Цитата Iska
за пределы цикла »

Цитата:

Цитата Busla
шаблон с диска читаете 611249 раз »

согласен. поправил...
Изначально в том коде просто нули были, а я вместо этого чтение файла добавил бездумно... :)

Busla 18-01-2019 10:56 2853074

Сидит полный форум несмыслёнышей: кодить умеют, а что писать не знают. И тут приходит Profile, весь в белом™ и наставляет на путь истинный: не берите шаблон из файла, а храните в переменной.

Позволяли бы батники работать с бинарными данными, - так бы и написали, а не советовали на других языках реализовывать.

YuS_2, megaloman, Iska а вы уверены, что текстовое данных представление не даст стороннего эффекта?

YuS_2, задним числом редактировать откоментированные сообщения некорректно и неэтично

YuS_2 18-01-2019 11:12 2853079

Цитата:

Цитата Busla
а вы уверены, что текстовое данных представление не даст стороннего эффекта? »

В вопросе звучало что? Заполнить файл B данными из файла A
В смысле, что не так?

Цитата:

Цитата Busla
некорректно и неэтично »

Почему? Я же написал, что с замечаниями согласен и потому код поправлен. Там же нет ничего такого, что имеет принципиальное значение... :)
Имхо, наоборот, неэтично плодить лишние сущности и оставлять для будущих читателей не совсем корректный код... да и в принципе, зачем дублировать сообщения с кодом, когда его можно просто поправить? Зайдет читатель в топик, а тут от разнообразия кода в глазах рябит и какой из представленных вариантов правильный? По-моему, гораздо правильнее оставить тот код, который наиболее верный и может представлять интерес для будущих читателей, а остальное беспощадно чистить... т.е. не вижу ни одной причины, чтобы хранить на форуме некорректные коды.

Profile 18-01-2019 12:08 2853090

Цитата:

Цитата Busla
Позволяли бы батники работать с бинарными данными, - так бы и написали, а не советовали на других языках реализовывать. »

...т.е. придется что-то сочинять? так просто не отделаюсь?

mwz 18-01-2019 13:23 2853106

Цитата:

Цитата Profile
611249 раз »

Для курьёза:
611249=10010101001110110001b

Скрытый текст
Запоминаем содержимое файла A как Шаблон-0 (ну этот шаг можно пропустить: оно и так будет в самом файле; просто для единообразия алгоритма) и далее используем как Шаблон-1.

Четыре раза (следующая единичка левее в двоичном значении) делаем конкатенацию Шаблон-1 с самим собой, сохраняя в том же Шаблон-1.
Сохраняем полученный файл и далее используем как как Шаблон-2.

Один раз (следующая единичка левее в двоичном значении) делаем конкатенацию Шаблон-2 с самим собой, сохраняя в том же Шаблон-2.
Сохраняем полученный файл и далее используем как как Шаблон-3.

И т.д. до последней единицы левее — сохраняя промежуточные удвоенные файлы при появлении 1 в исходном двоичном значении.

Делаем конкатенацию всех промежуточных шаблонов, начиная с Шаблон-0.

Задача решена.

PS
Возможна и более быстрая реализация этого алгоритма без использования промежуточных шаблонов, а только текущего удваиваемого и исходного файла A — если начать разборку двоичного значения слева.

Profile 18-01-2019 13:35 2853107

Цитата:

Цитата mwz
Для курьёза:
611249=10010101001110110001b »

наверное работае, для того кто понимает в этом)))
а как это в батнике реализовать?

megaloman 18-01-2019 15:33 2853123

Цитата:

Цитата Busla
... megaloman ... а вы уверены, что текстовое данных представление не даст стороннего эффекта? »

Не уверен. Я вообще не понимаю смысл задачи.
Цитата:

Цитата Profile
засунул свои 208байт прямо в команду, но все это дело сохраняется как текст, как сохранить это в бинарном виде? »

Вообще смысл реплики ускользает. Что в файле? Текст? Что значит сохранить эту строку в бинарном виде?
Profile,
Вот CMD на основе Copy /B. По времени (несколько секунд) немного медленнее, чем моё решение в VBS (но там алгоритм менее эффективный и на основе текстового потока).
Код:

@@Echo Off
cls
Set T=%Time%
        Set "FileIn=Z:\Box_In\FileIn.txt"
        Set "FileOut=Z:\Box_In\FileOut.txt"
        Set /A Max=611249

        If Not Exist "%FileIn%"  (Echo !!! File "%FileIn%" not found &Pause &Exit /B 2)

        Set /A @@01=2, @@02=4, @@03=8, @@04=16, @@05=32, @@06=64, @@07=128, @@08=256, @@09=512, @@10=1024, @@11=2048, @@12=4096, @@13=8192, @@14=16384, @@15=32768, @@16=65536, @@17=131072, @@18=262144, @@19=524288, @@20=1048576, @@21=2097152

        Set /A Min=0
        Set "Var="
        Set "All="
        Set /A Re=%Max%

        :Begin
                Set /A Re=%Re%-%Min%
                Set "All=%Var% %All%
                If %Re% LSS 2 GoTo :Continue
                FOR /F "usebackq tokens=1,2 delims==" %%i IN (`Set "@@"`) DO (
                        If %%j GTR %Re% GoTo :Begin
                        Set /A Min=%%j
                        Set "Var=%%j"
                )
        :Continue
        Call :Double "%FileIn%" "%FileOut%" %Re% %All% 
Echo %Time%
Echo %T%
Pause
GoTo :Eof

:Double
        Copy /B %1 "%~1~tmp1" >nul
        Copy /B %1 "%~1~tmp2" >nul
        > %2 (cd.)
        If %3 EQU 1 Copy /B %1 %2 >nul
       
        Set /A i=1
        :Beg1
                Set /A i=2*i
                Copy /B "%~1~tmp2"+"%~1~tmp1" "%~1~tmp2" >nul
                Copy /B "%~1~tmp2" "%~1~tmp1" >nul
                If %i% NEQ %4 GoTo :Beg1
                Copy /B %2+"%~1~tmp2" %2 >nul
                Shift /4
                If Not "%4"=="" GoTo :Beg1
                Del "%~1~tmp1"
                Del "%~1~tmp2"
GoTo :Eof

Что плохо: за скорость надо заплатить (в худшем случае трёхкратным свободным местом для работы скрипта)

alpap 18-01-2019 16:05 2853128

вот на чистом bat
Код:

@echo off
<A.txt (for /f "delims=" %%a in ('more') do set /a n+=1& call set "$_%%n%%=%%a")
>B.txt (for /l %%n in (1 1 611249) do @set $_)
pause

Да, не быстро: время старт/стоп
14:46:20,29
14:47:09,82
но все же менее минуты,
для сравнения время по коду megaloman,
15:10:38,53
15:10:39,47
НО, придется согласиться с появлением в каждой строке приставки: "$_n+1=" (n+1 - номер строки A.txt), что впрочем легко убирается (строка после "="), если нужен будет правильный вывод из B.txt. (Сразу сделать это не получиться если время дорого).

Profile 18-01-2019 16:58 2853136

Цитата:

Цитата megaloman
Вообще смысл реплики ускользает. Что в файле? Текст? Что значит сохранить эту строку в бинарном виде? »

Спасибо огромное.
Сутки не спал, то что нужно. Создается файл циклический как и нужно.

Огромное спасибо всем откликнувшимся


Время: 19:17.

Время: 19:17.
© OSzone.net 2001-