Имя: Пароль:
1C
1С v8
Распаковка сотен ZIP-файлов в одну папку
, ,
0 Night_Wolf
 
30.07.14
11:06
Есть 400 с гаком zip-файлов. Названия все разные (по ID контрагента). Лежат архивы в одной папке. Я читаю все файлы и пытаюсь по очереди их распаковать. Код:

Каталог = "E:\PDF-файлы\";
Файлы = НайтиФайлы(Каталог,"*.zip");
Для каждого Файл из Файлы Цикл
    Архив = Новый ЧтениеZipФайла();    
    Архив.Открыть(Файл.ПолноеИмя);                        
    Архив.ИзвлечьВсе(Каталог);
    Архив.Закрыть();
КонецЦикла;

первый файл распаковывается на ура. Второй - всегда с ошибкой:
Ошибка при вызове метода контекста (ИзвлечьВсе)
        Архив.ИзвлечьВсе(Каталог);
по причине:
Операция выполнена с ошибками

После чего процесс прерывается. Подскажите что это может быть и куда покопать?
1 Господин ПЖ
 
30.07.14
11:08
может не успевает
2 f_vadim
 
30.07.14
11:11
а если распаковывать в другой каталог?
3 Один С
 
30.07.14
11:12
атак?

Каталог = "E:\PDF-файлы\";
Файлы = НайтиФайлы(Каталог,"*.zip");
Для каждого Файл из Файлы Цикл
    Архив = Новый ЧтениеZipФайла(Файл.ПолноеИмя);                          
    Архив.ИзвлечьВсе(Каталог);
    Архив.Закрыть();
КонецЦикла;
4 Night_Wolf
 
30.07.14
11:12
Самое что интересное - файл после того как вылетело в каталоге распакованный есть. Такое ощущение, что где-то ещё связи скрытые от старого остаются.
(2) - в другой каталог сейчас попробую.
5 Один С
 
30.07.14
11:14
алучшетак..

Каталог = "E:\PDF-файлы\";
Файлы = НайтиФайлы(Каталог,"*.zip");
Для каждого Файл из Файлы Цикл
    Архив = Новый ЧтениеZipФайла(Файл.ПолноеИмя);                          
    Архив.ИзвлечьВсе(Каталог);
    Архив.Закрыть();
    УдалитьФайлы(Стр.ПолноеИмя);
КонецЦикла;
6 Night_Wolf
 
