Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
Lerikorner
0 / 0 / 1
Регистрация: 27.03.2016
Сообщений: 41
1

Склеивание архивов GZipStream - Неверный размер файла

27.04.2016, 13:25. Просмотров 1251. Ответов 4
Метки нет (Все метки)

Всем привет.
Пишу архиватор, который делит исходный файл на фрагменты, их жмёт GZipStream, далее склеивает сжатые фрагменты. В итоге имеем архив с непонятным размером (больше исходного). Файл внутри архива тоже имеет кривую длину, равную длине последнего записанного фрагмента.
Исходник при этом замечательно распаковывается.

Может, подскажет кто, в чем ошибка?

UPD запакованные фрагменты тоже кривых каких-то размеров. А вот бьется файл нормально

Добавлено через 1 час 6 минут
Проблема вылезает на любом файле (пробовал jpg, avi, cdr)

А также проблема вылезает и без биения. коэффициент разный
в среднем 1.5. Исключение txt, который жмется без проблем

Добавлено через 6 минут
.net 3.5
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.04.2016, 13:25
Ответы с готовыми решениями:

Создать поток сжатия GZipStream, и перенести данные из открытого файла в поток GZipStream
Здравствуйте. Объясните мне пожалуйста следующую вещь: Необходимо открыть файл для чтения. Создать...

При сжатии GZipStream размер выходного файла больше оригинала
Привет! гугл особо не помог по теме, хотя такую проблему встречал: при сжатии с помощью GZipStream...

GZipStream: Размер архива больше оригинала
Ну, собственно, вопрос в заголовке. Если я архивирую файл с разрешением .avi, .mp3 - архив (.gz) в...

GZipStream архивация частей файла
В общем делю файл на конкретное кол-во байт, но при архивации, части архива разного размера, не тот...

GZipStream. Сжатие, распаковка файла.
Народ помогите разобраться, вот правильно ли я сжимаю и разжимаю файлы? Просто например WinRar не...

4
Storm23
Эксперт .NETАвтор FAQ
9292 / 4512 / 1636
Регистрация: 11.01.2015
Сообщений: 5,731
Записей в блоге: 34
27.04.2016, 17:25 2
Цитата Сообщение от Lerikorner Посмотреть сообщение
Может, подскажет кто, в чем ошибка?
В 37-й строке.
0
Lerikorner
0 / 0 / 1
Регистрация: 27.03.2016
Сообщений: 41
27.04.2016, 17:39  [ТС] 3
Цитата Сообщение от Storm23 Посмотреть сообщение
В 37-й строке.
Вижу-вижу спасибо.

на всякий случай код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
using System;
using System.IO;
using System.IO.Compression;
using System.Threading;
 
namespace Compress_Decompress
{
 
    class GZipTest
    {
        public static int BufferSize = 2048 * 2048;  //!!!!!!
        public static bool error;
        public static  int multithread = Environment.ProcessorCount;//количество потоков
     
        public static void Compress(string inFileName, string outFileName)//путь к входному файлу, путь к выходному файлу, флаг
        {
            try
            {
                using (FileStream inFile = new FileStream(inFileName, FileMode.Open))//инициализация входного файла
                {
                    using (FileStream outFile = new FileStream(outFileName, FileMode.Create, FileAccess.Write))//инициализация выходного файла
                    {
                        //
                        // ПРИ РАБОТЕ С КОНСОЛЬЮ WINDOWS 
                        // ОБЯЗАТЕЛЬНО УКАЗЫВАЕМ ПОЛНЫЙ ПУТЬ И РАСШИРЕНИЕ ДЛЯ ВХОДНЫХ И ВЫХОДНЫХ ФАЙЛОВ!!!! 
                        //
                        using (GZipStream inGZip = new GZipStream(outFile, CompressionMode.Compress))//буферный поток сжатия
                        {
                            int read, i = 0, j = 0;
                           // int[] read = new int[multithread];
                            byte[] buffer = new byte[BufferSize];
                            Thread[] thread = new Thread[multithread];
                        //    object block = new object();
                            while ((inFile.Length - inFile.Position) > BufferSize)
                            {                                   
                                for (j = 0; (j < multithread-1) && 
                                    (inFile.Length - inFile.Position > BufferSize); j++)
                                {
                                    read = inFile.Read(buffer, 0, BufferSize);
                                    thread[j] = new Thread(()=>
                                    {
                                 //       lock(block)
                                        {
                                            Console.Write("- {0} -", j);
                                        //    read = inFile.Read(buffer, 0, BufferSize);
                                            inGZip.Write(buffer, 0, read);
                                        }
                                    });                                  
                                    thread[j].Start();
                                }
                                for (i = 0; i < j; i++)
                                {
                                    thread[i].Join();
                                }
                            }                            
                            inGZip.Write(buffer, 0, inFile.Read(buffer, 0, BufferSize));
                            inGZip.Close();  //!!!!!!
                        }
                        outFile.Close();
                    }
                    inFile.Close();
                    error = false;
                    Console.WriteLine(" finished packing. ");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message);
                error = true;
            }
        }
 
