yyl
33 分钟以前 a84c7d64980873ce50f9f5beb18f790a4b79045a
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
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
#if !(UNITY_IOS || UNITY_IPHONE)
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
 
 
#if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1) && !UNITY_EDITOR
 using File = UnityEngine.Windows.File;
#else
using File = System.IO.File;
#endif
 
#if NETFX_CORE
#if UNITY_WSA_10_0
        using System.IO.IsolatedStorage;
        using static System.IO.Directory;
        using static System.IO.File;
        using static System.IO.FileStream;
#endif
#endif
 
 
public class lzma
{
 
    //if you want to be able to call the functions: get7zinfo, get7zSize, decode2Buffer from a thread set this string before to the Application.persistentDataPath !
    public static string persitentDataPath = "";
 
#if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR
 
    internal static int[] props = new int[7];
    internal static bool defaultsSet = false;
 
    //0 = level, /* 0 <= level <= 9, default = 5 */
    //1 = dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
    //2 = lc, /* 0 <= lc <= 8, default = 3  */
    //3 = lp, /* 0 <= lp <= 4, default = 0  */
    //4 = pb, /* 0 <= pb <= 4, default = 2  */
    //5 = fb,  /* 5 <= fb <= 273, default = 32 */
    //6 = numThreads /* 1 or 2, default = 2 */
 
    //A function that sets the compression properties for the lzma compressor. Will affect the lzma alone file and the lzma buffer compression.
    //A simple usage of this function is to call it only with the 1st parameter that sets the compression level: setProps(9);
    //
    //Multithread safe advice: call this function before starting any thread operations !!!
    public static void setProps(int level = 5, int dictSize = 16777216, int lc = 3, int lp = 0, int pb = 2, int fb = 32, int numThreads = 2)
    {
        defaultsSet = true;
        props[0] = level;
        props[1] = dictSize;
        props[2] = lc;
        props[3] = lp;
        props[4] = pb;
        props[5] = fb;
        props[6] = numThreads;
    }
#endif
 
 
#if (UNITY_WEBGL) && !UNITY_EDITOR
 
#if (!UNITY_WEBGL)
            [DllImport("__Internal")]
            public static extern int lsetPermissions(string filePath, string _user, string _group, string _other);
            [DllImport("__Internal")]
            private static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths,  string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
#endif
 
        [DllImport("__Internal")]
        private static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("__Internal")]
        private static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("__Internal")]
        internal static extern int lzmaUtil(bool encode, string inPath, string outPath, IntPtr Props);
        [DllImport("__Internal")]
        internal static extern int decode2Buf(string filePath, string entry,  IntPtr buffer, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("__Internal")]
        internal static extern void _releaseBuffer(IntPtr buffer);    
        [DllImport("__Internal")]
        internal static extern IntPtr Lzma_Compress( IntPtr buffer, int bufferLength, bool makeHeader, ref int v, IntPtr Props);
        [DllImport("__Internal")]
        internal static extern int Lzma_Uncompress( IntPtr buffer, int bufferLength, int uncompressedSize,  IntPtr outbuffer,bool useHeader);
#endif
 
#if UNITY_5_4_OR_NEWER
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX) && (!UNITY_EDITOR || UNITY_EDITOR_LINUX)
        private const string libname = "lzma";
#elif UNITY_EDITOR || UNITY_STANDALONE_WIN 
    private const string libname = "liblzma";
#endif
#else
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX) && !UNITY_EDITOR
        private const string libname = "lzma";
#endif
#if UNITY_EDITOR || UNITY_STANDALONE_WIN 
        private const string libname = "liblzma";
#endif
#endif
 
