001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.transaction.util; 018 019import java.io.File; 020import java.io.FileInputStream; 021import java.io.FileOutputStream; 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.OutputStream; 025 026/** 027 * Helper methods for file manipulation. 028 * All methods are <em>thread safe</em>. 029 * 030 * @version $Id: FileHelper.java 493628 2007-01-07 01:42:48Z joerg $ 031 */ 032public final class FileHelper { 033 034 private static int BUF_SIZE = 50000; 035 private static byte[] BUF = new byte[BUF_SIZE]; 036 037 /** 038 * Deletes a file specified by a path. 039 * 040 * @param path path of file to be deleted 041 * @return <code>true</code> if file has been deleted, <code>false</code> otherwise 042 */ 043 public static boolean deleteFile(String path) { 044 File file = new File(path); 045 return file.delete(); 046 } 047 048 /** 049 * Checks if a file specified by a path exits. 050 * 051 * @param path path of file to be checked 052 * @return <code>true</code> if file exists, <code>false</code> otherwise 053 */ 054 public static boolean fileExists(String path) { 055 File file = new File(path); 056 return file.exists(); 057 } 058 059 /** 060 * Creates a file specified by a path. All necessary directories will be created. 061 * 062 * @param path path of file to be created 063 * @return <code>true</code> if file has been created, <code>false</code> if the file already exists 064 * @throws IOException 065 * If an I/O error occurred 066 */ 067 public static boolean createFile(String path) throws IOException { 068 File file = new File(path); 069 if (file.isDirectory()) { 070 return file.mkdirs(); 071 } else { 072 File dir = file.getParentFile(); 073 // do not check if this worked, as it may also return false, when all neccessary dirs are present 074 dir.mkdirs(); 075 return file.createNewFile(); 076 } 077 } 078 079 /** 080 * Removes a file. If the specified file is a directory all contained files will 081 * be removed recursively as well. 082 * 083 * @param toRemove file to be removed 084 */ 085 public static void removeRec(File toRemove) { 086 if (toRemove.isDirectory()) { 087 File fileList[] = toRemove.listFiles(); 088 for (int a = 0; a < fileList.length; a++) { 089 removeRec(fileList[a]); 090 } 091 } 092 toRemove.delete(); 093 } 094 095 /** 096 * Moves one directory or file to another. Existing files will be replaced. 097 * 098 * @param source file to move from 099 * @param target file to move to 100 * @throws IOException if an I/O error occurs (may result in partially done work) 101 */ 102 public static void moveRec(File source, File target) throws IOException { 103 byte[] sharedBuffer = new byte[BUF_SIZE]; 104 moveRec(source, target, sharedBuffer); 105 } 106 107 static void moveRec(File source, File target, byte[] sharedBuffer) throws IOException { 108 if (source.isDirectory()) { 109 if (!target.exists()) { 110 target.mkdirs(); 111 } 112 if (target.isDirectory()) { 113 114 File[] files = source.listFiles(); 115 for (int i = 0; i < files.length; i++) { 116 File file = files[i]; 117 File targetFile = new File(target, file.getName()); 118 if (file.isFile()) { 119 if (targetFile.exists()) { 120 targetFile.delete(); 121 } 122 if (!file.renameTo(targetFile)) { 123 copy(file, targetFile, sharedBuffer); 124 file.delete(); 125 } 126 } else { 127 if (!targetFile.exists()) { 128 if (!targetFile.mkdirs()) { 129 throw new IOException("Could not create target directory: " 130 + targetFile); 131 } 132 } 133 moveRec(file, targetFile); 134 } 135 } 136 source.delete(); 137 } 138 } else { 139 if (!target.isDirectory()) { 140 copy(source, target, sharedBuffer); 141 source.delete(); 142 } 143 } 144 } 145 146 /** 147 * Copies one directory or file to another. Existing files will be replaced. 148 * 149 * @param source directory or file to copy from 150 * @param target directory or file to copy to 151 * @throws IOException if an I/O error occurs (may result in partially done work) 152 */ 153 public static void copyRec(File source, File target) throws IOException { 154 byte[] sharedBuffer = new byte[BUF_SIZE]; 155 copyRec(source, target, sharedBuffer); 156 } 157 158 static void copyRec(File source, File target, byte[] sharedBuffer) throws IOException { 159 if (source.isDirectory()) { 160 if (!target.exists()) { 161 target.mkdirs(); 162 } 163 if (target.isDirectory()) { 164 165 File[] files = source.listFiles(); 166 for (int i = 0; i < files.length; i++) { 167 File file = files[i]; 168 File targetFile = new File(target, file.getName()); 169 if (file.isFile()) { 170 if (targetFile.exists()) { 171 targetFile.delete(); 172 } 173 copy(file, targetFile, sharedBuffer); 174 } else { 175 targetFile.mkdirs(); 176 copyRec(file, targetFile); 177 } 178 } 179 } 180 } else { 181 if (!target.isDirectory()) { 182 if (!target.exists()) { 183 File dir = target.getParentFile(); 184 if(!dir.exists() && !dir.mkdirs()) { 185 throw new IOException("Could not create target directory: " + dir); 186 } 187 if (!target.createNewFile()) { 188 throw new IOException("Could not create target file: " + target); 189 } 190 } 191 copy(source, target, sharedBuffer); 192 } 193 } 194 } 195 196 /** 197 * Copies one file to another using {@link #copy(InputStream, OutputStream)}. 198 * 199 * @param input 200 * source file 201 * @param output 202 * destination file 203 * @return the number of bytes copied 204 * @throws IOException 205 * if an I/O error occurs (may result in partially done work) 206 * @see #copy(InputStream, OutputStream) 207 */ 208 public static long copy(File input, File output) throws IOException { 209 FileInputStream in = null; 210 try { 211 in = new FileInputStream(input); 212 return copy(in, output); 213 } finally { 214 if (in != null) { 215 try { 216 in.close(); 217 } catch (IOException e) { 218 } 219 } 220 } 221 } 222 223 /** 224 * Copies one file to another using the supplied buffer. 225 * 226 * @param input source file 227 * @param output destination file 228 * @param copyBuffer buffer used for copying 229 * @return the number of bytes copied 230 * @throws IOException if an I/O error occurs (may result in partially done work) 231 * @see #copy(InputStream, OutputStream) 232 */ 233 public static long copy(File input, File output, byte[] copyBuffer) throws IOException { 234 FileInputStream in = null; 235 FileOutputStream out = null; 236 try { 237 in = new FileInputStream(input); 238 out = new FileOutputStream(output); 239 return copy(in, out, copyBuffer); 240 } finally { 241 if (in != null) { 242 try { 243 in.close(); 244 } catch (IOException e) { 245 } 246 } 247 if (out != null) { 248 try { 249 out.close(); 250 } catch (IOException e) { 251 } 252 } 253 } 254 } 255 256 /** 257 * Copies an <code>InputStream</code> to a file using {@link #copy(InputStream, OutputStream)}. 258 * 259 * @param in stream to copy from 260 * @param outputFile file to copy to 261 * @return the number of bytes copied 262 * @throws IOException if an I/O error occurs (may result in partially done work) 263 * @see #copy(InputStream, OutputStream) 264 */ 265 public static long copy(InputStream in, File outputFile) throws IOException { 266 FileOutputStream out = null; 267 try { 268 out = new FileOutputStream(outputFile); 269 return copy(in, out); 270 } finally { 271 if (out != null) { 272 try { 273 out.close(); 274 } catch (IOException e) { 275 } 276 } 277 } 278 } 279 280 /** 281 * Copies an <code>InputStream</code> to an <code>OutputStream</code> using a local internal buffer for performance. 282 * Compared to {@link #globalBufferCopy(InputStream, OutputStream)} this method allows for better 283 * concurrency, but each time it is called generates a buffer which will be garbage. 284 * 285 * @param in stream to copy from 286 * @param out stream to copy to 287 * @return the number of bytes copied 288 * @throws IOException if an I/O error occurs (may result in partially done work) 289 * @see #globalBufferCopy(InputStream, OutputStream) 290 */ 291 public static long copy(InputStream in, OutputStream out) throws IOException { 292 // we need a buffer of our own, so no one else interferes 293 byte[] buf = new byte[BUF_SIZE]; 294 return copy(in, out, buf); 295 } 296 297 /** 298 * Copies an <code>InputStream</code> to an <code>OutputStream</code> using a global internal buffer for performance. 299 * Compared to {@link #copy(InputStream, OutputStream)} this method generated no garbage, 300 * but decreases concurrency. 301 * 302 * @param in stream to copy from 303 * @param out stream to copy to 304 * @return the number of bytes copied 305 * @throws IOException if an I/O error occurs (may result in partially done work) 306 * @see #copy(InputStream, OutputStream) 307 */ 308 public static long globalBufferCopy(InputStream in, OutputStream out) throws IOException { 309 synchronized (BUF) { 310 return copy(in, out, BUF); 311 } 312 } 313 314 /** 315 * Copies an <code>InputStream</code> to an <code>OutputStream</code> using the specified buffer. 316 * 317 * @param in stream to copy from 318 * @param out stream to copy to 319 * @param copyBuffer buffer used for copying 320 * @return the number of bytes copied 321 * @throws IOException if an I/O error occurs (may result in partially done work) 322 * @see #globalBufferCopy(InputStream, OutputStream) 323 * @see #copy(InputStream, OutputStream) 324 */ 325 public static long copy(InputStream in, OutputStream out, byte[] copyBuffer) throws IOException { 326 long bytesCopied = 0; 327 int read = -1; 328 329 while ((read = in.read(copyBuffer, 0, copyBuffer.length)) != -1) { 330 out.write(copyBuffer, 0, read); 331 bytesCopied += read; 332 } 333 return bytesCopied; 334 } 335}