30.07.14
11:17
(3) - и так та же самая ошибка вылезает.
(2) - Ошибка другая:
Ошибка при вызове метода контекста (ИзвлечьВсе)
        Архив.ИзвлечьВсе("Е:\Распаковка\");
по причине:
Ошибка создания файла: Е:\Распаковка\014f10d2-dc04-11df-9bcd-00e0814bddfb-31-07-2014.pdf
7 f_vadim
 
30.07.14
11:18
(6) а просто unzip эти файлы распаковывает?
8 ДенисЧ
 
30.07.14
11:18
А может, проще?
КомандаСистемы("winrar e e:\распакаовка\*.zip");
?
9 mikecool
 
30.07.14
11:18
имхо - таймаут, надо задержку между распаковками ставить
10 Night_Wolf
 
30.07.14
11:21
(7) - даже в Unreal commander распаковывает без проблем. Но если вхожу внутрь любого файла и говорю "распаковать и выполнить" - пишет "неизвестная ошибка".  
(8) - WinRar не вариант - специально zip-ом жал.
11 Соло
 
30.07.14
11:24
(8) unrar.exe будет корректнее, он по крайней мере не требует лицензирования
12 Один С
 
30.07.14
11:25
(6) не может быть. у меня так работает. проблема в том, что строчка Архив.Открыть у тебя лишняя.
13 ОфисныйБабай
 
30.07.14
11:25
у зипа есть свои консольные команды как у вин рара? такой же алгоритм реализовывал через команды, все норм.
14 f_vadim
 
30.07.14
11:27
(10) сдаётся мне, на длине наименования затык.
unreal не показатель, попробуй консольный unzip
15 Night_Wolf
 
30.07.14
11:41
(12) - я сделал как у тебя - не работает. Вылетает именно на втором файле. Каким бы он ни был.
16 f_vadim
 
30.07.14
11:42
мож архив битый?
17 Night_Wolf
 
30.07.14
11:44
(15) - ошибся, скопировал несколько файлов в другую папку, попробовал из неё - сразу вылетело на первом же.
(16) Архив не битый - разархивируется же стандартно без проблем любой файл.

Может ли быть проблема в том, что эти файлы хранятся в БД в двоичном формате IMAGE? Я их упаковываю и ложу в базу через ADODB. Потом достаю и хочу распаковать и просмотреть. Это pdf-ки, которые в 1С не нужны в типовой.
18 Night_Wolf
 
30.07.14
11:50
Обнаружил странный глюк: Из 10 файлов например, когда нажимаю "извлечь в текущую папку" - получаю что разархивируется один и тот же файл. Как будто бы они ссылаются на один. Вообще странность. Привожу код записи файлов:
Пока RecordSet.EOF() = 0 Цикл
// Пишем таблицу
Строка = ТаблицаДокументов.Добавить();
Строка.ConsumerID = RecordSet.Fields("ConsumerID").Value;
Строка.Value = RecordSet.Fields("Value").Value;
Строка.Extension = RecordSet.Fields("Extension").Value;
RecordSet.MoveNext();
КонецЦикла;

И потом из таблицы уже сохраняю файлы на диск:
мПоток = Новый ComОбъект("ADODB.Stream");
мПоток.Type = 1;
мПоток.Open();
Для каждого Строка из ТаблицаДокументов Цикл
    ИмяФайлаПриемника = Каталог+Строка.ConsumerID+".zip";
    мПоток.Write(Строка.Value);
    мПоток.SaveToFile(ИмяФайлаПриемника, 2);        
КонецЦикла;

Может тут где-то косяк? Я с ADO не работал ранее из 1С.
19 Серго62
 
30.07.14
12:13
Я вот так делал:
RS.MoveFirst();
Пока НЕ RS.EOF Цикл
    //Тут твои операторы
    RS.MoveNext();
КонецЦикла;


RS - это рекордсет
20 Night_Wolf
 
30.07.14
12:26
(19) - Проблема такая: Считал значения двух документов из БД. Записал их в строки таблицы в поле Value. Затем в цикле пишу:
мПоток.Write(Строка.Value);
мПоток.SaveToFile(ИмяФайлаПриемника, 2);  

Для первого дока получаю: Док1.zip и внутри у него Док1.pdf,
для второго дока получаю: Док2.zip, но внутри у него Док1.pdf.

Причем Док1.pdf в первом архиве и Док1.pdf - это разные доки, у них разное содержимое, правильное. Но при распаковке Док2.zip получаю файл док1.pdf. Это если упрощённо.

Соответствено вопрос: вот в этой строке кода
мПоток.SaveToFile(ИмяФайлаПриемника, 2);
как указать, чтобы pdf файл назывался также, как и zip-файл, то есть Док2 ?
21 ДенисЧ
 
30.07.14
12:28
(20) Ты хочешь через адо поменять содержимое архива? Не взлетит
22 Night_Wolf
 
30.07.14
12:33
(21) - почему поменять? Я пишу pdf-ки из MS SQL на диск, в архивы. И не понимаю, почему если я уже пишу данные контрагента С в файл С.zip (например есть A.pdf, B.pdf, C.pdf), то почему у меня записываются именно данные контрагента С, но с названием A.pdf ? Почему не C.pdf в архиве?
23 ДенисЧ
 
30.07.14
12:34
(22) Потому что так пишешь
24 DrZombi
 
гуру
30.07.14
12:34
(22) Почему там должен быть C.pdf ?
Если ты не указал :)
25 DrZombi
 
гуру
30.07.14
12:35
+ Зачем тебе АДО?
26 Night_Wolf
 