#if UNITY_EDITOR || UNITY_STANDALONE_WIN ||  UNITY_ANDROID || UNITY_STANDALONE_LINUX
#if ( UNITY_STANDALONE_LINUX || UNITY_ANDROID ||  UNITY_EDITOR_LINUX) && !UNITY_EDITOR_WIN
            //set permissions of a file in user, group, other. Each string should contain any or all chars of "rwx".
            //returns 0 on success
            [DllImport(libname, EntryPoint = "lsetPermissions")]
            internal static extern int lsetPermissions(string filePath, string _user, string _group, string _other);
#endif
    [DllImport(libname, EntryPoint = "decompress7zip")]
    internal static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "decompress7zip2")]
    internal static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "_getSize")]
    internal static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "lzmaUtil")]
    internal static extern int lzmaUtil(bool encode, string inPath, string outPath, IntPtr Props);
    [DllImport(libname, EntryPoint = "decode2Buf")]
    internal static extern int decode2Buf(string filePath, string entry, IntPtr buffer, IntPtr FileBuffer, int FileBufferLength);
    [DllImport(libname, EntryPoint = "_releaseBuffer")]
    internal static extern void _releaseBuffer(IntPtr buffer);
    [DllImport(libname, EntryPoint = "Lzma_Compress")]
    internal static extern IntPtr Lzma_Compress(IntPtr buffer, int bufferLength, bool makeHeader, ref int v, IntPtr Props);
    [DllImport(libname, EntryPoint = "Lzma_Uncompress")]
    internal static extern int Lzma_Uncompress(IntPtr buffer, int bufferLength, int uncompressedSize, IntPtr outbuffer, bool useHeader);
#endif
 
