001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030package org.openimaj.io; 031 032import java.io.BufferedInputStream; 033import java.io.BufferedOutputStream; 034import java.io.BufferedReader; 035import java.io.File; 036import java.io.FileInputStream; 037import java.io.FileOutputStream; 038import java.io.FileWriter; 039import java.io.FilenameFilter; 040import java.io.IOException; 041import java.io.InputStream; 042import java.io.InputStreamReader; 043import java.io.PrintWriter; 044import java.net.URL; 045import java.net.URLConnection; 046import java.util.ArrayList; 047import java.util.Arrays; 048import java.util.List; 049import java.util.Stack; 050 051/** 052 * Utility methods for dealing with files on the filesystem 053 * 054 * @author Jonathon Hare (jsh2@ecs.soton.ac.uk) 055 * @author Sina Samangooei (ss@ecs.soton.ac.uk) 056 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 057 * 058 */ 059public class FileUtils { 060 /** 061 * Recursively delete a directory 062 * @param dir 063 * @return true if success; false otherwise 064 */ 065 public static boolean deleteRecursive(final File dir) { 066 if (dir.isDirectory()) { 067 final String[] children = dir.list(); 068 for (int i=0; i<children.length; i++) { 069 final boolean success = FileUtils.deleteRecursive(new File(dir, children[i])); 070 if (!success) { 071 return false; 072 } 073 } 074 } 075 076 // The directory is now empty so delete it 077 return dir.delete(); 078 } 079 080 /** 081 * Download the contents of the given URL to the given file 082 * @param url The URL to download from 083 * @param file The target file 084 * @throws IOException if an error occurs 085 */ 086 public static void downloadURL(final URL url, final File file) throws IOException { 087 final URLConnection conn = url.openConnection(); 088 final InputStream stream = conn.getInputStream(); 089 final FileOutputStream fos = new FileOutputStream(file); 090 final byte[] buffer = new byte[1024]; 091 int read = 0; 092 while((read = stream.read(buffer)) != -1){ 093 fos.write(buffer,0,read); 094 } 095 fos.close(); 096 } 097 098 /** 099 * Utility method for quickly create a {@link BufferedReader} for 100 * a given file. 101 * @param file The file 102 * @return the corresponding reader 103 * @throws IOException if an error occurs 104 */ 105 public static BufferedReader read(final File file) throws IOException { 106 return new BufferedReader(new InputStreamReader(new FileInputStream(file))); 107 } 108 /** 109 * Utility method for reading a whole file into a single string. 110 * @param stream The stream 111 * @return the corresponding reader 112 * @throws IOException if an error occurs 113 */ 114 public static String readall(final InputStream stream) throws IOException { 115 final BufferedReader br = new BufferedReader(new InputStreamReader(stream)); 116 String line = null; 117 final StringBuilder builder = new StringBuilder(); 118 while((line = br.readLine()) != null){ 119 builder.append(line); 120 builder.append("\n"); 121 } 122 123 return builder.toString(); 124 } 125 /** 126 * Utility method for reading a whole file into a single string. 127 * @param stream The stream 128 * @param encoding the charset of {@link InputStreamReader} 129 * @return the corresponding reader 130 * @throws IOException if an error occurs 131 */ 132 public static String readall(final InputStream stream, String encoding) throws IOException { 133 final BufferedReader br = new BufferedReader(new InputStreamReader(stream,encoding)); 134 String line = null; 135 final StringBuilder builder = new StringBuilder(); 136 while((line = br.readLine()) != null){ 137 builder.append(line); 138 builder.append("\n"); 139 } 140 141 return builder.toString(); 142 } 143 144 /** 145 * Utility method for reading a whole file into a single string. 146 * @param file The file 147 * @return the corresponding reader 148 * @throws IOException if an error occurs 149 */ 150 public static String readall(final File file) throws IOException { 151 return FileUtils.readall(new FileInputStream(file)); 152 } 153 154 /** 155 * Helper function for writing a text stream to a file. 156 * @param stream the stream will be consumed 157 * @param output file 158 * @return a temporary file with the stream context written 159 * @throws IOException 160 */ 161 public static File copyStreamToFile(final InputStream stream,final File output) throws IOException{ 162 final BufferedReader r = new BufferedReader(new InputStreamReader(stream)); 163 String l =null; 164 final PrintWriter writer = new PrintWriter(new FileWriter(output)); 165 while((l = r.readLine())!=null){ 166 writer.println(l); 167 } 168 writer.close(); 169 r.close(); 170 return output; 171 } 172 173 /** 174 * Helper function for writing a binary stream to a file. The stream and 175 * the file are both closed on completion. 176 * 177 * @param stream The stream to be consumed. 178 * @param output The file to output to 179 * @return The output file 180 * @throws IOException 181 */ 182 public static File copyStreamToFileBinary( final InputStream stream, 183 final File output ) throws IOException 184 { 185 final FileOutputStream out = new FileOutputStream( output ); 186 final byte buf[] = new byte[1024]; 187 int len = 0; 188 while( (len = stream.read( buf )) > 0 ) 189 out.write( buf, 0, len ); 190 out.close(); 191 stream.close(); 192 193 return output; 194 } 195 196 /** 197 * Given a JAR Resource, this method will unpack the file to 198 * a temporary file and return the temporary file location. 199 * This temporary file will be deleted on the application exit. 200 * If the given resource is not a JAR resource, the method 201 * will return null. 202 * 203 * @param resource The resource to unpack 204 * @return The temporary file location 205 * @throws IOException If the temporary file could not be created. 206 */ 207 public static File unpackJarFile( final URL resource ) throws IOException 208 { 209 return FileUtils.unpackJarFile( resource, true ); 210 } 211 212 /** 213 * Given a JAR Resource, this method will unpack the file to 214 * a temporary file and return the temporary file location. 215 * If the given resource is not a JAR resource, the method 216 * will return null. 217 * 218 * @param resource The resource to unpack 219 * @param deleteOnExit Whether to delete the temporary file on exit 220 * @return The temporary file location 221 * @throws IOException If the temporary file could not be created. 222 */ 223 public static File unpackJarFile( final URL resource, final boolean deleteOnExit ) 224 throws IOException 225 { 226 if( !FileUtils.isJarResource( resource ) ) 227 return null; 228 229 final String ext = resource.toString().substring( 230 resource.toString().lastIndexOf(".") ); 231 final File f = File.createTempFile( "openimaj",ext ); 232 FileUtils.unpackJarFile( resource, f, deleteOnExit ); 233 return f; 234 } 235 236 /** 237 * Given a JAR resource, this method will unpack the file 238 * to the given destination. If the given resource is not 239 * a JAR resource, this method will do nothing. 240 * 241 * @param resource The resource to unpack. 242 * @param destination The destination file 243 * @param deleteOnExit Whether to delete the unpacked file on exit. 244 */ 245 public static void unpackJarFile( final URL resource, final File destination, 246 final boolean deleteOnExit ) 247 { 248 if( deleteOnExit ) 249 destination.deleteOnExit(); 250 251 BufferedInputStream urlin = null; 252 BufferedOutputStream fout = null; 253 try { 254 final int bufSize = 8 * 1024; 255 urlin = new BufferedInputStream( 256 resource.openConnection().getInputStream(), 257 bufSize); 258 fout = new BufferedOutputStream( 259 new FileOutputStream( destination ), bufSize); 260 261 int read = -1; 262 final byte[] buf = new byte[ bufSize ]; 263 while ((read = urlin.read(buf, 0, bufSize)) >= 0) 264 fout.write(buf, 0, read); 265 266 fout.flush(); 267 } 268 catch (final IOException ioex) 269 { 270 return; 271 } 272 catch( final SecurityException sx ) 273 { 274 return; 275 } 276 finally 277 { 278 if (urlin != null) 279 { 280 try 281 { 282 urlin.close(); 283 } 284 catch (final IOException cioex) 285 { 286 } 287 } 288 if (fout != null) 289 { 290 try 291 { 292 fout.close(); 293 } 294 catch (final IOException cioex) 295 { 296 } 297 } 298 } 299 } 300 301 /** 302 * Returns whether the given resource is a jar resource. 303 * @param resource The resource to test. 304 * @return TRUE if the resource is a JAR resource 305 */ 306 public static boolean isJarResource( final URL resource ) 307 { 308 return FileUtils.isJarResource( resource.toString() ); 309 } 310 311 /** 312 * Returns whether the given resource is a jar resource. 313 * @param resourceURL The resource to test. 314 * @return TRUE if the resource is in a jar. 315 */ 316 public static boolean isJarResource( final String resourceURL ) 317 { 318 return resourceURL.startsWith( "jar:" ); 319 } 320 321 /** 322 * Count the number of newlines in the given file 323 * @param filename The file 324 * @return the number of newline characters 325 */ 326 public static int countLines(final File filename) { 327 InputStream is = null; 328 try { 329 is = new BufferedInputStream(new FileInputStream(filename)); 330 final byte[] c = new byte[1024]; 331 int count = 0; 332 int readChars = 0; 333 while ((readChars = is.read(c)) != -1) { 334 for (int i = 0; i < readChars; ++i) { 335 if (c[i] == '\n') 336 ++count; 337 } 338 } 339 return count; 340 } 341 catch(final Exception e){ 342 return -1; 343 } finally { 344 try { 345 is.close(); 346 } catch (final IOException e) { 347 return -1; 348 } 349 } 350 } 351 352 /** 353 * Using {@link File#listFiles(FilenameFilter)} find a file in the directory recursively (i.e. following directories down). 354 * @param start 355 * @param filenameFilter 356 * @return list of files matching the filter 357 */ 358 public static File[] findRecursive(final File start, final FilenameFilter filenameFilter) { 359 final Stack<File> filesToCheck = new Stack<File>(); 360 final List<File> found = new ArrayList<File>(); 361 filesToCheck .push(start); 362 while(filesToCheck.size() > 0){ 363 final File toCheck = filesToCheck.pop(); 364 final File[] afiles = toCheck.listFiles(new FilenameFilter() { 365 366 @Override 367 public boolean accept(final File dir, final String name) { 368 final File found = new File(dir,name); 369 final boolean accept = filenameFilter.accept(found, name); 370 if(toCheck != found && found .isDirectory()) 371 { 372 System.out.println("Adding: " + found); 373 filesToCheck.push(found); 374 } 375 return accept; 376 } 377 }); 378 found.addAll(Arrays.asList(afiles)); 379 } 380 return found.toArray(new File[found.size()]); 381 } 382 383 /** 384 * @param file the file to read from 385 * @return the lines in the file 386 * @throws IOException 387 */ 388 public static String[] readlines(final File file) throws IOException { 389 final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 390 String line = null; 391 final List<String> allLines = new ArrayList<String>(); 392 while((line = br.readLine()) != null){ 393 allLines.add(line); 394 } 395 br.close(); 396 397 return allLines.toArray(new String[allLines.size()]); 398 } 399 400 /** 401 * @param file the file to read from 402 * @param encoding 403 * @return the lines in the file 404 * @throws IOException 405 */ 406 public static String[] readlines(final File file, String encoding) throws IOException { 407 final BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file),encoding)); 408 String line = null; 409 final List<String> allLines = new ArrayList<String>(); 410 while((line = br.readLine()) != null){ 411 allLines.add(line); 412 } 413 br.close(); 414 415 return allLines.toArray(new String[allLines.size()]); 416 } 417 418 /** 419 * @param stream the file to read from 420 * @return the lines in the file 421 * @throws IOException 422 */ 423 public static String[] readlines(final InputStream stream) throws IOException { 424 final BufferedReader br = new BufferedReader(new InputStreamReader(stream)); 425 String line = null; 426 final List<String> allLines = new ArrayList<String>(); 427 while((line = br.readLine()) != null){ 428 allLines.add(line); 429 } 430 431 return allLines.toArray(new String[allLines.size()]); 432 } 433 434 /** 435 * @param stream the file to read from 436 * @param encoding the inputstream encoding 437 * @return the lines in the file 438 * @throws IOException 439 */ 440 public static String[] readlines(final InputStream stream, String encoding) throws IOException { 441 final BufferedReader br = new BufferedReader(new InputStreamReader(stream,encoding)); 442 String line = null; 443 final List<String> allLines = new ArrayList<String>(); 444 while((line = br.readLine()) != null){ 445 allLines.add(line); 446 } 447 448 return allLines.toArray(new String[allLines.size()]); 449 } 450}