30.07.14
12:35
(23) Подскажи пожалуйста, а как ему указать чтобы он файл, который в архиве, называл правильно?
В строке мПоток.Write(Строка.Value); - просто поток данных в двоичном формате насколько я понимаю.
27 Night_Wolf
 
30.07.14
12:36
(25) - у меня задача такая - хранить pdf-ки где-то. Хранить их в 1С я не придумал как. Да и не нужны они в ней, поэтому сделал стороннюю БД с нужной таблицей.
28 DrZombi
 
гуру
30.07.14
12:37
+ Распаковка сотен ZIP-файлов в одну папку

Тут зарыты куча проблем.
  - Файловая система не любит, когда в одном каталоге 10000 -тысячи файлов, тормозит однако.
  - ты рискуешь нарваться на повторение имени распакуемого файла
29 DrZombi
 
гуру
30.07.14
12:38
(27) Хранить их в 1С я не придумал как.

Если на сиквеле или еще где, много места HDD, то храни, как картинки, подсмотри в УПП или еще где.

В простом Регистре Сведений.
30 Night_Wolf
 
30.07.14
12:39
(28) - повторение имени файла не произойдет, потому что имя файла - это UID контрагента + дата в формате "ДДММГГГГ". Это мы уже проходили, решили больше на такие грабли не напарываться. Все доки будут выбираться в папку максимум за месяц.
(29) - в 1С хранить не хочу, потому что архивы баз будут больше всего лишь из-за актов сверок, которые через год уже можно будет почистить за предыдущий год.
31 Night_Wolf
 
30.07.14
12:40
(28) - подскажи как ему указать что имя данных, которые он сохраняет - должно быть С.pdf?
32 DrZombi
 
гуру
30.07.14
12:44
(31) Покажи код, как ты Упаковываешь через АДО?
И как ты присваиваешь нужное имя файлу, который упакуешь?
33 Garykom
 
гуру
30.07.14
12:45
(0)(32) не издевайся извлекай во временную папку и переименовывай/копируй куда надо уже распакованное, потом удаляй старый если копируешь и новый распаковывай
34 Garykom
 
гуру
30.07.14
12:46
(33)+ как понял проблема одинаковые имена файлов внутри разных архивов
35 Night_Wolf
 
30.07.14
12:48
(32) Вот:
ИмяВременногоФайла = КаталогВременныхФайлов()+СокрЛП(Контрагент.УникальныйИдентификатор())+"-" +Формат(КонецМесяца(ДатаЗаписиДокументов)-1,"ДФ='dd-MM-yyyy'")+".pdf";        ТабДок.Записать(ИмяВременногоФайла,ТипФайлаТабличногоДокумента.PDF);
пФайл = Новый Файл(ИмяВременногоФайла);

Затем заворачиваю в zip:
ИмяZipФайла = ПолучитьИмяВременногоФайла("zip");

        УровеньСжатия = УровеньСжатияZIP.Оптимальный;
        Zip = Новый ЗаписьZipФайла(ИмяZipФайла, , , , УровеньСжатия);
                
Zip.Добавить(ИмяВременногоФайла);
Zip.Записать();
    
ФайлZip    = Новый Файл(ИмяZipФайла);

А далее в поток:
Поток = Новый ComОбъект("ADODB.Stream");
Поток.Type = 1;
Поток.Open();
Поток.LoadFromFile(ФайлZip    .ПолноеИмя);
RecordSet.Fields("Value").Value = Поток.Read();
RecordSet.Update();


В zip лежит правильно сформированное имя файла.
36 DrZombi
 
гуру
30.07.14
12:48
(34) Трудно сказать, у (0) не пойми как вообще упаковывает :)
37 DrZombi
 
гуру
30.07.14
12:51
(35) И для чего там АДО? :)

Типо для скорости? Как крылышки на жигули? :)
38 Night_Wolf
 
30.07.14
13:03
(34) - правильно понял. Как бы это мне побороть? :)
39 Night_Wolf
 
30.07.14
13:03
(37) - я просто другого способа сложить документы в стороннюю БД не нашёл. Воспользовался тем, что нашёл. Да и скорость мне нравится, а при отправке доков потребителям она возможно будет критичной.
40 DrZombi
 