#if (UNITY_WP_8_1 || UNITY_WSA) && !UNITY_EDITOR
#if UNITY_WSA_10_0
            [DllImport("liblzma", EntryPoint = "decompress7zip")]
            internal static extern int decompress7zip(string filePath, string exctractionPath, bool fullPaths,  string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
#endif
        [DllImport("liblzma", EntryPoint = "decompress7zip2")]
        internal static extern int decompress7zip2(string filePath, string exctractionPath, bool fullPaths, string entry, IntPtr progress, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("liblzma", EntryPoint = "_getSize")]
        internal static extern int _getSize(string filePath, string tempPath, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("liblzma", EntryPoint = "decode2Buf")]
        internal static extern int decode2Buf(string filePath, string entry,  IntPtr buffer, IntPtr FileBuffer, int FileBufferLength);
        [DllImport("liblzma", EntryPoint = "Lzma_Uncompress")]
        internal static extern int Lzma_Uncompress( IntPtr buffer, int bufferLength, int uncompressedSize, IntPtr outbuffer,bool useHeader);
#endif
 
 
    // set permissions of a file in user, group, other.
    // Each string should contain any or all chars of "rwx".
    // returns 0 on success
    public static int setFilePermissions(string filePath, string _user, string _group, string _other)
    {
#if (UNITY_STANDALONE_LINUX || UNITY_ANDROID ||  UNITY_EDITOR_LINUX) && !UNITY_EDITOR_WIN
            return lsetPermissions(filePath, _user, _group, _other);
#else
        return -1;
#endif
    }
 
    // An integer variable to store the total number of files in a 7z archive, excluding the folders.
    public static int trueTotalFiles = 0;
 
    //ERROR CODES:
    //  1 : OK
    //    2 : Could not find requested file in archive
    // -1 : Could not open input(7z) file
    // -2 : Decoder doesn't support this archive
    // -3 : Can not allocate memory
    // -4 : CRC error of 7z file
    // -5 : Unknown error
    // -6 : Can not open output file (usually when the path to write to, is invalid)
    // -7 : Can not write output file
    // -8 : Can not close output file
 
    //The most common use of this library is to download a 7z file in your Application.persistentDataPath directory
    //and decompress it in a folder that you want.
 
    //int lz=lzma.doDecompress7zip(Application.persistentDataPath+"/myCompresedFile.7z",Application.persistentDataPath+"/myUncompressedFiles/");
 
    //WSA8.1 does not support large files.
 
    //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z)
    //exctractionPath    : the path in where you want your files to be extracted
    //progress          : a single item integer array to get the progress of the extracted files (use this function when calling from a separate thread, otherwise call the 2nd implementation)
    //                  : (for ios this integer is not properly updated. So we use the lzma.getProgressCount() function to get the progress. See example.)
    //largeFiles        : set this to true if you are extracting files larger then 30-40 Mb. It is slower though but prevents crashing your app when extracting large files!
    //fullPaths            : set this to true if you want to keep the folder structure of the 7z file.
    //entry                : set the name of a single file file you want to extract from your archive. If the file resides in a folder, the full path should be added.
    //                       (for example  game/meshes/small/table.mesh )
    //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will decompress from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    //use this function from a separate thread to get the progress  of the extracted files in the referenced 'progress' integer.
    //
    public static int doDecompress7zip(string filePath, string exctractionPath, int[] progress, bool largeFiles = false, bool fullPaths = false, string entry = null, byte[] FileBuffer = null)
    {
 
        int res = 0;
        GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned);
 
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
 
        if(FileBuffer != null) {
            GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
            
                
            if (largeFiles){
                res = decompress7zip(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }else{
                res =  decompress7zip2(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }
                fbuf.Free(); ibuf.Free(); return res;
        } else {
            if (largeFiles){
                res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }else{
                res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject() , IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }
        }
        
#endif
 
#if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_STANDALONE_LINUX && !UNITY_ANDROID) || UNITY_EDITOR_WIN || UNITY_WSA_10_0
        if (largeFiles)
        {
            res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
        else
        {
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
#endif
 
#if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 || UNITY_WEBGL) && !UNITY_EDITOR
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
#endif
    }
 
    //same as above only the progress integer is a local variable.
    //use this when you don't want to get the progress of the extracted files and when not calling the function from a separate thread.
    public static int doDecompress7zip(string filePath, string exctractionPath, bool largeFiles = false, bool fullPaths = false, string entry = null, byte[] FileBuffer = null)
    {
        //make a check if the last '/' exists at the end of the exctractionPath and add it if it is missing
        if (@exctractionPath.Substring(@exctractionPath.Length - 1, 1) != "/") { @exctractionPath += "/"; }
 
        int[] progress = new int[1];
        GCHandle ibuf = GCHandle.Alloc(progress, GCHandleType.Pinned);
        int res = 0;
 
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
        if(FileBuffer != null) {
            GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
            
            
            if (largeFiles){
                res = decompress7zip(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }else{
                res = decompress7zip2(null, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length);
            }
                fbuf.Free(); ibuf.Free(); return res;
        } else {
            if (largeFiles){
                res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }else{
                res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
                ibuf.Free(); return res;
            }
        }
#endif
 
#if (!UNITY_WSA && !UNITY_WEBGL && !UNITY_STANDALONE_LINUX && !UNITY_ANDROID) || UNITY_EDITOR_WIN || UNITY_WSA_10_0
        if (largeFiles)
        {
            res = decompress7zip(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
        else
        {
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
        }
#endif
 
#if (UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1 || UNITY_WEBGL) && !UNITY_EDITOR
            res = decompress7zip2(@filePath, @exctractionPath, fullPaths, entry, ibuf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            ibuf.Free(); return res;
#endif
    }
 
 
#if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR
    //ERROR CODES (for both encode/decode LzmaUtil functions):
    //   1 : OK
    // -10 : Can not read input file
    // -11 : Can not write output file
    // -12 : Can not allocate memory
    // -13 : Data error
 
    //This function encodes a single archive in lzma alone format.
    //inPath    : the file to be encoded. (use full path + file name)
    //outPath    : the .lzma file that will be produced. (use full path + file name)
    //
    //You can set the compression properties by calling the setProps function before.
    //setProps(9) for example will set compression evel to highest level.
    public static int LzmaUtilEncode(string inPath, string outPath)
    {
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        int res = lzmaUtil(true, @inPath, @outPath, prps.AddrOfPinnedObject());
        prps.Free();
        return res;
    }
 
 
    //This function decodes a single archive in lzma alone format.
    //inPath    : the .lzma file that will be decoded. (use full path + file name)
    //outPath    : the decoded file. (use full path + file name)
    public static int LzmaUtilDecode(string inPath, string outPath)
    {
        return lzmaUtil(false, @inPath, @outPath, IntPtr.Zero);
    }
 
#endif
 
    //Lists get filled with filenames (including path if the file is in a folder) and uncompressed file sizes
    public static List<string> ninfo = new List<string>();//filenames
    public static List<long> sinfo = new List<long>();//file sizes
 
    //this function fills the ArrayLists with the filenames and file sizes that are in the 7zip file
    //returns            : the total size in bytes of the files in the 7z archive 
    //
    //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z)
    //tempPath            : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used)
    //                    : this is useful when your 7z archive resides in a read only location.
    //                    : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename.
    //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    //
    //trueTotalFiles is an integer variable to store the total number of files in a 7z archive, excluding the folders.
    public static long get7zInfo(string filePath, string tempPath = null, byte[] FileBuffer = null)
    {
 
        ninfo.Clear(); sinfo.Clear();
        trueTotalFiles = 0;
        int res = -1;
        string logPath = "";
 
#if !NETFX_CORE
        if (@tempPath == null)
        {
            if (persitentDataPath.Length > 0) logPath = @persitentDataPath + "/sevenZip.log"; else logPath = @Application.persistentDataPath + "/sevenZip.log";
        }
        else { logPath = @tempPath; }
#endif
        //for WSA, logPath should always be: Application.persistentDataPath + "/sevenZip.log"; 
#if NETFX_CORE
#if UNITY_WSA_10_0
                if(persitentDataPath.Length>0) logPath = @persitentDataPath + "/sevenZip.log"; else  logPath = @Application.persistentDataPath + "/sevenZip.log";
#endif
#if UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1
                if(persitentDataPath.Length>0) logPath = @persitentDataPath + "/sevenZip.log"; else  logPath = @UnityEngine.Windows.Directory.localFolder + "/sevenZip.log";
#endif
#endif
 
        if (File.Exists(logPath + ".txt")) File.Delete(logPath + ".txt");
 
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
          if(FileBuffer != null) {
                GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
                res = _getSize(null, logPath,  fbuf.AddrOfPinnedObject(), FileBuffer.Length);
                fbuf.Free();
            }else {
                res = _getSize(@filePath, logPath,  IntPtr.Zero, 0);
            }
#else
        res = _getSize(@filePath, logPath, IntPtr.Zero, 0);
#endif
 
        if (res == -1) { /*Debug.Log("Input file not found.");*/ return -1; }
 
        if (!File.Exists(logPath + ".txt")) {/* Debug.Log("Info file not found.");*/ return -3; }
 
#if !NETFX_CORE
        StreamReader r = new StreamReader(logPath + ".txt");
#endif
#if NETFX_CORE
#if UNITY_WSA_10_0
            IsolatedStorageFile ipath = IsolatedStorageFile.GetUserStoreForApplication();
            StreamReader r = new StreamReader(new IsolatedStorageFileStream("sevenZip.log.txt", FileMode.Open, ipath));
#endif
#if UNITY_WSA_8_1 || UNITY_WP_8_1 || UNITY_WINRT_8_1
            var data = UnityEngine.Windows.File.ReadAllBytes(logPath + ".txt");
            string ss = System.Text.Encoding.UTF8.GetString(data,0,data.Length);
            StringReader r = new StringReader(ss);
#endif
#endif
 
        string line;
        string[] rtt;
        long t = 0, sum = 0;
 
        while ((line = r.ReadLine()) != null)
        {
            rtt = line.Split('|');
            ninfo.Add(rtt[0]);
            long.TryParse(rtt[1], out t);
            sum += t;
            sinfo.Add(t);
            if (t > 0) trueTotalFiles++;
        }
 
#if !NETFX_CORE
        r.Close();
#endif
        r.Dispose();
        File.Delete(logPath + ".txt");
 
        return sum;
    }
 
 
    //this function returns the uncompressed file size of a given file in the 7z archive if specified,
    //otherwise it will return the total uncompressed size of all the files in the archive.
    //
    //If you don't fill the filePath parameter it will assume that the get7zInfo function has already been called.
    //
    //
    //filePath            : the full path to the archive, including the archives name. (/myPath/myArchive.7z)
    //                     : if you call the function with filePath as null, it will try to find file sizes from the last call.
    //fileName             : the file name we want to get the file size (if it resides in a folder add the folder path also)
    //tempPath            : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used)
    //                    : this is useful when your 7z archive resides in a read only location.
    //                    : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename.
    //FileBuffer        : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    public static long get7zSize(string filePath = null, string fileName = null, string tempPath = null, byte[] FileBuffer = null)
    {
 
        if (filePath != null)
        {
            if (get7zInfo(@filePath, @tempPath, FileBuffer) < 0) { return -1; }
        }
 
        if (ninfo == null)
        {
            if (ninfo.Count == 0) { return -1; }
        }
 
        long sum = 0;
 
        if (fileName != null)
        {
            for (int i = 0; i < ninfo.Count; i++)
            {
                if (ninfo[i].ToString() == fileName)
                {
                    return (long)sinfo[i];
                }
            }
        }
        else
        {
            for (int i = 0; i < ninfo.Count; i++)
            {
                sum += (long)sinfo[i];
            }
            return sum;
        }
        return -1;//nothing was found
    }
 
 
 
    //A function to decode a specific archive in a 7z archive to a byte buffer
    //
    //filePath        : the full path to the 7z archive 
    //entry            : the file name to decode to a buffer. If the file resides in a folder, the full path should be used.
    //tempPath        : (optional) a temp path that will be used to write the files info (otherwise the path of the 7z archive will be used)
    //                : this is useful when your 7z archive resides in a read only location.
    //                : the tempPath should be in this form: 'dir/dir/myTempLog' with no slash in the end. The last name will be used as the log's filename.
    //FileBuffer    : A buffer that holds a 7zip file. When assigned the function will read from this buffer and will ignore the filePath. (Linux, iOS, Android, MacOSX)
    public static byte[] decode2Buffer(string filePath, string entry, string tempPath = null, byte[] FileBuffer = null)
    {
        int bufs = (int)get7zSize(@filePath, entry, @tempPath, FileBuffer);
        if (bufs <= 0) return null;//entry error or it does not exist
        byte[] nb = new byte[bufs];
        int res = 0;
 
        GCHandle dec2buf = GCHandle.Alloc(nb, GCHandleType.Pinned);
 
#if (UNITY_ANDROID || UNITY_STANDALONE_LINUX || UNITY_EDITOR) && !UNITY_EDITOR_WIN
          if(FileBuffer != null) {
                GCHandle fbuf = GCHandle.Alloc(FileBuffer, GCHandleType.Pinned);
                res = decode2Buf(null, entry, dec2buf.AddrOfPinnedObject(), fbuf.AddrOfPinnedObject(), FileBuffer.Length);
                fbuf.Free();
            }else {
                res = decode2Buf(@filePath, entry, dec2buf.AddrOfPinnedObject(), IntPtr.Zero, 0);
            }
#else
        res = decode2Buf(@filePath, entry, dec2buf.AddrOfPinnedObject(), IntPtr.Zero, 0);
#endif
 
        dec2buf.Free();
        if (res == 1) { return nb; }
        else { nb = null; return null; }
 
    }
 
#if !(UNITY_WSA || UNITY_WP_8_1) || UNITY_EDITOR
 
    //This function encodes inBuffer to lzma alone format into the outBuffer provided.
    //The buffer can be saved also into a file and can be opened by applications that opens the lzma alone format.
    //This buffer can be uncompressed by the decompressBuffer function.
    //Returns true if success
    //if makeHeader==false then the lzma 13 bytes header will not be added to the buffer.
    //
    //You can set the compression properties by calling the setProps function before.
    //setProps(9) for example will set compression level to the highest level.
    //
    public static bool compressBuffer(byte[] inBuffer, ref byte[] outBuffer, bool makeHeader = true)
    {
 
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
 
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptr;
 
        int res = 0;
 
        ptr = Lzma_Compress(cbuf.AddrOfPinnedObject(), inBuffer.Length, makeHeader, ref res, prps.AddrOfPinnedObject());
 
        cbuf.Free(); prps.Free();
 
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return false; }
 
        Array.Resize(ref outBuffer, res);
        Marshal.Copy(ptr, outBuffer, 0, res);
 
        _releaseBuffer(ptr);
 
        return true;
    }
 
 
    //same as the above function, only it compresses a part of the input buffer.
    //
    //inBufferPartialLength: the size of the input buffer that should be compressed
    //inBufferPartialIndex:  the offset of the input buffer from where the compression will start
    //
    public static bool compressBufferPartial(byte[] inBuffer, int inBufferPartialIndex, int inBufferPartialLength, ref byte[] outBuffer, bool makeHeader = true)
    {
        if (inBufferPartialIndex + inBufferPartialLength > inBuffer.Length) return false;
 
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
 
        IntPtr ptr;
        IntPtr ptrPartial;
 
        int res = 0;
 
        ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + inBufferPartialIndex);
 
        ptr = Lzma_Compress(ptrPartial, inBufferPartialLength, makeHeader, ref res, prps.AddrOfPinnedObject());
 
        cbuf.Free();
 
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return false; }
 
        Array.Resize(ref outBuffer, res);
        Marshal.Copy(ptr, outBuffer, 0, res);
 
        _releaseBuffer(ptr);
 
        return true;
    }
 
 
    //same as compressBufferPartial, only this function will compress the data into a fixed size buffer
    //the compressed size is returned so you can manipulate it at will.
    public static int compressBufferPartialFixed(byte[] inBuffer, int inBufferPartialIndex, int inBufferPartialLength, ref byte[] outBuffer, bool safe = true, bool makeHeader = true)
    {
        if (inBufferPartialIndex + inBufferPartialLength > inBuffer.Length) return 0;
 
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
 
        IntPtr ptr;
        IntPtr ptrPartial;
 
        int res = 0;
 
        ptrPartial = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + inBufferPartialIndex);
 
        ptr = Lzma_Compress(ptrPartial, inBufferPartialLength, makeHeader, ref res, prps.AddrOfPinnedObject());
 
        cbuf.Free();
 
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return 0; }
 
        //if the compressed buffer is larger then the fixed size buffer we use:
        //1. then write only the data that fit in it.
        //2. or we return 0. 
        //It depends on if we set the safe flag to true or not.
        if (res > outBuffer.Length)
        {
            if (safe) { _releaseBuffer(ptr); return 0; } else { res = outBuffer.Length; }
        }
 
        Marshal.Copy(ptr, outBuffer, 0, res);
 
        _releaseBuffer(ptr);
 
        return res;
    }
 
 
    //same as the compressBuffer function, only this function will put the result in a fixed size buffer to avoid memory allocations.
    //the compressed size is returned so you can manipulate it at will.
    public static int compressBufferFixed(byte[] inBuffer, ref byte[] outBuffer, bool safe = true, bool makeHeader = true)
    {
 
        if (!defaultsSet) setProps();
        GCHandle prps = GCHandle.Alloc(props, GCHandleType.Pinned);
 
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptr;
 
        int res = 0;
 
        ptr = Lzma_Compress(cbuf.AddrOfPinnedObject(), inBuffer.Length, makeHeader, ref res, prps.AddrOfPinnedObject());
 
        cbuf.Free(); prps.Free();
        if (res == 0 || ptr == IntPtr.Zero) { _releaseBuffer(ptr); return 0; }
 
        //if the compressed buffer is larger then the fixed size buffer we use:
        //1. then write only the data that fit in it.
        //2. or we return 0. 
        //It depends on if we set the safe flag to true or not.
        if (res > outBuffer.Length)
        {
            if (safe) { _releaseBuffer(ptr); return 0; } else { res = outBuffer.Length; }
        }
 
        Marshal.Copy(ptr, outBuffer, 0, res);
 
        _releaseBuffer(ptr);
 
        return res;
    }
 
#endif
 
 
 
 
 
    //This function will decompress a compressed asset bundle.
    //It finds the magic number of the lzma format and extracts from there.
    //
    //inBuffer:        the buffer that stores a compressed asset bundle.
    //outBuffer:    a referenced buffer where the asset bundle will be uncompressed.
    //The error codes
    /*
        OK 0
        
        ERROR_DATA 1
        ERROR_MEM 2
        ERROR_UNSUPPORTED 4
        ERROR_PARAM 5
        ERROR_INPUT_EOF 6
        ERROR_OUTPUT_EOF 7
        ERROR_FAIL 11
        ERROR_THREAD 12
    */
    public static int decompressAssetBundle(byte[] inBuffer, ref byte[] outbuffer)
    {
 
        int offset = 0;
 
        for (int i = 0; i < inBuffer.Length; i++)
        {
            if (i > 1024) break;
            if (inBuffer[i] == 0x5d)
            {
                if (inBuffer[i + 1] == 0x00)
                {
                    if (inBuffer[i + 2] == 0x00)
                    {
                        if (inBuffer[i + 3] == 0x08)
                        {
                            offset = i; break;
                        }
                    }
                }
            }
        }
 
        if (offset == 0 || offset > 1024) return 4;
 
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        IntPtr ptrBundle = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + offset);
        int uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, offset + 5);
        if (uncompressedSize < 0) { cbuf.Free(); return 4; }
        Array.Resize(ref outbuffer, uncompressedSize);
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
 
        int res = Lzma_Uncompress(ptrBundle, inBuffer.Length - offset, uncompressedSize, obuf.AddrOfPinnedObject(), true);
 
        cbuf.Free();
        obuf.Free();
 
        //if(res!=0){/*Debug.Log("ERROR: "+res.ToString());*/ return res; }
 
        return res;
    }
 
 
    /*
    //this will decompress an lzma alone format file.
    public static  int decompressLzmaAlone(string inFile,  string outFile){
 
        if(File.Exists(inFile)) {
            var inBuffer = File.ReadAllBytes(inFile);
 
            int offset = 0;
        
            for(int i=0; i<inBuffer.Length; i++) {
                if(i>16) break;
                if(inBuffer[i] == 0x5d) {
                    if(inBuffer[i+1] == 0x00) {
                        if(inBuffer[i+2] == 0x00) {
                            if(inBuffer[i+3] == 0x00) {
                                offset = i;  break; 
                            }
                        }
                    }
                }
            }
        
            if(offset>16) {  inBuffer=null; return 4; }
 
            GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
            IntPtr ptrBundle = new IntPtr(cbuf.AddrOfPinnedObject().ToInt64() + offset);
            int uncompressedSize = (int)BitConverter.ToUInt64(inBuffer,offset+5);
            if(uncompressedSize<0) { cbuf.Free(); return 4; }
            byte[] outBuffer = new byte[uncompressedSize];
            GCHandle obuf = GCHandle.Alloc(outBuffer, GCHandleType.Pinned);
        
            int res = Lzma_Uncompress(ptrBundle, inBuffer.Length-offset, uncompressedSize, obuf.AddrOfPinnedObject(), true);
 
            cbuf.Free();
            obuf.Free();
 
            File.WriteAllBytes(outFile, outBuffer);
 
            Array.Resize(ref outBuffer, 0);
            Array.Resize(ref inBuffer, 0);
 
            outBuffer = null;
            inBuffer = null;
 
            GC.Collect();
 
            return res;    
        } else {
            return -1;
        }    
    }
    */
 
 
    //This function decompresses an lzma compressed byte buffer.
    //If the useHeader flag is false you have to provide the uncompressed size of the buffer via the customLength integer.
    //if res==0 operation was successful
    //The error codes
    /*
        OK 0
        
        ERROR_DATA 1
        ERROR_MEM 2
        ERROR_UNSUPPORTED 4
        ERROR_PARAM 5
        ERROR_INPUT_EOF 6
        ERROR_OUTPUT_EOF 7
        ERROR_FAIL 11
        ERROR_THREAD 12
        */
    public static int decompressBuffer(byte[] inBuffer, ref byte[] outbuffer, bool useHeader = true, int customLength = 0)
    {
 
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        int uncompressedSize = 0;
 
        //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header 
        //provide the known uncompressed size through the customLength integer.
        if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength;
 
        Array.Resize(ref outbuffer, uncompressedSize);
 
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
 
        int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader);
 
        cbuf.Free();
        obuf.Free();
 
        //if(res!=0){/*Debug.Log("ERROR: "+res.ToString());*/ return res; }
 
        return res;
    }
 
    public static byte[] decompressBuffer(byte[] inBuffer, bool useHeader = true, int customLength = 0)
    {
 
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        int uncompressedSize = 0;
 
        //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header 
        //provide the known uncompressed size through the customLength integer.
        if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength;
 
        byte[] outbuffer = new byte[uncompressedSize];
 
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
 
        int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader);
 
        cbuf.Free();
        obuf.Free();
 
        if (res != 0) {/*Debug.Log("ERROR: "+res.ToString());*/ return null; }
 
        return outbuffer;
    }
 
 
    //same as above function. Only this one outputs to a buffer of fixed which size isn't resized to avoid memory allocations.
    //The fixed buffer should have a size that will be able to hold the incoming decompressed data.
    //returns the uncompressed size.
    public static int decompressBufferFixed(byte[] inBuffer, ref byte[] outbuffer, bool safe = true, bool useHeader = true, int customLength = 0)
    {
 
        int uncompressedSize = 0;
 
        //if the lzma header will be used to extract the uncompressed size of the buffer. If the buffer does not have a header 
        //provide the known uncompressed size through the customLength integer.
        if (useHeader) uncompressedSize = (int)BitConverter.ToUInt64(inBuffer, 5); else uncompressedSize = customLength;
 
        //Check if the uncompressed size is bigger then the size of the fixed buffer. Then:
        //1. write only the data that fit in it.
        //2. or return a negative number. 
        //It depends on if we set the safe flag to true or not.
        if (uncompressedSize > outbuffer.Length)
        {
            if (safe) return -101; else uncompressedSize = outbuffer.Length;
        }
 
        GCHandle cbuf = GCHandle.Alloc(inBuffer, GCHandleType.Pinned);
        GCHandle obuf = GCHandle.Alloc(outbuffer, GCHandleType.Pinned);
 
        int res = Lzma_Uncompress(cbuf.AddrOfPinnedObject(), inBuffer.Length, uncompressedSize, obuf.AddrOfPinnedObject(), useHeader);
 
        cbuf.Free();
        obuf.Free();
 
        if (res != 0) {/*Debug.Log("ERROR: "+res.ToString());*/ return -res; }
 
        return uncompressedSize;
    }
 
}
#endif