17
17
import java .nio .charset .Charset ;
18
18
import java .util .ArrayList ;
19
19
import java .util .Enumeration ;
20
+ import java .util .HashSet ;
20
21
import java .util .zip .CRC32 ;
21
22
import java .util .zip .CheckedInputStream ;
22
23
import java .util .zip .CheckedOutputStream ;
@@ -42,6 +43,12 @@ public class FileUtils {
42
43
".amr" , ".awb" , ".wma" , ".wmv" ,
43
44
".tflite" , ".lite"
44
45
};
46
+ private static final String APPEND_PREFIX_FORMAT = "#$&(" ;
47
+ private static final String APPEND_SUBFIX_FORMAT = ")&$#" ;
48
+
49
+ private static final HashSet <String > ResFileNameSet = new HashSet <>();
50
+ private static final String RES_PATH_CONST = "res" + File .separator ;
51
+
45
52
46
53
/**
47
54
* 解压文件
@@ -52,6 +59,7 @@ public class FileUtils {
52
59
*/
53
60
@ SuppressWarnings ("rawtypes" )
54
61
public static boolean decompressZip (String zipPath , String descDir ) {
62
+ ResFileNameSet .clear ();
55
63
File zipFile = new File (zipPath );
56
64
boolean flag = false ;
57
65
if (!descDir .endsWith (File .separator )) {
@@ -88,6 +96,17 @@ public static boolean decompressZip(String zipPath, String descDir) {
88
96
if (new File (outPath ).isDirectory ()) {
89
97
continue ;
90
98
}
99
+
100
+ // 处理res/aaa.xml资源名称忽略大小写出现重复的问题, 比如 youtube app, 漫画人app等等
101
+ if (zipEntryName .startsWith (RES_PATH_CONST ) && zipEntryName .split (File .separator ).length == 2 ) {
102
+ String fileName = zipEntryName .split (File .separator )[1 ];
103
+ fileName = getNotContainedFileName (fileName , ResFileNameSet );
104
+ ResFileNameSet .add (fileName .toLowerCase ());
105
+
106
+ zipEntryName = RES_PATH_CONST + fileName ;
107
+ outPath = (descDir + zipEntryName ).replace ("/" , File .separator );
108
+ }
109
+
91
110
//保存文件路径信息(可利用md5.zip名称的唯一性,来判断是否已经解压)
92
111
// System.err.println("当前zip解压之后的路径为:" + outPath);
93
112
OutputStream out = new FileOutputStream (outPath );
@@ -107,6 +126,33 @@ public static boolean decompressZip(String zipPath, String descDir) {
107
126
return flag ;
108
127
}
109
128
129
+ private static String getNotContainedFileName (String fileName , HashSet <String > set ) {
130
+ StringBuilder name = new StringBuilder (fileName );
131
+ if (set .contains (name .toString ().toLowerCase ())) {
132
+ for (int i = 1 ; i < 100 ; i ++) {
133
+ name .insert (0 , APPEND_SUBFIX_FORMAT );
134
+ name .insert (0 , i );
135
+ name .insert (0 , APPEND_PREFIX_FORMAT );
136
+ if (!set .contains (name .toString ().toLowerCase ())) {
137
+ return name .toString ();
138
+ }
139
+ }
140
+ } else {
141
+ return name .toString ();
142
+ }
143
+ return name .toString ();
144
+ }
145
+
146
+ private static String removeFileNamePrefix (String fileName ) {
147
+ String lastPrefix = APPEND_PREFIX_FORMAT + "1" + APPEND_SUBFIX_FORMAT ;
148
+ int index = fileName .lastIndexOf (lastPrefix );
149
+ if (index >= 0 ) {
150
+ return fileName .substring (index + lastPrefix .length ());
151
+ } else {
152
+ return fileName ;
153
+ }
154
+ }
155
+
110
156
private static InputStream getInputStreamFromFile (String filePath ) {
111
157
return FileUtils .class .getClassLoader ().getResourceAsStream (filePath );
112
158
}
@@ -248,8 +294,11 @@ private static void compressFile(File file, ZipOutputStream zipOut, String baseD
248
294
BufferedInputStream bis = null ;
249
295
try {
250
296
bis = new BufferedInputStream (new FileInputStream (file ));
251
- ZipEntry entry = new ZipEntry (baseDir + file .getName ());
252
297
String fileName = file .getName ();
298
+ if (baseDir .equals (RES_PATH_CONST )) { // 处理res/目录下,文件名称忽略大小写出现重复的问题
299
+ fileName = removeFileNamePrefix (fileName );
300
+ }
301
+ ZipEntry entry = new ZipEntry (baseDir + fileName );
253
302
boolean isNoCompressFileFormat = false ;
254
303
int index = fileName .lastIndexOf ("." );
255
304
if (index >= 0 ) {
@@ -357,5 +406,4 @@ private static void close(Closeable closeable) {
357
406
io .printStackTrace ();
358
407
}
359
408
}
360
-
361
409
}
0 commit comments