        public static void Decompress(string inFileName, string outFileName) //путь к входному файлу, путь к выходному файлу
        {
            try
            {
                using (FileStream inFile = new FileStream(inFileName, FileMode.Open))//инициализация входного файла
                {
                    using (GZipStream outGZip = new GZipStream(inFile,CompressionMode.Decompress))
                    {
                        //
                        // ПРИ РАБОТЕ С КОНСОЛЬЮ WINDOWS 
                        // ОБЯЗАТЕЛЬНО УКАЗЫВАЕМ ПОЛНЫЙ ПУТЬ И РАСШИРЕНИЕ ДЛЯ ВХОДНЫХ И ВЫХОДНЫХ ФАЙЛОВ!!!! 
                        //
                        using (FileStream outFile = new FileStream(outFileName, FileMode.Create, FileAccess.Write))     //инициализация буфера распаковки
                        {
                            int read = 0, i = 0, j = 0;
                            //  int[] read = new int[multithread];
                            byte[] buffer = new byte[BufferSize];
                            Thread[] thread = new Thread[multithread];
                            object block = new object();
                            while ((inFile.Length - inFile.Position) > BufferSize)
                            {
                                for (j = 0; (j < multithread-1) && ((inFile.Length - inFile.Position) > BufferSize); j++)
                                {
                                    read = outGZip.Read(buffer, 0, BufferSize);
                                       thread[j] = new Thread(() =>
                                       {
                                           lock (block)
                                           {
                                               Console.Write("- {0} -", j);
                                               outFile.Write(buffer, 0, read);
                                           }
                                       });
                                       thread[j].Start();
 
                                    //       thread[j].Join();
                                   }
                                   for (i = 0; i < j; i++)
                                   {
                                       thread[i].Join();
                                   }
                                }
                            outFile.Write(buffer, 0, outGZip.Read(buffer, 0, BufferSize));
                            outFile.Close();
                        }
                        outGZip.Close();
                    }
                    inFile.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message);
                error = true;
            }
        }
    }
    class FileModify
    {
         //public static long GZipLimit = 4294967296; // 4*2^30
         public static long GZipLimit = 30000000;
 
