1+ using System ;
2+ using System . Collections ;
3+ using System . Collections . Generic ;
4+ using System . IO ;
5+ using System . Linq ;
6+ using System . Text ;
7+ using UnityEngine ;
8+
9+ namespace ATRI . Collection
10+ {
11+ public class FileDB : IDisposable
12+ {
13+ #region member
14+ // fileOffset, subFileLen, subFile isCopyTo File
15+ private Dictionary < string , ValueTuple < int , int , bool , string > > tableInfo = new Dictionary < string , ( int , int , bool , string ) > ( ) ;
16+ private Dictionary < string , object > tableDict = new Dictionary < string , object > ( ) ;
17+ private FileStream _fs ;
18+ private string _path ;
19+ private bool _inited = false ;
20+ #endregion
21+
22+ public FileDB ( string filePath )
23+ {
24+ _path = filePath ;
25+ }
26+
27+ #region public
28+
29+ public bool TryGetValueByTableName < TKey , TValue > ( string tableName , TKey key , out TValue value ) where TKey : IEquatable < TKey >
30+ {
31+ Init ( ) ;
32+ object dict ;
33+ if ( ! tableDict . TryGetValue ( tableName , out dict ) )
34+ {
35+ ValueTuple < int , int , bool , string > info ;
36+ if ( tableInfo . TryGetValue ( tableName , out info ) )
37+ {
38+ // copy value to mergefile
39+ if ( ! info . Item3 )
40+ {
41+ var tempBuff = FileDictionaryUtils . moveTempBuff ;
42+ FileStream subFile = new FileStream ( info . Item4 , FileMode . Open , FileAccess . Read ) ;
43+ int bytesRead ;
44+ _fs . Seek ( info . Item1 , SeekOrigin . Begin ) ;
45+ while ( ( bytesRead = subFile . Read ( tempBuff , 0 , tempBuff . Length ) ) > 0 )
46+ {
47+ _fs . Write ( tempBuff , 0 , bytesRead ) ;
48+ }
49+ }
50+ SubFileStream subFileStream = new SubFileStream ( _fs , info . Item1 , info . Item2 ) ;
51+ dict = new FileDictionary < TKey , TValue > ( subFileStream ) ;
52+ tableInfo . Remove ( tableName ) ;
53+ tableDict . Add ( tableName , dict ) ;
54+ }
55+ else
56+ {
57+ Debug . LogError ( "tableInfo not init" ) ;
58+ value = default ( TValue ) ;
59+ return false ;
60+ }
61+ }
62+
63+ FileDictionary < TKey , TValue > fd = ( FileDictionary < TKey , TValue > ) dict ;
64+ return fd . TryGetValue ( key , out value ) ;
65+ }
66+
67+ public void Dispose ( )
68+ {
69+ if ( _fs != null )
70+ {
71+ _fs . Dispose ( ) ;
72+ }
73+ }
74+
75+ public void MergeRuntime ( params string [ ] paths )
76+ {
77+ if ( File . Exists ( _path ) )
78+ {
79+ File . Delete ( _path ) ;
80+ }
81+
82+ tableInfo . Clear ( ) ;
83+ _inited = false ;
84+
85+ int len = 0 ;
86+ foreach ( var filePath in paths )
87+ {
88+ FileInfo fi = new FileInfo ( filePath ) ;
89+ if ( ! fi . Exists )
90+ {
91+ throw new Exception ( filePath + " not exit! please check" ) ;
92+ }
93+ string fileName = Path . GetFileNameWithoutExtension ( filePath ) ;
94+ if ( tableInfo . ContainsKey ( fileName ) )
95+ {
96+ Debug . LogError ( fileName + " already exit!plz check in:[\n " + string . Concat ( paths , "\n " ) + "]" ) ;
97+ return ;
98+ }
99+
100+ tableInfo . Add ( fileName , ( len , ( int ) fi . Length , false , filePath ) ) ;
101+ len += ( int ) fi . Length ;
102+ }
103+ }
104+
105+ #if UNITY_EDITOR
106+ public void MergeEditor ( params string [ ] paths )
107+ {
108+ if ( File . Exists ( _path ) )
109+ {
110+ File . Delete ( _path ) ;
111+ }
112+
113+ tableInfo . Clear ( ) ;
114+ _inited = false ;
115+
116+ FileStream fs = new FileStream ( _path , FileMode . CreateNew , FileAccess . Write ) ;
117+ BinaryWriter bfw = new BinaryWriter ( fs ) ;
118+
119+ MemoryStream headMs = new MemoryStream ( ) ;
120+ BinaryWriter bw = new BinaryWriter ( headMs ) ;
121+
122+ int len = 0 ;
123+ bw . Write ( paths . Length ) ;
124+ Dictionary < string , string > closeSet = new Dictionary < string , string > ( ) ;
125+ foreach ( var filePath in paths )
126+ {
127+ FileInfo fi = new FileInfo ( filePath ) ;
128+ if ( ! fi . Exists )
129+ {
130+ throw new Exception ( filePath + "not eixt! please check" ) ;
131+ }
132+
133+ string fileName = Path . GetFileNameWithoutExtension ( filePath ) ;
134+ if ( closeSet . ContainsKey ( fileName ) )
135+ {
136+ throw new Exception ( filePath + "file name the same with path:" + closeSet [ fileName ] ) ;
137+ }
138+
139+ byte [ ] strData = UTF8Encoding . UTF8 . GetBytes ( fileName ) ;
140+ bw . Write ( strData . Length ) ;
141+ bw . Write ( strData ) ;
142+ bw . Write ( len ) ;
143+ bw . Write ( ( int ) fi . Length ) ;
144+
145+ len += ( int ) fi . Length ;
146+ }
147+
148+ int totalHeadLen = ( int ) headMs . Length ;
149+ bw . Flush ( ) ;
150+ bw . Close ( ) ;
151+
152+ bfw . Write ( totalHeadLen ) ;
153+ bfw . Write ( headMs . ToArray ( ) ) ;
154+
155+ var tempBuff = FileDictionaryUtils . moveTempBuff ;
156+
157+ foreach ( var filePath in paths )
158+ {
159+ int bytesRead ;
160+ FileStream subFile = new FileStream ( filePath , FileMode . Open , FileAccess . Read ) ;
161+ while ( ( bytesRead = subFile . Read ( tempBuff , 0 , tempBuff . Length ) ) > 0 )
162+ {
163+ fs . Write ( tempBuff , 0 , bytesRead ) ;
164+ }
165+ }
166+
167+ bfw . Flush ( ) ;
168+ bfw . Close ( ) ;
169+
170+ }
171+ #endif
172+
173+ #endregion
174+
175+ private void Init ( )
176+ {
177+ if ( _inited ) return ;
178+ _inited = true ;
179+
180+ // merge in runtime
181+ if ( tableInfo . Count <= 0 )
182+ {
183+ _fs = new FileStream ( _path , FileMode . OpenOrCreate , FileAccess . Read ) ;
184+ BinaryReader br = new BinaryReader ( _fs ) ;
185+ int totalHeadLen = br . ReadInt32 ( ) ;
186+ int fileLen = br . ReadInt32 ( ) ;
187+
188+ for ( int i = 0 ; i < fileLen ; i ++ )
189+ {
190+ int strLen = br . ReadInt32 ( ) ;
191+ byte [ ] datas = br . ReadBytes ( strLen ) ;
192+ string fileName = UTF8Encoding . UTF8 . GetString ( datas ) ;
193+ int offset = br . ReadInt32 ( ) ;
194+ int onefileLen = br . ReadInt32 ( ) ;
195+
196+ tableInfo . Add ( fileName , ( offset + totalHeadLen + 4 , onefileLen , true , "" ) ) ;
197+ }
198+ }
199+ else
200+ {
201+ _fs = new FileStream ( _path , FileMode . OpenOrCreate , FileAccess . ReadWrite ) ;
202+ }
203+ }
204+
205+ }
206+ }
0 commit comments