Войти

Показать полную графическую версию : Разбить тхт файл не только по строкам, но и по папкам


Страниц : [1] 2

Abricosio
11-07-2018, 15:15
В замечательной теме (http://forum.oszone.net/post-1961186.html) раскрывается вопрос, как разбить большой тхт файл на много мелких по кол-ву строк
Моя задача чуть шире. Есть файл на 10 млн строк. Мне нужно получить 100 папок, в каждой по 100 файлов тхт, в каждом файле по 1000 строк из стартового файла.
Названия папок 1,2,3,4,5,...,100
Названия файлов 1.txt, 2.txt, 3.txt, ..., 100.txt

Кто-нибудь может помочь с этой непосильной для меня задачей?

YuS_2
11-07-2018, 15:29
Кто-нибудь может помочь с этой непосильной для меня задачей? »
CMD тут вряд ли поможет... 10 млн. строк... подавится считать... :)
Лучше вооружитесь powershell-ом.

Abricosio
11-07-2018, 15:32
А как powershellом это сделать? :)

Iska
11-07-2018, 17:04
Abricosio, размер файла:
Есть файл на 10 млн строк. »
каков? В мегабайтах?

Busla
11-07-2018, 17:59
как powershellом это сделать? »

просто по файлам раскидать вот так:
$counter = 0; $linesPerFile=10000; Get-Content .\big.log | ForEach-Object { $counter++; Add-Content -Path "$(($counter/$linesPerFile).ToString('000000')).log" -Value $_ }
к сожалению, в реализации Add-Content Микрософт накосипорила - директории он автоматически не создаёт, поэтому коротко не написать :(
После Get-Content указываете путь к файлу, в текущей директории создаются файлы по 10 тыс строк (количество задаётся переменной $linesPerFile)

размер файла:
каков? В мегабайтах? »
это неважно, не требуется никакого хитрого анализа, чтобы его его целиком в память пихать

YuS_2
11-07-2018, 18:00
А как powershellом это сделать? »
Как-то так:
$fl = 'test.txt'
$root = 'root'
if (!(test-path $root)){md $root|out-null}
gc $fl -read 1000|%{$i,$n=1,1}{
$tmp = "$root\$n"
if(!(test-path $tmp)){md $tmp|out-null}
set-content -path "$tmp\$i.txt" -val $_
switch ($i) {
100 {$n++;$i=0}
}
$i++
}

чтобы его его целиком в память пихать »
если его целиком пихать в память, powershell загнется не хуже (или не лучше?) cmd :)

Busla
11-07-2018, 18:36
если его целиком пихать в память, powershell загнется не хуже (или не лучше?) cmd »
и сам делаешь то же самое: если пользователь решит делить файл не на 100 тыс. файлов, а на два? - всё переписывать?

YuS_2
11-07-2018, 18:43
и сам делаешь то же самое »
где? присмотрись повнимательнее...

Разве что, можно чуток оптимизировать, чтобы не дергать $tmp при каждой итерации:
$fl = 'test.txt'
$root = 'root'
if (!(test-path $root)){md $root|out-null}
gc $fl -read 1000|%{$i,$n=1,1;$tmp = "$root\$n"}{
if(!(test-path $tmp)){md $tmp|out-null}
set-content -path "$tmp\$i.txt" -val $_
switch ($i) {
100 {$n++;$i=0;$tmp = "$root\$n"}
}
$i++
}

Iska
11-07-2018, 19:41
это неважно, не требуется никакого хитрого анализа, чтобы его его целиком в память пихать »
Э… Ну, запихните в память текстовый файл в десять-двадцать гигабайт.

Busla
11-07-2018, 20:17
где? »
результирующий файл формируется в памяти и за раз пишется инструкцией set-content

Ну, запихните в память текстовый файл в десять-двадцать гигабайт. »
зачем?