        public static void SplitFile(string infile,int count,bool pack)
        {
            int read;
            var extension = pack ? Path.GetExtension(infile):Path.GetExtension(infile.Remove(infile.Length - 3));
            var name = Path.GetFileNameWithoutExtension(infile);
            var directoryName = Path.GetDirectoryName(infile);
            byte[] buffer = new byte[GZipTest.BufferSize];
            int tail =Convert.ToInt32( GZipLimit % GZipTest.BufferSize);
            using (FileStream _from_stream = new FileStream(infile, FileMode.Open))
            {
                for (int i = 0; i < count+1; i++)
                {
                    string comp_string = !pack ? string.Format(directoryName + "boof1" + "_{0}" + extension+".gz", i) :
                             string.Format(directoryName + "boof1" + "_{0}"+extension, i);
                    using (FileStream _to_stream = new FileStream(comp_string, 
                                                                  FileMode.Create,FileAccess.Write))
                    {
                        Console.WriteLine("{0}й том для обработки создается...", i);
                        _from_stream.Position = i * GZipLimit;
                        while ((_to_stream.Length<GZipLimit)&&(_from_stream.Position<_from_stream.Length))
                        {
                            read = _from_stream.Read(buffer, 0, GZipTest.BufferSize);
                            if ((GZipLimit - _to_stream.Position < GZipTest.BufferSize)&&(i!=count))
                            {
                                read = _from_stream.Read(buffer, 0, tail);
                            }
                            _to_stream.Write(buffer, 0, read);
                        }
                        _to_stream.Close();
                    }
                }
                _from_stream.Close();
            }          
        }
        public static void MergeFile(string infile,int count,bool pack)
        {
            int read;
            var extension = Path.GetExtension(infile.Remove(infile.Length - 3));
            var name = Path.GetFileNameWithoutExtension(infile);
            var directoryName = Path.GetDirectoryName(infile);
            byte[] buffer = new byte[GZipTest.BufferSize];
            using (FileStream _to_stream = new FileStream(infile, FileMode.Append,FileAccess.Write))
            {
                for (int i = 0; i < count+1; i++)
                {
                    Console.WriteLine(extension);
                    string comp_string = pack ? string.Format(directoryName + "boof1" + "_{0}" + extension, i) : 
                                                 string.Format(directoryName + "boof1" + "_{0}"+extension+".gz", i); 
 
                    using (FileStream _from_stream = new FileStream(comp_string,
                                                                  FileMode.Open, FileAccess.Read))
                    {
                        //_from_stream.Position = i * GZipLimit;
                     //   _to_stream.Position = i * GZipLimit;
                        while (((read = _from_stream.Read(buffer, 0, GZipTest.BufferSize)) != 0))
                        {
                            _to_stream.Write(buffer, 0, read);
                        }
                        _from_stream.Close();
                    }
                    Console.WriteLine("{0}й том соединен.", i);
                }
                 _to_stream.Close();
            }
        }      
    }
 
