38 import android.os.Build; |
38 import android.os.Build; |
39 import android.os.Environment; |
39 import android.os.Environment; |
40 import android.util.Log; |
40 import android.util.Log; |
41 |
41 |
42 public class FileUtils { |
42 public class FileUtils { |
43 private static final String ROOT_DIR = "Data"; |
43 private static final String ROOT_DIR = "Data"; |
44 private static final String TAG = FileUtils.class.getSimpleName(); |
44 private static final String TAG = FileUtils.class.getSimpleName(); |
45 |
45 |
46 /** |
46 /** |
47 * @return true if the data path is currently available. However, it can vanish at any time so |
47 * @return true if the data path is currently available. However, it can vanish at any time so |
48 * normally you should just try to use it and rely on the exceptions. |
48 * normally you should just try to use it and rely on the exceptions. |
49 */ |
49 */ |
50 public static boolean isDataPathAvailable() { |
50 public static boolean isDataPathAvailable() { |
51 return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); |
51 return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()); |
52 } |
52 } |
53 |
53 |
54 /** |
54 /** |
55 * get the path to which we should download all the data files |
55 * get the path to which we should download all the data files |
56 * @param c context |
56 * @param c context |
57 * @return The directory |
57 * @return The directory |
58 * @throws FileNotFoundException if external storage is not available at the moment |
58 * @throws FileNotFoundException if external storage is not available at the moment |
59 */ |
59 */ |
60 public static File getCachePath(Context c) throws FileNotFoundException { |
60 public static File getCachePath(Context c) throws FileNotFoundException { |
61 File cachePath = null; |
61 File cachePath = null; |
62 if(Build.VERSION.SDK_INT < 8){//8 == Build.VERSION_CODES.FROYO |
62 if(Build.VERSION.SDK_INT < 8){//8 == Build.VERSION_CODES.FROYO |
63 cachePath = PreFroyoSDCardDir.getDownloadPath(c); |
63 cachePath = PreFroyoSDCardDir.getDownloadPath(c); |
64 } else { |
64 } else { |
65 cachePath = FroyoSDCardDir.getDownloadPath(c); |
65 cachePath = FroyoSDCardDir.getDownloadPath(c); |
66 } |
66 } |
67 if(cachePath==null) { |
67 if(cachePath==null) { |
68 throw new FileNotFoundException("External storage is currently unavailable"); |
68 throw new FileNotFoundException("External storage is currently unavailable"); |
69 } else { |
69 } else { |
70 return cachePath; |
70 return cachePath; |
71 } |
71 } |
72 } |
72 } |
73 |
73 |
74 public static File getDataPathFile(Context c, String...subpath) throws FileNotFoundException { |
74 public static File getDataPathFile(Context c, String...subpath) throws FileNotFoundException { |
75 File file = new File(getCachePath(c), ROOT_DIR); |
75 File file = new File(getCachePath(c), ROOT_DIR); |
76 for(String pathcomponent : subpath) { |
76 for(String pathcomponent : subpath) { |
77 file = new File(file, pathcomponent); |
77 file = new File(file, pathcomponent); |
78 } |
78 } |
79 return file; |
79 return file; |
80 } |
80 } |
81 |
81 |
82 @TargetApi(8) |
82 @TargetApi(8) |
83 private static class FroyoSDCardDir{ |
83 private static class FroyoSDCardDir{ |
84 public static File getDownloadPath(Context c){ |
84 public static File getDownloadPath(Context c){ |
85 return c.getExternalCacheDir(); |
85 return c.getExternalCacheDir(); |
86 } |
86 } |
87 } |
87 } |
88 |
88 |
89 private static class PreFroyoSDCardDir{ |
89 private static class PreFroyoSDCardDir{ |
90 public static File getDownloadPath(Context c){ |
90 public static File getDownloadPath(Context c){ |
91 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ |
91 if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ |
92 File extStorageDir = Environment.getExternalStorageDirectory(); |
92 File extStorageDir = Environment.getExternalStorageDirectory(); |
93 if(extStorageDir != null) { |
93 if(extStorageDir != null) { |
94 return new File(extStorageDir, "Hedgewars"); |
94 return new File(extStorageDir, "Hedgewars"); |
95 } |
95 } |
96 } |
96 } |
97 return null; |
97 return null; |
98 } |
98 } |
99 } |
99 } |
100 |
100 |
101 /** |
101 /** |
102 * Return a File array with all the files from dirName |
102 * Return a File array with all the files from dirName |
103 * @param c |
103 * @param c |
104 * @param dirName |
104 * @param dirName |
105 * @return |
105 * @return |
106 * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dirName" does not exist |
106 * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dirName" does not exist |
107 */ |
107 */ |
108 public static File[] getFilesFromRelativeDir(Context c, String dirName) throws FileNotFoundException { |
108 public static File[] getFilesFromRelativeDir(Context c, String dirName) throws FileNotFoundException { |
109 File f = getDataPathFile(c, dirName); |
109 File f = getDataPathFile(c, dirName); |
110 |
110 |
111 if(f.isDirectory()) { |
111 if(f.isDirectory()) { |
112 return f.listFiles(); |
112 return f.listFiles(); |
113 } else { |
113 } else { |
114 throw new FileNotFoundException("Directory "+dirName+" does not exist."); |
114 throw new FileNotFoundException("Directory "+dirName+" does not exist."); |
115 } |
115 } |
116 } |
116 } |
117 |
117 |
118 /** |
118 /** |
119 * Checks if this directory has a file with suffix suffix |
119 * Checks if this directory has a file with suffix suffix |
120 * @param f - directory |
120 * @param f - directory |
121 * @return |
121 * @return |
122 */ |
122 */ |
123 public static boolean hasFileWithSuffix(File f, String suffix){ |
123 public static boolean hasFileWithSuffix(File f, String suffix){ |
124 if(f.isDirectory()){ |
124 if(f.isDirectory()){ |
125 for(String s : f.list()){ |
125 for(String s : f.list()){ |
126 if(s.endsWith(suffix)) return true; |
126 if(s.endsWith(suffix)) return true; |
127 } |
127 } |
128 return false; |
128 return false; |
129 }else{ |
129 }else{ |
130 return false; |
130 return false; |
131 } |
131 } |
132 } |
132 } |
133 |
133 |
134 /** |
134 /** |
135 * Gives back all dirs which contain a file with suffix fileSuffix |
135 * Gives back all dirs which contain a file with suffix fileSuffix |
136 * @param c |
136 * @param c |
137 * @param path |
137 * @param path |
138 * @param fileSuffix |
138 * @param fileSuffix |
139 * @return |
139 * @return |
140 * @throws FileNotFoundException If the sdcard is not available or the subdirectory "path" does not exist |
140 * @throws FileNotFoundException If the sdcard is not available or the subdirectory "path" does not exist |
141 */ |
141 */ |
142 public static List<String> getDirsWithFileSuffix(Context c, String path, String fileSuffix) throws FileNotFoundException{ |
142 public static List<String> getDirsWithFileSuffix(Context c, String path, String fileSuffix) throws FileNotFoundException{ |
143 File[] files = getFilesFromRelativeDir(c,path); |
143 File[] files = getFilesFromRelativeDir(c,path); |
144 ArrayList<String> ret = new ArrayList<String>(); |
144 ArrayList<String> ret = new ArrayList<String>(); |
145 |
145 |
146 for(File f : files){ |
146 for(File f : files){ |
147 if(hasFileWithSuffix(f, fileSuffix)) ret.add(f.getName()); |
147 if(hasFileWithSuffix(f, fileSuffix)) ret.add(f.getName()); |
148 } |
148 } |
149 return ret; |
149 return ret; |
150 } |
150 } |
151 |
151 |
152 /** |
152 /** |
153 * Get all files from directory dir which have the given suffix |
153 * Get all files from directory dir which have the given suffix |
154 * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dir" does not exist |
154 * @throws FileNotFoundException If the sdcard is not available or the subdirectory "dir" does not exist |
155 */ |
155 */ |
156 public static List<String> getFileNamesFromDirWithSuffix(Context c, String dir, String suffix, boolean removeSuffix) throws FileNotFoundException{ |
156 public static List<String> getFileNamesFromDirWithSuffix(Context c, String dir, String suffix, boolean removeSuffix) throws FileNotFoundException{ |
157 File[] files = FileUtils.getFilesFromRelativeDir(c, dir); |
157 File[] files = FileUtils.getFilesFromRelativeDir(c, dir); |
158 List<String> ret = new ArrayList<String>(); |
158 List<String> ret = new ArrayList<String>(); |
159 for(File file : files){ |
159 for(File file : files){ |
160 String s = file.getName(); |
160 String s = file.getName(); |
161 if(s.endsWith(suffix)){ |
161 if(s.endsWith(suffix)){ |
162 if(removeSuffix) ret.add(s.substring(0, s.length()-suffix.length())); |
162 if(removeSuffix) ret.add(s.substring(0, s.length()-suffix.length())); |
163 else ret.add(s); |
163 else ret.add(s); |
164 } |
164 } |
165 } |
165 } |
166 return ret; |
166 return ret; |
167 } |
167 } |
168 |
168 |
169 /** |
169 /** |
170 * Close a resource (possibly null), ignoring any IOException. |
170 * Close a resource (possibly null), ignoring any IOException. |
171 */ |
171 */ |
172 public static void closeQuietly(Closeable c) { |
172 public static void closeQuietly(Closeable c) { |
173 if(c!=null) { |
173 if(c!=null) { |
174 try { |
174 try { |
175 c.close(); |
175 c.close(); |
176 } catch(IOException e) { |
176 } catch(IOException e) { |
177 Log.w(TAG, e); |
177 Log.w(TAG, e); |
178 } |
178 } |
179 } |
179 } |
180 } |
180 } |
181 |
181 |
182 /** |
182 /** |
183 * Write all data from the input stream to the file, creating or overwriting it. |
183 * Write all data from the input stream to the file, creating or overwriting it. |
184 * The input stream will be closed. |
184 * The input stream will be closed. |
185 * |
185 * |
186 * @throws IOException |
186 * @throws IOException |
187 */ |
187 */ |
188 public static void writeStreamToFile(InputStream is, File file) throws IOException { |
188 public static void writeStreamToFile(InputStream is, File file) throws IOException { |
189 OutputStream os = null; |
189 OutputStream os = null; |
190 byte[] buffer = new byte[8192]; |
190 byte[] buffer = new byte[8192]; |
191 try { |
191 try { |
192 os = new FileOutputStream(file); |
192 os = new FileOutputStream(file); |
193 int size; |
193 int size; |
194 while((size=is.read(buffer)) != -1) { |
194 while((size=is.read(buffer)) != -1) { |
195 os.write(buffer, 0, size); |
195 os.write(buffer, 0, size); |
196 } |
196 } |
197 os.close(); // Important to close this non-quietly, in case of exceptions when flushing |
197 os.close(); // Important to close this non-quietly, in case of exceptions when flushing |
198 } finally { |
198 } finally { |
199 FileUtils.closeQuietly(is); |
199 FileUtils.closeQuietly(is); |
200 FileUtils.closeQuietly(os); |
200 FileUtils.closeQuietly(os); |
201 } |
201 } |
202 } |
202 } |
203 |
203 |
204 /** |
204 /** |
205 * Moves resources pointed to by sourceResId (from @res/raw/) to the app's private data directory |
205 * Moves resources pointed to by sourceResId (from @res/raw/) to the app's private data directory |
206 * @param c |
206 * @param c |
207 * @param sourceResId |
207 * @param sourceResId |
208 * @param directory |
208 * @param directory |
209 */ |
209 */ |
210 public static void resRawToFilesDir(Context c, int sourceResId, int targetFilenames, String directory) throws IOException { |
210 public static void resRawToFilesDir(Context c, int sourceResId, int targetFilenames, String directory) throws IOException { |
211 File targetDir = new File(c.getFilesDir(), directory); |
211 File targetDir = new File(c.getFilesDir(), directory); |
212 targetDir.mkdirs(); |
212 targetDir.mkdirs(); |
213 |
213 |
214 //Get an array with the resource files ID |
214 //Get an array with the resource files ID |
215 Resources resources = c.getResources(); |
215 Resources resources = c.getResources(); |
216 TypedArray ta = resources.obtainTypedArray(sourceResId); |
216 TypedArray ta = resources.obtainTypedArray(sourceResId); |
217 TypedArray filenames = resources.obtainTypedArray(targetFilenames); |
217 TypedArray filenames = resources.obtainTypedArray(targetFilenames); |
218 for(int i = 0; i < ta.length(); i++){ |
218 for(int i = 0; i < ta.length(); i++){ |
219 int resId = ta.getResourceId(i, 0); |
219 int resId = ta.getResourceId(i, 0); |
220 String fileName = filenames.getString(i); |
220 String fileName = filenames.getString(i); |
221 File f = new File(targetDir, fileName); |
221 File f = new File(targetDir, fileName); |
222 writeStreamToFile(resources.openRawResource(resId), f); |
222 writeStreamToFile(resources.openRawResource(resId), f); |
223 } |
223 } |
224 } |
224 } |
225 |
225 |
226 public static String readToString(InputStream is) throws IOException { |
226 public static String readToString(InputStream is) throws IOException { |
227 try { |
227 try { |
228 ByteArrayOutputStream os = new ByteArrayOutputStream(); |
228 ByteArrayOutputStream os = new ByteArrayOutputStream(); |
229 byte[] buffer = new byte[8192]; |
229 byte[] buffer = new byte[8192]; |
230 int size; |
230 int size; |
231 while((size=is.read(buffer)) != -1) { |
231 while((size=is.read(buffer)) != -1) { |
232 os.write(buffer, 0, size); |
232 os.write(buffer, 0, size); |
233 } |
233 } |
234 return new String(os.toByteArray()); |
234 return new String(os.toByteArray()); |
235 } finally { |
235 } finally { |
236 closeQuietly(is); |
236 closeQuietly(is); |
237 } |
237 } |
238 } |
238 } |
239 |
239 |
240 private static final char[] badFilenameChars = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|', '.', '\0' }; |
240 private static final char[] badFilenameChars = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|', '.', '\0' }; |
241 |
241 |
242 /** |
242 /** |
243 * Modify the given String so that it can be used as part of a filename |
243 * Modify the given String so that it can be used as part of a filename |
244 * without causing problems from illegal/special characters. |
244 * without causing problems from illegal/special characters. |
245 * |
245 * |
246 * The result should be similar to the input, but isn't necessarily |
246 * The result should be similar to the input, but isn't necessarily |
247 * reversible. |
247 * reversible. |
248 */ |
248 */ |
249 public static String replaceBadChars(String name) { |
249 public static String replaceBadChars(String name) { |
250 if (name == null || name.trim().length()==0) { |
250 if (name == null || name.trim().length()==0) { |
251 return "_"; |
251 return "_"; |
252 } |
252 } |
253 name = name.trim(); |
253 name = name.trim(); |
254 for (char badChar : badFilenameChars) { |
254 for (char badChar : badFilenameChars) { |
255 name = name.replace(badChar, '_'); |
255 name = name.replace(badChar, '_'); |
256 } |
256 } |
257 return name; |
257 return name; |
258 } |
258 } |
259 } |
259 } |