YuS_2
11-07-2018, 20:31
результирующий файл формируется в памяти и за раз пишется инструкцией set-content »
И что? Я говорю о:
gc text.txt
и
gc text.txt -readcount 1000
В первом случае, по конвейеру будет передаваться первая строка только после помещения всего файла в память (что может привести к достаточно длительному ожиданию, если не зависанию, при достаточно большом файле). Во втором случае, первая строка (вернее блок строк) передается после помещения в память некоторого количества строк -readcount <int64>, что значительно ускоряет процесс... в общем, попробуйте, тогда станет понятно в чем разница.

Iska
11-07-2018, 20:44
зачем? »
Затем, что не поместится.

Abricosio
11-07-2018, 22:00
Все отлично в примере на павершел, один только нюанс - пустая строчка в самом конце, но я ее регуляркой почикаю) Спасибо!

Busla
11-07-2018, 22:10
YuS_2, неверно
по умолчанию readcount равно единице, чтобы прочитать весь файл за раз нужно принудительно выставить нуль

Вы смешали в одно "буфер чтения" и размер выходного файла. Всё это "значительно ускоряет процесс" пока файлы крохотные. А как только понадобится напилить файл на куски по несколько ГБ (например, чтобы на DVD записать) - так сразу скрипту и поплохеет.

Iska
11-07-2018, 22:23
Busla, YuS_2, в документации сказано, что:
-ReadCount <Int64>
Specifies how many lines of content are sent through the pipeline at a time. The default value is 1. A value of 0 (zero) sends all of the content at one time.

This parameter does not change the content displayed, but it does affect the time it takes to display the content. As the value of ReadCount increases, the time it takes to return the first line increases, but the total time for the operation decreases. This can make a perceptible difference in very large items.
но ничего не сказано про собственно само чтение. Как с этим обстоит дело?

Abricosio
11-07-2018, 22:38
А нет, не получается, регуляркой эту строку не видно, удалить массово через notepad++ не получается. Возможно ли переделать скрипт, чтобы он не делал 1001-ю пустую строку?
Заранее большое спасибо!

Iska
11-07-2018, 22:45
Abricosio, там нет «пустой строки»:

https://i.imgur.com/nClHTbb.png

где Вы её нашли?!

Abricosio
11-07-2018, 23:04
Странно, у меня во всех файлах последняя строка пустая, 1001я. Проверял в notepad++ и обычном тхт редакторе

Iska
12-07-2018, 00:32
Abricosio, это:

https://i.imgur.com/nnKcpS4.png

не «пустая строка».

Пустая строка — вот:

https://i.imgur.com/6rGzKIY.png

Если Вам категорически нужно, чтобы последняя строка не завершалась символами конца строки:

https://i.imgur.com/9Zb0pyE.png

— это другое дело.

YuS_2
12-07-2018, 05:40
чтобы прочитать весь файл за раз »
gc text.txt -raw

Вы смешали в одно "буфер чтения" и размер выходного файла. »
Я? Где? :)
Лично я говорил о том, что вредно помещать весь файл (при условии, что он достаточно большой) в память, чтобы производить с ним дальнейшие манипуляции. О размерах выходного файла заговорил ты, я ничего об этом не писал.

А как только понадобится напилить файл на куски по несколько ГБ (например, чтобы на DVD записать) - так сразу скрипту и поплохеет. »
Чтобы поменьше теоретизировать, предлагаю провести простой эксперимент:
1. Создай текстовый файл (UTF8, хотя это неважно), в 10000000 строк, с одним символом в каждой строке. Размер у него получится не сильно большим (чуть больше 28Мб), но достаточным для эксперимента. Возможно, конфигурация компьютера будет влиять на результат, но это можно "поправить" увеличением количества строк. :)
2.
a)
gc text.txt -read 5000000|set-content text-out.txt
b)
gc text.txt|set-content text-out.txt
3. Приведи здесь результат эксперимента.

Мои результаты:
a) TotalSeconds : 6,9191207
b) Неадекватное потребление физ.памяти до 3,5Гб и более процессом powershell, нагрузка процессора в 50% и более, плюс подвисания интерфейса windows. Терпения, чтобы дождаться окончания процесса (если это реально), у меня не хватило. В общем, плохеет не только скрипту и размер у файла не очень-то огромный... :)




© OSzone.net 2001-2012