    class FileProcess
    {
        static public void FileCompress(string infileName, string outfileName)
        {
            FileStream infile = new FileStream(infileName, FileMode.Open, FileAccess.Read);
            var extension = Path.GetExtension(infileName);
            var name = Path.GetFileNameWithoutExtension(infileName);
            var directoryName = Path.GetDirectoryName(infileName);
            int count = Convert.ToInt32(infile.Length / FileModify.GZipLimit);
            long length = infile.Length;
            infile.Close();
            if (length > FileModify.GZipLimit)
            {
                FileModify.SplitFile(infileName,count,true);
                for (int i = 0; i < count + 1; i++)
                {
                    string inFrag = string.Format(directoryName + "boof1" + "_{0}"+extension, i);
                    GZipTest.Compress(inFrag, inFrag + ".gz");
                }
                FileModify.MergeFile(outfileName,count, true);
            }
            else
            {
                GZipTest.Compress(infileName, outfileName);
            }
        }
        static public void FileDecompress(string infileName, string outfileName)
        {
            FileStream infile = new FileStream(infileName, FileMode.Open, FileAccess.Read);
            var extension = Path.GetExtension(infileName.Remove(infileName.Length - 3));
            var directoryName = Path.GetDirectoryName(infileName);
            int count = Convert.ToInt32(infile.Length / FileModify.GZipLimit);
            long length = infile.Length;
            infile.Close();
            if (length > FileModify.GZipLimit)
            {
                FileModify.SplitFile(infileName,count,false);
                for (int i = 0; i < count + 1; i++)
                {
                    string outFrag = string.Format(directoryName + "boof1" + "_{0}"+extension, i);
                    GZipTest.Decompress(outFrag+".gz", outFrag);
                }
                FileModify.MergeFile(outfileName,count,false);
            }
            else
            {
                GZipTest.Decompress(infileName, outfileName);
            }
 
        }
        class Program
        {
            static string GZip, fIN, fOUT;
            static bool flag = true;
            public static void Main(string[] args)//параметры для командной строки должны быть закомментированы для отладки!!!!
            {
                DateTime dold = DateTime.Now;
                /*        try
                        {
                            GZip = args[0]; //во время работы с консолью  раскомментировать GZip, fIN, fOUT!!!!
                            fIN = args[1];
                            fOUT = args[2];
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("ERROR: " + ex.Message+"|| Неверно введены параметры.");
                            GZipTest.error = true;
                        }*/
 
                try
                {
                    Console.CancelKeyPress += delegate //ловим ctrl+c
                    {
                        GC.Collect(); //чистим мусор
                       flag = false;
                    };
                    while ((true) & (flag))
                    {
                        GZip = "decompress";
                        fOUT = string.Format("d:/test_decomp_3.avi");
                        fIN = string.Format("d:/test_decomp_merge_3.avi.gz");
                        if (GZip == "compress")
                        {
                            Console.WriteLine("packing: ");
                            //  GZipTest.Compress(fIN, fOUT);
                            FileProcess.FileCompress(fIN, fOUT);
                        }
                        else if (GZip == "decompress")
                        {
                            Console.WriteLine("unpacking: ");
                            FileProcess.FileDecompress(fIN, fOUT);
                           //  GZipTest.Decompress(fIN, fOUT);
                        }
                        flag = false;
                        GC.Collect(); //чистим мусор
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("ERROR: " + ex.Message);
                    GZipTest.error = true;
                }
                //    FileModify.SplitFile("d:/test_decomp_3.avi");
                //   FileModify.MergeFile("d:/test_merge_2.avi.gz");
                TimeSpan sp = DateTime.Now - dold;
                Console.WriteLine("press Enter to terminate! CODE {0}", GZipTest.error ? "1" : "0");
                Console.WriteLine("completed in {0} secs", sp);
                Console.ReadLine();
            }
 
        }
     
    }
}
Добавлено через 11 минут
Проблемы начинаются на строке 152, когда пытаюсь разделенные куски архива распаковать в новый файл.
Помимо непонятного размера архива, вылезает и ошибка магического числа
0
Storm23
Эксперт .NETАвтор FAQ
9292 / 4512 / 1636
Регистрация: 11.01.2015
Сообщений: 5,731
Записей в блоге: 34
27.04.2016, 17:41 4
Цитата Сообщение от Lerikorner Посмотреть сообщение
C#
1
2
3
4
5
6
7
8
thread[j] = new Thread(()=>
  {
    //lock(block)
    Console.Write("- {0} -", j);
    // * *read = inFile.Read(buffer, 0, BufferSize);
    inGZip.Write(buffer, 0, read);
  }); 
thread[j].Start();
Как вы лихо пишите в один стрим из разных потоков. Аж загляденье.
Представьте что десяти ученикам дали одну тетрадку и поручили писать в этой тетрадке сочинение. Всем десятерым. Одновременно. Представляете что будет в этой тетрадке? Вот примерно тоже творится и вашем стриме.
Если вы хотели сделать паралельное зипование нескольких фрагментов файла, то для каждого потока нужно создавать свой GZipStrem, а затем, когда все потоки завершат сжатие - нужно аккуратно записать все сжатые куски в один файл.
0
Lerikorner
0 / 0 / 1
Регистрация: 27.03.2016
Сообщений: 41
27.04.2016, 20:52  [ТС] 5
Добавлено через 39 секунд
Цитата Сообщение от Storm23 Посмотреть сообщение
Как вы лихо пишите в один стрим из разных потоков. Аж загляденье.
Нет, с этим проблем нет никаких, упаковка-распаковка этой части проходит нормально, информация не теряется, так как у каждого GZip действительно свой поток с индексом j.
Помимо такого дробления, нужно еще рубить и весь файл, так как файлы для обработки 32GB, а в 3.5 есть ограничение 4GB.
Так вот. при упаковке фрагменты некоторого размер.а большого файла соединяются и в принципе архив рабочий.
В случае распаковки (при рассечении таким же методом), распаковывается только первый фрагмент, остальные выдают ошибку Магического числа. Значит, неправильно как-то режу при распаковке...

Добавлено через 3 часа 3 минуты
В общем, кажется, решение есть - нужно вместе с архивом создать List или массив с элементами long, которые будут последовательными точками входа в тома архива при распаковке, для того чтобы попадать в магические числа. а массив этот прилепить в конец архива, и при распаковке извлекать.
0
27.04.2016, 20:52
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.04.2016, 20:52

GZipStream - параллельная распаковка файла большого размера
Всем привет! Проблема отображена в названии темы. С сжатием всё понятно: читаем кусочки файлов...

Странная ошибка при сжатии файла в GZipStream
В процессе разработки проекта возникла странная ошибка при сжатии файла. class ZipStrings {...

Теряется расширение файла при его архивации GZipStream-ом
Добрый день. Написал следующий код для архивации текстового файла. static string path =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.