/* | |
* Copyright 2011 gitblit.com. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
package com.gitblit.utils; | |
import java.io.BufferedInputStream; | |
import java.io.BufferedReader; | |
import java.io.BufferedWriter; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.io.OutputStreamWriter; | |
import java.nio.charset.Charset; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
/** | |
* Common file utilities. | |
* | |
* @author James Moger | |
* | |
*/ | |
public class FileUtils { | |
/** 1024 (number of bytes in one kilobyte) */ | |
public static final int KB = 1024; | |
/** 1024 {@link #KB} (number of bytes in one megabyte) */ | |
public static final int MB = 1024 * KB; | |
/** 1024 {@link #MB} (number of bytes in one gigabyte) */ | |
public static final int GB = 1024 * MB; | |
/** | |
* Returns an int from a string representation of a file size. | |
* e.g. 50m = 50 megabytes | |
* | |
* @param aString | |
* @param defaultValue | |
* @return an int value or the defaultValue if aString can not be parsed | |
*/ | |
public static int convertSizeToInt(String aString, int defaultValue) { | |
return (int) convertSizeToLong(aString, defaultValue); | |
} | |
/** | |
* Returns a long from a string representation of a file size. | |
* e.g. 50m = 50 megabytes | |
* | |
* @param aString | |
* @param defaultValue | |
* @return a long value or the defaultValue if aString can not be parsed | |
*/ | |
public static long convertSizeToLong(String aString, long defaultValue) { | |
// trim string and remove all spaces | |
aString = aString.toLowerCase().trim(); | |
StringBuilder sb = new StringBuilder(); | |
for (String a : aString.split(" ")) { | |
sb.append(a); | |
} | |
aString = sb.toString(); | |
// identify value and unit | |
int idx = 0; | |
int len = aString.length(); | |
while (Character.isDigit(aString.charAt(idx))) { | |
idx++; | |
if (idx == len) { | |
break; | |
} | |
} | |
long value = 0; | |
String unit = null; | |
try { | |
value = Long.parseLong(aString.substring(0, idx)); | |
unit = aString.substring(idx); | |
} catch (Exception e) { | |
return defaultValue; | |
} | |
if (unit.equals("g") || unit.equals("gb")) { | |
return value * GB; | |
} else if (unit.equals("m") || unit.equals("mb")) { | |
return value * MB; | |
} else if (unit.equals("k") || unit.equals("kb")) { | |
return value * KB; | |
} | |
return defaultValue; | |
} | |
/** | |
* Returns the byte [] content of the specified file. | |
* | |
* @param file | |
* @return the byte content of the file | |
*/ | |
public static byte [] readContent(File file) { | |
byte [] buffer = new byte[(int) file.length()]; | |
BufferedInputStream is = null; | |
try { | |
is = new BufferedInputStream(new FileInputStream(file)); | |
is.read(buffer, 0, buffer.length); | |
} catch (Throwable t) { | |
System.err.println("Failed to read byte content of " + file.getAbsolutePath()); | |
t.printStackTrace(); | |
} finally { | |
if (is != null) { | |
try { | |
is.close(); | |
} catch (IOException ioe) { | |
System.err.println("Failed to close file " + file.getAbsolutePath()); | |
ioe.printStackTrace(); | |
} | |
} | |
} | |
return buffer; | |
} | |
/** | |
* Returns the string content of the specified file. | |
* | |
* @param file | |
* @param lineEnding | |
* @return the string content of the file | |
*/ | |
public static String readContent(File file, String lineEnding) { | |
StringBuilder sb = new StringBuilder(); | |
InputStreamReader is = null; | |
BufferedReader reader = null; | |
try { | |
is = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8")); | |
reader = new BufferedReader(is); | |
String line = null; | |
while ((line = reader.readLine()) != null) { | |
sb.append(line); | |
if (lineEnding != null) { | |
sb.append(lineEnding); | |
} | |
} | |
} catch (Throwable t) { | |
System.err.println("Failed to read content of " + file.getAbsolutePath()); | |
t.printStackTrace(); | |
} finally { | |
if (reader != null){ | |
try { | |
reader.close(); | |
} catch (IOException ioe) { | |
System.err.println("Failed to close file " + file.getAbsolutePath()); | |
ioe.printStackTrace(); | |
} | |
} | |
if (is != null) { | |
try { | |
is.close(); | |
} catch (IOException ioe) { | |
System.err.println("Failed to close file " + file.getAbsolutePath()); | |
ioe.printStackTrace(); | |
} | |
} | |
} | |
return sb.toString(); | |
} | |
/** | |
* Writes the string content to the file. | |
* | |
* @param file | |
* @param content | |
*/ | |
public static void writeContent(File file, String content) { | |
OutputStreamWriter os = null; | |
try { | |
os = new OutputStreamWriter(new FileOutputStream(file), Charset.forName("UTF-8")); | |
BufferedWriter writer = new BufferedWriter(os); | |
writer.append(content); | |
writer.flush(); | |
} catch (Throwable t) { | |
System.err.println("Failed to write content of " + file.getAbsolutePath()); | |
t.printStackTrace(); | |
} finally { | |
if (os != null) { | |
try { | |
os.close(); | |
} catch (IOException ioe) { | |
System.err.println("Failed to close file " + file.getAbsolutePath()); | |
ioe.printStackTrace(); | |
} | |
} | |
} | |
} | |
/** | |
* Recursively traverses a folder and its subfolders to calculate the total | |
* size in bytes. | |
* | |
* @param directory | |
* @return folder size in bytes | |
*/ | |
public static long folderSize(File directory) { | |
if (directory == null || !directory.exists()) { | |
return -1; | |
} | |
if (directory.isDirectory()) { | |
long length = 0; | |
for (File file : directory.listFiles()) { | |
length += folderSize(file); | |
} | |
return length; | |
} else if (directory.isFile()) { | |
return directory.length(); | |
} | |
return 0; | |
} | |
/** | |
* Delete a file or recursively delete a folder. | |
* | |
* @param fileOrFolder | |
* @return true, if successful | |
*/ | |
public static boolean delete(File fileOrFolder) { | |
boolean success = false; | |
if (fileOrFolder.isDirectory()) { | |
File [] files = fileOrFolder.listFiles(); | |
if (files != null) { | |
for (File file : files) { | |
if (file.isDirectory()) { | |
success |= delete(file); | |
} else { | |
success |= file.delete(); | |
} | |
} | |
} | |
} | |
success |= fileOrFolder.delete(); | |
return success; | |
} | |
/** | |
* Copies a file or folder (recursively) to a destination folder. | |
* | |
* @param destinationFolder | |
* @param filesOrFolders | |
* @return | |
* @throws FileNotFoundException | |
* @throws IOException | |
*/ | |
public static void copy(File destinationFolder, File... filesOrFolders) | |
throws FileNotFoundException, IOException { | |
destinationFolder.mkdirs(); | |
for (File file : filesOrFolders) { | |
if (file.isDirectory()) { | |
copy(new File(destinationFolder, file.getName()), file.listFiles()); | |
} else { | |
File dFile = new File(destinationFolder, file.getName()); | |
BufferedInputStream bufin = null; | |
FileOutputStream fos = null; | |
try { | |
bufin = new BufferedInputStream(new FileInputStream(file)); | |
fos = new FileOutputStream(dFile); | |
int len = 8196; | |
byte[] buff = new byte[len]; | |
int n = 0; | |
while ((n = bufin.read(buff, 0, len)) != -1) { | |
fos.write(buff, 0, n); | |
} | |
} finally { | |
try { | |
if (bufin != null) bufin.close(); | |
} catch (Throwable t) { | |
} | |
try { | |
if (fos != null) fos.close(); | |
} catch (Throwable t) { | |
} | |
} | |
dFile.setLastModified(file.lastModified()); | |
} | |
} | |
} | |
/** | |
* Determine the relative path between two files. Takes into account | |
* canonical paths, if possible. | |
* | |
* @param basePath | |
* @param path | |
* @return a relative path from basePath to path | |
*/ | |
public static String getRelativePath(File basePath, File path) { | |
Path exactBase = Paths.get(getExactFile(basePath).toURI()); | |
Path exactPath = Paths.get(getExactFile(path).toURI()); | |
if (exactPath.startsWith(exactBase)) { | |
return exactBase.relativize(exactPath).toString().replace('\\', '/'); | |
} | |
// no relative relationship | |
return null; | |
} | |
/** | |
* Returns the exact path for a file. This path will be the canonical path | |
* unless an exception is thrown in which case it will be the absolute path. | |
* | |
* @param path | |
* @return the exact file | |
*/ | |
public static File getExactFile(File path) { | |
try { | |
return path.getCanonicalFile(); | |
} catch (IOException e) { | |
return path.getAbsoluteFile(); | |
} | |
} | |
public static File resolveParameter(String parameter, File aFolder, String path) { | |
if (aFolder == null) { | |
// strip any parameter reference | |
path = path.replace(parameter, "").trim(); | |
if (path.length() > 0 && path.charAt(0) == '/') { | |
// strip leading / | |
path = path.substring(1); | |
} | |
} else if (path.contains(parameter)) { | |
// replace parameter with path | |
path = path.replace(parameter, aFolder.getAbsolutePath()); | |
} | |
return new File(path); | |
} | |
} |