гуру
30.07.14
13:08
(38) Что там бороть, именуй уникально и будет тебе счастье :)

В строку "ДФ='dd-MM-yyyy'" добавь время до секунды.
41 Night_Wolf
 
30.07.14
13:09
(33) - так так всё и делается. Переименовывается правда в этой же папке, но старый удаляется. Код в (0) - он в цикле происходит. И там есть УдалитьФайлы(), после копирования. На точке останова всё так и происходит - файл распаковался, скопировался с новым (нужным) именем, старый удалился, распаковывается новый.
42 DrZombi
 
гуру
30.07.14
13:09
+(39) >>>> RecordSet.Fields("Value").Value = Поток.Read();
RecordSet.Update();

Это ты к какой БД пытаешься уложиться? :)
На чем оно работает, SQL, DBA?
43 Night_Wolf
 
30.07.14
13:10
(42) MS SQL.
44 DrZombi
 
гуру
30.07.14
13:11
(43) Сторонняя БД, случаем не другая 1C? ):
45 Night_Wolf
 
30.07.14
13:12
(44) Нет, я просто создал БД на SQL, с одной таблицей с нужными полями и туда файлы запихиваю.
46 DrZombi
 
гуру
30.07.14
13:12
(43) Ты Поток закрываешь, после каждого файла?
47 DrZombi
 
гуру
30.07.14
13:15
+(45) А вообще, ты пытался уточнить, Что возможно ты всегда кладешь в свою SQL таблицу один и тот же файл.

А где ты имена Архива хранишь?
Ты же в SQL кладешь не имя файла, а Двоичный набор данных :)
48 Night_Wolf
 
30.07.14
13:19
(46) - нет, поток я не закрываю после записи каждого файла. Сейчас попробую.

(47) - В SQL всё нормально, потому что файлы, который внутри zip-ов, хоть и называются однинаково, но если распаковать их в разных каталогах и открыть одновременно - там разная информация.

Имена архивов я нигде не храню - я их беру из ID контрагента. Ведь я данные (по сути двоичные) записываю в архив с именем, с каким мне хочется. Это то не влияет.
49 Night_Wolf
 
30.07.14
13:21
(47) -  если быть до конца точным с именем zip:

Для каждого Строка из ТаблицаДокументов Цикл
  ИмяФайлаПриемника = Каталог+Строка.ConsumerID+".zip";
  мПоток.Write(Строка.Value);
  мПоток.SaveToFile(ИмяФайлаПриемника, 2);        
КонецЦикла;
50 Night_Wolf
 
30.07.14
13:26
(46) - ты гений! Ларчик просто открывался:

мПоток = Новый ComОбъект("ADODB.Stream");
мПоток.Type = 1;
Для каждого Строка из ТаблицаДокументов Цикл
  мПоток.Open();
  ИмяФайлаПриемника = Каталог+Строка.ConsumerID+".zip";
  мПоток.Write(Строка.Value);
  мПоток.SaveToFile(ИмяФайлаПриемника, 2);        
  мПоток.Close();
КонецЦикла;

Спасибо всем!
P/S Админам, если не сложно - можно тему переименовать в "Запись ZIP-файлов из MS SQL на диск через ADO". А то вдруг кто-то будет искать решение.
51 Один С
 
30.07.14
13:41
(50) Назначаю тебя Админом. Переименуй тему сам. Нажми на стрелку слева от названия темы.
52 Night_Wolf
 
30.07.14
13:55
(51) - не вижу стрелки слева. Может скрин для тупых на почту: [email protected] ?
53 Один С
 
30.07.14
14:02
54 Night_Wolf
 
30.07.14
14:07
(53) Спасибо, но у меня только это:
http://www.picshare.ru/view/4929620/

Сорри за флуд.
55 DrZombi
 
гуру
30.07.14
14:46
(54) Эта ссылка "Vote", даже у меня есть :)
56 DrZombi
 
гуру
30.07.14
14:48
+(54) Самое странное, как ты смог удалять Архивы, при незакрытом потоке ;)