質問編集履歴

1

追記1

2020/11/25 01:56

投稿

BeatStar
BeatStar

スコア4958

test CHANGED
File without changes
test CHANGED
@@ -38,463 +38,11 @@
38
38
 
39
39
 
40
40
 
41
- ```C++
42
-
43
- // インクルードされているとして
41
+ [コード](https://pastebin.com/JMnjS4iH)
44
42
 
45
43
 
46
44
 
47
- using namespace std;
48
-
49
-
50
-
51
- namespace Test1{
52
-
53
- using SingnaturesQueue = std::queue<char>;
54
-
55
- using UCharQueue = std::queue<unsigned char>;
56
-
57
- using UCharStack = std::stack<unsigned char>;
58
-
59
- }
60
-
61
-
62
-
63
- namespace Test1{
64
-
65
- unsigned long convertHexStringToULong( const std::string &str ){
66
-
67
- char* endptr;
68
-
69
- unsigned res = strtoul( str.c_str(), &endptr, 16 );
70
-
71
- return res;
72
-
73
- }
74
-
75
- }
76
-
77
-
78
-
79
- namespace Test1{
80
-
81
- std::string convertUCharToHexString( unsigned char val ){
82
-
83
- stringstream ss;
84
-
85
- ss << std::hex << static_cast<unsigned int>(val);
86
-
87
- return ss.str();
88
-
89
- }
90
-
91
- }
92
-
93
-
94
-
95
- namespace Test1{
96
-
97
- class ICompressedItem{
98
-
99
- public:
100
-
101
- using TYPE = unsigned char;
102
-
103
- public:
104
-
105
- virtual ~ICompressedItem(){}
106
-
107
- virtual std::string filename( void ) const = 0;
108
-
109
- virtual std::list<ICompressedItem::TYPE> fileEntry( void ) const = 0;
110
-
111
- };
112
-
113
- using CompressedItemList = std::list<ICompressedItem*>;
114
-
115
- }
116
-
117
-
118
-
119
- namespace Test1{
120
-
121
- class IReader{
122
-
123
- public:
124
-
125
- virtual ~IReader(){}
126
-
127
- virtual Test1::CompressedItemList read( void ) = 0;
128
-
129
- };
130
-
131
- }
132
-
133
-
134
-
135
- namespace Test1::ZipFiles{
136
-
137
- class CompressedItem : public Test1::ICompressedItem{
138
-
139
- public:
140
-
141
- CompressedItem( const Test1::UCharQueue &all ) : all_(all){
142
-
143
- int versionNeeded2Extract = CompressedItem::extractIntDecimal( 2 );
144
-
145
- cout << "version needed to extract = " << versionNeeded2Extract << endl;
146
-
147
- int generalPurposeBitFlag = CompressedItem::extractIntDecimal( 2 );
148
-
149
- int compressionMethod = CompressedItem::extractIntDecimal( 2 );
150
-
151
- cout << "compressionMethod = " << compressionMethod << endl;
152
-
153
- int lastModFileTime = CompressedItem::extractIntDecimal( 2 );
154
-
155
- int lastModeFileDate = CompressedItem::extractIntDecimal( 2 );
156
-
157
- int crc_32 = CompressedItem::extractIntDecimal( 4 );
158
-
159
- int compressedSize = CompressedItem::extractIntDecimal( 4 );
160
-
161
- int uncompressedSize = CompressedItem::extractIntDecimal( 4 );
162
-
163
- int fileNameLength = CompressedItem::extractULongDecimal( 2 );
164
-
165
- int extraFieldLength = CompressedItem::extractIntDecimal( 2 );
166
-
167
-
168
-
169
- {
170
-
171
- for( int i = 0; i < fileNameLength; i++ ){
172
-
173
- filename_ += static_cast<char>(all_.front());
174
-
175
- all_.pop();
176
-
177
- }
178
-
179
- }
180
-
181
-
182
-
183
- for( int i = 0; i < extraFieldLength; i++ ) all_.pop();
184
-
185
-
186
-
187
- {
188
-
189
- Test1::UCharStack cs;
190
-
191
- while( !all_.empty() ){
192
-
193
- ICompressedItem::TYPE uc = all_.front();
194
-
195
- all_.pop();
196
-
197
- cs.push( uc );
198
-
199
- }
200
-
201
- while( !cs.empty() ){
202
-
203
- ICompressedItem::TYPE uc = cs.top();
204
-
205
- cs.pop();
206
-
207
- fileEntry_.push_back( uc );
208
-
209
- }
210
-
211
- }
212
-
213
- // 前に余計なシグネチャ(3バイト分)が付いているため、そぎ落とす
214
-
215
- for( int i = 0; i < 3; i++ ) fileEntry_.pop_front();
216
-
217
- }
218
-
219
- ~CompressedItem(){}
220
-
221
-
222
-
223
- std::string filename( void ) const{ return filename_; }
224
-
225
- std::list<ICompressedItem::TYPE> fileEntry( void ) const{ return fileEntry_; }
226
-
227
- protected:
228
-
229
- int extractIntDecimal( int nbytes ){
230
-
231
- Test1::UCharStack cs;
232
-
233
- // データをnbytes分取り出す
234
-
235
- for( int i = 0; i < nbytes; i++ ){
236
-
237
- unsigned char c = all_.front();
238
-
239
- all_.pop();
240
-
241
- cs.push( c );
242
-
243
- }
244
-
245
-
246
-
247
- // 16進数に変換
248
-
249
- std::string ss = "";
250
-
251
- while( !cs.empty() ){
252
-
253
- unsigned char t = cs.top();
254
-
255
- cs.pop();
256
-
257
- ss += Test1::convertUCharToHexString( static_cast<unsigned char>(t) );
258
-
259
- }
260
-
261
- // 10進数の整数に変換
262
-
263
- unsigned long res = Test1::convertHexStringToULong( ss );
264
-
265
- return static_cast<int>(res);
266
-
267
- }
268
-
269
- protected:
270
-
271
- unsigned long extractULongDecimal( int nbytes ){
272
-
273
- Test1::UCharStack cs;
274
-
275
- // データをnbytes分取り出す
276
-
277
- for( int i = 0; i < nbytes; i++ ){
278
-
279
- unsigned char c = all_.front();
280
-
281
- all_.pop();
282
-
283
- cs.push( c );
284
-
285
- }
286
-
287
-
288
-
289
- // 16進数に変換
290
-
291
- std::string ss = "";
292
-
293
- while( !cs.empty() ){
294
-
295
- unsigned char t = cs.top();
296
-
297
- cs.pop();
298
-
299
- ss += Test1::convertUCharToHexString( static_cast<unsigned char>(t) );
300
-
301
- }
302
-
303
- // 10進数の整数に変換
304
-
305
- return Test1::convertHexStringToULong( ss );
306
-
307
- }
308
-
309
- private:
310
-
311
- Test1::UCharQueue all_;
312
-
313
- private:
314
-
315
- std::string filename_;
316
-
317
- std::list<ICompressedItem::TYPE> fileEntry_;
318
-
319
- };
320
-
321
- }
322
-
323
-
324
-
325
- namespace Test1::ZipFiles{
326
-
327
- class Reader : public Test1::IReader{
328
-
329
- public:
330
-
331
- Reader( const std::string &compressedFilePath ) : file_(new Util::BinaryFileReader(compressedFilePath)),zipLocalHeaderSignature_(Reader::createZipLocalHeaderSignature()),centralDirectoryFileHeaderSignature_(Reader::createCentralDirectoryFileHeaderSignature()){
332
-
333
-
334
-
335
- }
336
-
337
- ~Reader(){ delete file_; }
338
-
339
- std::string filepath( void ) const{ return file_->filepath(); }
340
-
341
- bool isEnabled( void ) const{ return file_->isEnabled(); }
342
-
343
- virtual Test1::CompressedItemList read( void ){
344
-
345
- Test1::CompressedItemList items; // 結果を保持するリスト
346
-
347
- Test1::UCharQueue all; // 一時的に保持しておくキュー
348
-
349
- Test1::SingnaturesQueue signature; // シグネチャとして保存してチェックするためのもの
350
-
351
- // バイナリデータが存在している間
352
-
353
- while( !file_->isEof() ){
354
-
355
- // シグネチャは4バイトまで
356
-
357
- if( signature.size() >= 4 ) signature.pop();
358
-
359
-
360
-
361
- // ファイルから1バイト分読み込む
362
-
363
- char c[1];
364
-
365
- file_->read( c, 1, 1 );
366
-
367
-
368
-
369
- // 読み込んだデータを16進数としてシグネチャキューに突っ込む
370
-
371
- signature.push( c[0] );
372
-
373
-
374
-
375
- if( signature == zipLocalHeaderSignature_ ){ // ZIPローカルヘッダのシグネチャと一致する場合
376
-
377
- // allを itemsに追加
378
-
379
- if( !all.empty() ) items.push_back( new Test1::ZipFiles::CompressedItem( all ) );
380
-
381
- // all を破棄
382
-
383
- all = Test1::UCharQueue();
384
-
385
- }else if( signature == centralDirectoryFileHeaderSignature_ ){ // セントラルディレクトリファイルヘッダのシグネチャと一致する場合
386
-
387
- // allを itemsに追加
388
-
389
- if( !all.empty() ) items.push_back( new Test1::ZipFiles::CompressedItem( all ) );
390
-
391
- // これ以上はないのでbreak
392
-
393
- break;
394
-
395
- }else{ // それ以外はそのままallに追加
396
-
397
- all.push( c[0] );
398
-
399
- }
400
-
401
- }
402
-
403
- return items;
404
-
405
- }
406
-
407
- protected:
408
-
409
- Test1::SingnaturesQueue createZipLocalHeaderSignature( void );
410
-
411
- Test1::SingnaturesQueue createCentralDirectoryFileHeaderSignature( void );
412
-
413
- private:
414
-
415
- Util::BinaryFileReader* file_;
416
-
417
- Test1::SingnaturesQueue zipLocalHeaderSignature_;
418
-
419
- Test1::SingnaturesQueue centralDirectoryFileHeaderSignature_;
420
-
421
- };
422
-
423
- }
424
-
425
-
426
-
427
- int main( int argc, char* argv[] ){
428
-
429
- if( argc < 2 ){
430
-
431
- cout << "cmd: main FILE" << endl;
432
-
433
- return -1;
434
-
435
- }
436
-
437
-
438
-
439
- Test1::ZipFiles::Reader* reader = new Test1::ZipFiles::Reader( argv[1] );
440
-
441
- if( !reader->isEnabled() ){
442
-
443
- cout << "Cannnot read " << reader->filepath() << endl;
444
-
445
- return -2;
446
-
447
- }
448
-
449
-
450
-
451
- Test1::CompressedItemList itemList = reader->read();
452
-
453
-
454
-
455
- delete reader;
456
-
457
- cout << "size = " << itemList.size() << endl;
458
-
459
-
460
-
461
- Test1::CompressedItemList::iterator it = itemList.begin();
462
-
463
- {
464
-
465
- Util::BinaryFileWriter fileWriter( (*it)->filename() );
466
-
467
- if( !fileWriter.isEnabled() ){
468
-
469
- cout << "Cannot open " << fileWriter.filepath() << endl;
470
-
471
- return -2;
472
-
473
- }
474
-
475
-
476
-
477
- std::list<Test1::ICompressedItem::TYPE> file = (*it)->fileEntry();
478
-
479
- for( Test1::ICompressedItem::TYPE c : file ){
480
-
481
- fileWriter.write( &c, 1, 1 );
482
-
483
- }
484
-
485
- }
486
-
487
- return 0;
488
-
489
- }
490
-
491
- ```
492
-
493
- ※ 字数制限のため一部省略. Util::BinaryFileReaderはファイルの読み取りとする
494
-
495
-
496
-
497
- (コードの一部を変更しています)
45
+ 字数制限の為、別のサイトをお借りしています。
498
46
 
499
47
 
500
48
 
@@ -527,3 +75,91 @@
527
75
  言語: C++
528
76
 
529
77
  コンパイラ: MinGW (g++)
78
+
79
+
80
+
81
+ ---
82
+
83
+ [追記1]
84
+
85
+
86
+
87
+ 一応、SaitoAtsushiさんのおっしゃるように、zlibなるものをDLして実際に使ってみました。
88
+
89
+
90
+
91
+ 一旦、今回の私のコードとは別の実行ファイルとしてzlibを使ったプログラムを生成しておき、
92
+
93
+ 何らかの画像ファイルとそれをzipファイルにした圧縮ファイルのそれぞれを用意します。
94
+
95
+
96
+
97
+ ```ここに言語を入力
98
+
99
+ [準備0]
100
+
101
+ ■ zlibを使った解凍系プログラム (便宜上、zlibmain.exe とする)
102
+
103
+ ■ 今回の自分のプログラム (main.exe とする)
104
+
105
+ ■ 適当な画像ファイル (image1.jpgとする)
106
+
107
+ ■ image1.jpgをzipファイルにしたもの (arc1.zipとする)
108
+
109
+ ```
110
+
111
+
112
+
113
+ ※ zlibmain.exe のコードは [zlib 入門](https://oku.edu.mie-u.ac.jp/~okumura/compression/zlib.html) にある comptest2.c をそのまま流用。
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+ ```ここに言語を入力
122
+
123
+ [やったこと1]
124
+
125
+ 1. main.exeでarc1.zipからimage1.jpgをファイルとして取り出す
126
+
127
+  → そのファイルをcomp2.bin として生成しておく
128
+
129
+ 2. zlibmain.exe で image1.jpg を comp.bin として圧縮する( "c" オプションにて )
130
+
131
+ 2. comp.bin と comp2.bin を それぞれ、BzEditor なるバイナリエディタでダンプリストを生成
132
+
133
+ 3. (3)で生成されたダンプリストを二つ、比較してみる
134
+
135
+ ```
136
+
137
+
138
+
139
+ この"やったこと1" では、そもそもデータが合っていないようです。
140
+
141
+
142
+
143
+ 私が使った comp.bin では { ED, 02, 00, 00, 78, ... } となっていますが、
144
+
145
+ comp2.bin では { 01, FF, E0, F3, ... } のようになっています。
146
+
147
+
148
+
149
+ 逆さなのかなぁと思い、(comp2.binを)逆から読んでみても、該当するデータ列が見つかりません。
150
+
151
+ 単純に、ランダムに comp.bin にある { 00, 00 } をcomp2.bin から探し出して、
152
+
153
+ その周辺の16進数を比較しても同じデータになっていませんでした。
154
+
155
+
156
+
157
+ つまり、本来は同じファイルのデータを読んでいるはずなのに、別のデータ列になっているのです。
158
+
159
+
160
+
161
+ 私の組み方が悪いのでしょうか。
162
+
163
+
164
+
165
+ あまりバイナリファイルを扱わないため、混乱しています…。