2014-04-19 02:30:29 -04:00
package net.filebot.util ;
2014-04-01 08:36:34 -04:00
2014-04-17 11:35:33 -04:00
import static java.util.Arrays.* ;
2014-11-07 08:26:54 -05:00
import static java.util.Collections.* ;
2014-04-17 11:35:33 -04:00
2014-04-01 08:36:34 -04:00
import java.io.BufferedInputStream ;
import java.io.File ;
import java.io.FileFilter ;
import java.io.FileInputStream ;
import java.io.FilenameFilter ;
import java.io.IOException ;
import java.io.InputStream ;
import java.io.InputStreamReader ;
import java.io.Reader ;
2015-05-08 04:20:20 -04:00
import java.math.BigInteger ;
2014-04-01 08:36:34 -04:00
import java.nio.ByteBuffer ;
import java.nio.channels.FileChannel ;
import java.nio.charset.Charset ;
2015-05-09 02:38:47 -04:00
import java.nio.charset.StandardCharsets ;
2014-04-01 08:36:34 -04:00
import java.nio.file.AtomicMoveNotSupportedException ;
2014-07-15 08:57:07 -04:00
import java.nio.file.FileVisitOption ;
import java.nio.file.FileVisitResult ;
import java.nio.file.Files ;
2014-04-16 13:23:25 -04:00
import java.nio.file.Path ;
2014-07-15 08:57:07 -04:00
import java.nio.file.SimpleFileVisitor ;
2014-04-01 08:36:34 -04:00
import java.nio.file.StandardCopyOption ;
2014-11-06 23:54:21 -05:00
import java.nio.file.StandardOpenOption ;
2014-07-15 08:57:07 -04:00
import java.nio.file.attribute.BasicFileAttributes ;
2015-05-08 04:20:20 -04:00
import java.security.MessageDigest ;
import java.security.NoSuchAlgorithmException ;
2014-04-01 08:36:34 -04:00
import java.util.ArrayList ;
import java.util.Collection ;
import java.util.Comparator ;
2014-07-15 08:57:07 -04:00
import java.util.EnumSet ;
2014-04-01 08:36:34 -04:00
import java.util.HashMap ;
import java.util.Iterator ;
import java.util.LinkedList ;
import java.util.List ;
import java.util.Map ;
import java.util.Scanner ;
import java.util.SortedMap ;
import java.util.TreeMap ;
import java.util.TreeSet ;
2014-07-19 14:27:20 -04:00
import java.util.logging.Level ;
import java.util.logging.Logger ;
2014-04-01 08:36:34 -04:00
import java.util.regex.Matcher ;
import java.util.regex.Pattern ;
import com.ibm.icu.text.CharsetDetector ;
import com.ibm.icu.text.CharsetMatch ;
public final class FileUtilities {
public static File moveRename ( File source , File destination ) throws IOException {
// resolve destination
destination = resolveDestination ( source , destination , true ) ;
if ( source . isDirectory ( ) ) {
// move folder
org . apache . commons . io . FileUtils . moveDirectory ( source , destination ) ;
2014-07-19 14:27:20 -04:00
return destination ;
}
// on Windows, use ATOMIC_MOVE which allows us to rename files even if only lower/upper-case changes (without ATOMIC_MOVE the operation would be ignored)
// but ATOMIC_MOVE can only work for files on the same drive, if that is not the case there is no point trying move with ATOMIC_MOVE
2014-07-19 14:31:19 -04:00
if ( File . separator . equals ( " \\ " ) & & source . equals ( destination ) ) {
2014-04-01 08:36:34 -04:00
try {
2014-07-19 14:27:20 -04:00
return Files . move ( source . toPath ( ) , destination . toPath ( ) , StandardCopyOption . ATOMIC_MOVE ) . toFile ( ) ;
2014-04-01 08:36:34 -04:00
} catch ( AtomicMoveNotSupportedException e ) {
2014-07-19 14:27:20 -04:00
Logger . getLogger ( FileUtilities . class . getName ( ) ) . log ( Level . WARNING , e . toString ( ) ) ;
2014-04-01 08:36:34 -04:00
}
}
2014-07-19 14:27:20 -04:00
// Linux and Mac OS X
return Files . move ( source . toPath ( ) , destination . toPath ( ) , StandardCopyOption . REPLACE_EXISTING ) . toFile ( ) ;
2014-04-01 08:36:34 -04:00
}
public static File copyAs ( File source , File destination ) throws IOException {
// resolve destination
destination = resolveDestination ( source , destination , true ) ;
if ( source . isDirectory ( ) ) {
// copy folder
org . apache . commons . io . FileUtils . copyDirectory ( source , destination ) ;
2014-07-19 14:27:20 -04:00
return destination ;
2014-04-01 08:36:34 -04:00
}
2014-07-19 14:27:20 -04:00
// copy file
return Files . copy ( source . toPath ( ) , destination . toPath ( ) , StandardCopyOption . REPLACE_EXISTING ) . toFile ( ) ;
2014-04-01 08:36:34 -04:00
}
2014-08-28 15:23:28 -04:00
public static File resolveDestination ( File source , File destination ) {
// resolve destination
if ( ! destination . isAbsolute ( ) ) {
// same folder, different name
destination = new File ( source . getParentFile ( ) , destination . getPath ( ) ) ;
}
return destination ;
}
2014-04-01 08:36:34 -04:00
public static File resolveDestination ( File source , File destination , boolean mkdirs ) throws IOException {
// resolve destination
if ( ! destination . isAbsolute ( ) ) {
// same folder, different name
destination = new File ( source . getParentFile ( ) , destination . getPath ( ) ) ;
}
// create parent folder if necessary
2015-03-23 04:22:06 -04:00
if ( mkdirs ) {
// make sure that the folder structure is created, and throw exception if the folder structure can't be created
Files . createDirectories ( destination . getParentFile ( ) . toPath ( ) ) ;
2014-04-01 08:36:34 -04:00
}
return destination ;
}
public static File createRelativeSymlink ( File link , File target , boolean relativize ) throws IOException {
if ( relativize ) {
// make sure we're working with the full path
link = link . getCanonicalFile ( ) ;
target = target . getCanonicalFile ( ) ;
try {
target = link . getParentFile ( ) . toPath ( ) . relativize ( target . toPath ( ) ) . toFile ( ) ;
} catch ( Throwable e ) {
// unable to relativize link target
}
}
// create symlink via NIO.2
2014-07-15 08:57:07 -04:00
return Files . createSymbolicLink ( link . toPath ( ) , target . toPath ( ) ) . toFile ( ) ;
}
public static File createHardLinkStructure ( File link , File target ) throws IOException {
if ( target . isFile ( ) ) {
return Files . createLink ( link . toPath ( ) , target . toPath ( ) ) . toFile ( ) ;
}
// if the target is a directory, recreate the structure and hardlink each file item
final Path source = target . getCanonicalFile ( ) . toPath ( ) ;
final Path destination = link . getCanonicalFile ( ) . toPath ( ) ;
Files . walkFileTree ( source , EnumSet . of ( FileVisitOption . FOLLOW_LINKS ) , FILE_WALK_MAX_DEPTH , new SimpleFileVisitor < Path > ( ) {
@Override
public FileVisitResult visitFile ( Path file , BasicFileAttributes attrs ) throws IOException {
Path linkFile = destination . resolve ( source . relativize ( file ) ) ;
Files . createDirectories ( linkFile . getParent ( ) ) ;
Files . createLink ( linkFile , file ) ;
return FileVisitResult . CONTINUE ;
}
} ) ;
return destination . toFile ( ) ;
2014-04-01 08:36:34 -04:00
}
public static boolean delete ( File file ) {
// delete files or files
return org . apache . commons . io . FileUtils . deleteQuietly ( file ) ;
}
2015-04-11 14:31:29 -04:00
public static void createFolders ( File folder ) throws IOException {
if ( ! folder . isDirectory ( ) ) {
Files . createDirectories ( folder . toPath ( ) ) ;
}
}
2015-03-25 01:36:29 -04:00
public static void createFileIfNotExists ( File file ) throws IOException {
if ( ! file . isFile ( ) ) {
// create parent folder structure if necessary & create file
Files . createDirectories ( file . getParentFile ( ) . toPath ( ) ) ;
2015-04-11 14:31:29 -04:00
Files . createFile ( file . toPath ( ) ) ;
2015-03-25 01:18:35 -04:00
}
}
2014-04-01 08:36:34 -04:00
public static byte [ ] readFile ( File source ) throws IOException {
2016-01-31 11:13:04 -05:00
long size = source . length ( ) ;
if ( size < 0 | | size > Integer . MAX_VALUE ) {
throw new IllegalArgumentException ( " Unable to read file: " + source ) ;
}
2014-04-01 08:36:34 -04:00
2016-01-31 11:13:04 -05:00
try ( InputStream in = new FileInputStream ( source ) ) {
2014-04-01 08:36:34 -04:00
byte [ ] data = new byte [ ( int ) size ] ;
int position = 0 ;
int read = 0 ;
while ( position < data . length & & ( read = in . read ( data , position , data . length - position ) ) > = 0 ) {
position + = read ;
}
return data ;
}
}
2015-12-06 14:33:12 -05:00
public static String readTextFile ( File file ) throws IOException {
try ( Reader reader = new UnicodeReader ( new BufferedInputStream ( new FileInputStream ( file ) , BUFFER_SIZE ) , false , StandardCharsets . UTF_8 ) ) {
StringBuilder text = new StringBuilder ( ) ;
char [ ] buffer = new char [ BUFFER_SIZE ] ;
2014-04-01 08:36:34 -04:00
2015-12-06 14:33:12 -05:00
int read = 0 ;
while ( ( read = reader . read ( buffer ) ) > = 0 ) {
text . append ( buffer , 0 , read ) ;
}
2014-04-01 08:36:34 -04:00
2015-12-06 14:33:12 -05:00
return text . toString ( ) ;
}
2014-04-01 08:36:34 -04:00
}
2014-04-17 15:52:23 -04:00
public static File writeFile ( ByteBuffer data , File destination ) throws IOException {
2014-11-06 23:54:21 -05:00
try ( FileChannel channel = FileChannel . open ( destination . toPath ( ) , StandardOpenOption . CREATE , StandardOpenOption . TRUNCATE_EXISTING , StandardOpenOption . WRITE ) ) {
2014-04-17 15:52:23 -04:00
channel . write ( data ) ;
2014-04-01 08:36:34 -04:00
}
2014-04-17 15:52:23 -04:00
return destination ;
2014-04-01 08:36:34 -04:00
}
2016-03-05 16:06:20 -05:00
public static List < String [ ] > readCSV ( InputStream source , String charsetName , String pattern ) {
try ( Scanner scanner = new Scanner ( source , charsetName ) ) {
Pattern separator = Pattern . compile ( pattern ) ;
List < String [ ] > rows = new ArrayList < String [ ] > ( 65536 ) ;
2014-04-01 08:36:34 -04:00
2016-03-05 16:06:20 -05:00
while ( scanner . hasNextLine ( ) ) {
rows . add ( separator . split ( scanner . nextLine ( ) ) ) ;
}
2014-04-01 08:36:34 -04:00
2016-03-05 16:06:20 -05:00
return rows ;
}
2014-04-01 08:36:34 -04:00
}
public static Reader createTextReader ( File file ) throws IOException {
CharsetDetector detector = new CharsetDetector ( ) ;
detector . setDeclaredEncoding ( " UTF-8 " ) ; // small boost for UTF-8 as default encoding
detector . setText ( new BufferedInputStream ( new FileInputStream ( file ) ) ) ;
CharsetMatch charset = detector . detect ( ) ;
if ( charset ! = null )
return charset . getReader ( ) ;
// assume UTF-8 by default
2015-12-06 14:33:12 -05:00
return new InputStreamReader ( new FileInputStream ( file ) , StandardCharsets . UTF_8 ) ;
2014-04-01 08:36:34 -04:00
}
public static String getText ( ByteBuffer data ) throws IOException {
CharsetDetector detector = new CharsetDetector ( ) ;
detector . setDeclaredEncoding ( " UTF-8 " ) ; // small boost for UTF-8 as default encoding
detector . setText ( new ByteBufferInputStream ( data ) ) ;
CharsetMatch charset = detector . detect ( ) ;
if ( charset ! = null ) {
try {
return charset . getString ( ) ;
} catch ( RuntimeException e ) {
throw new IOException ( " Failed to read text " , e ) ;
}
}
// assume UTF-8 by default
return Charset . forName ( " UTF-8 " ) . decode ( data ) . toString ( ) ;
}
/ * *
* Pattern used for matching file extensions .
2015-07-25 18:47:19 -04:00
*
2014-04-01 08:36:34 -04:00
* e . g . " file.txt " - > match " txt " , " .hidden " - > no match
* /
public static final Pattern EXTENSION = Pattern . compile ( " (?<=.[.]) \\ p{Alnum}+$ " ) ;
public static final String UNC_PREFIX = " \\ \\ " ;
public static String getExtension ( File file ) {
if ( file . isDirectory ( ) )
return null ;
return getExtension ( file . getName ( ) ) ;
}
public static String getExtension ( String name ) {
Matcher matcher = EXTENSION . matcher ( name ) ;
if ( matcher . find ( ) ) {
// extension without leading '.'
return matcher . group ( ) ;
}
// no extension
return null ;
}
public static boolean hasExtension ( File file , String . . . extensions ) {
// avoid native call for speed, if possible
return hasExtension ( file . getName ( ) , extensions ) & & ! file . isDirectory ( ) ;
}
public static boolean hasExtension ( String filename , String . . . extensions ) {
for ( String it : extensions ) {
if ( filename . length ( ) - it . length ( ) > = 2 & & filename . charAt ( filename . length ( ) - it . length ( ) - 1 ) = = '.' ) {
String tail = filename . substring ( filename . length ( ) - it . length ( ) , filename . length ( ) ) ;
if ( tail . equalsIgnoreCase ( it ) ) {
return true ;
}
}
}
return false ;
}
public static String getNameWithoutExtension ( String name ) {
Matcher matcher = EXTENSION . matcher ( name ) ;
if ( matcher . find ( ) ) {
return name . substring ( 0 , matcher . start ( ) - 1 ) ;
}
// no extension, return given name
return name ;
}
public static String getName ( File file ) {
if ( file . getName ( ) . isEmpty ( ) | | UNC_PREFIX . equals ( file . getParent ( ) ) )
return getFolderName ( file ) ;
return getNameWithoutExtension ( file . getName ( ) ) ;
}
public static String getFolderName ( File file ) {
if ( UNC_PREFIX . equals ( file . getParent ( ) ) )
return file . toString ( ) ;
if ( file . getName ( ) . length ( ) > 0 )
return file . getName ( ) ;
// file might be a drive (only has a path, but no name)
return replacePathSeparators ( file . toString ( ) , " " ) ;
}
public static boolean isDerived ( File derivate , File prime ) {
return isDerived ( getName ( derivate ) , prime ) ;
}
public static boolean isDerived ( String derivate , File prime ) {
String base = getName ( prime ) . trim ( ) . toLowerCase ( ) ;
derivate = derivate . trim ( ) . toLowerCase ( ) ;
return derivate . startsWith ( base ) ;
}
public static boolean isDerivedByExtension ( File derivate , File prime ) {
return isDerivedByExtension ( getName ( derivate ) , prime ) ;
}
public static boolean isDerivedByExtension ( String derivate , File prime ) {
String base = getName ( prime ) . trim ( ) . toLowerCase ( ) ;
derivate = derivate . trim ( ) . toLowerCase ( ) ;
if ( derivate . equals ( base ) )
return true ;
while ( derivate . length ( ) > base . length ( ) & & getExtension ( derivate ) ! = null ) {
derivate = getNameWithoutExtension ( derivate ) ;
if ( derivate . equals ( base ) )
return true ;
}
return false ;
}
public static boolean containsOnly ( Collection < File > files , FileFilter filter ) {
if ( files . isEmpty ( ) ) {
return false ;
}
for ( File file : files ) {
if ( ! filter . accept ( file ) )
return false ;
}
return true ;
}
public static List < File > sortByUniquePath ( Collection < File > files ) {
// sort by unique lower-case paths
TreeSet < File > sortedSet = new TreeSet < File > ( CASE_INSENSITIVE_PATH ) ;
sortedSet . addAll ( files ) ;
return new ArrayList < File > ( sortedSet ) ;
}
public static List < File > filter ( Iterable < File > files , FileFilter . . . filters ) {
List < File > accepted = new ArrayList < File > ( ) ;
for ( File file : files ) {
for ( FileFilter filter : filters ) {
if ( filter . accept ( file ) ) {
accepted . add ( file ) ;
break ;
}
}
}
return accepted ;
}
public static FileFilter not ( FileFilter filter ) {
return new NotFileFilter ( filter ) ;
}
public static List < File > listPath ( File file ) {
return listPathTail ( file , Integer . MAX_VALUE , false ) ;
}
public static List < File > listPathTail ( File file , int tailSize , boolean reverse ) {
LinkedList < File > nodes = new LinkedList < File > ( ) ;
File node = file ;
for ( int i = 0 ; node ! = null & & i < tailSize & & ! UNC_PREFIX . equals ( node . toString ( ) ) ; i + + , node = node . getParentFile ( ) ) {
if ( reverse ) {
nodes . addLast ( node ) ;
} else {
nodes . addFirst ( node ) ;
}
}
return nodes ;
}
public static File getRelativePathTail ( File file , int tailSize ) {
File f = null ;
for ( File it : listPathTail ( file , tailSize , false ) ) {
if ( it . getParentFile ( ) ! = null ) {
f = new File ( f , it . getName ( ) ) ;
}
}
return f ;
}
2014-07-28 06:00:27 -04:00
public static List < File > getFileSystemRoots ( ) {
File [ ] roots = File . listRoots ( ) ;
// roots array may be null if folder permissions do not allow listing of files
if ( roots = = null ) {
roots = new File [ 0 ] ;
}
return asList ( roots ) ;
}
public static List < File > getChildren ( File folder ) {
2014-11-04 05:06:45 -05:00
return getChildren ( folder , null , null ) ;
2014-07-28 06:00:27 -04:00
}
public static List < File > getChildren ( File folder , FileFilter filter ) {
2014-11-04 05:06:45 -05:00
return getChildren ( folder , filter , null ) ;
}
public static List < File > getChildren ( File folder , FileFilter filter , Comparator < File > sorter ) {
File [ ] files = filter = = null ? folder . listFiles ( ) : folder . listFiles ( filter ) ;
2014-06-23 11:09:43 -04:00
// children array may be null if folder permissions do not allow listing of files
if ( files = = null ) {
2014-07-28 06:00:27 -04:00
files = new File [ 0 ] ;
2014-11-04 05:06:45 -05:00
} else if ( sorter ! = null ) {
sort ( files , sorter ) ;
2014-06-23 11:09:43 -04:00
}
return asList ( files ) ;
}
2014-07-15 08:57:07 -04:00
public static final int FILE_WALK_MAX_DEPTH = 32 ;
2014-04-16 13:23:25 -04:00
public static List < File > listFiles ( File . . . folders ) {
2014-04-17 11:35:33 -04:00
return listFiles ( asList ( folders ) ) ;
2014-04-16 13:23:25 -04:00
}
public static List < File > listFiles ( Iterable < File > folders ) {
2014-07-15 08:57:07 -04:00
return listFiles ( folders , FILE_WALK_MAX_DEPTH , false , true , false ) ;
2014-04-17 11:35:33 -04:00
}
public static List < File > listFolders ( Iterable < File > folders ) {
2014-07-15 08:57:07 -04:00
return listFiles ( folders , FILE_WALK_MAX_DEPTH , false , false , true ) ;
2014-04-16 13:23:25 -04:00
}
2014-04-17 11:35:33 -04:00
public static List < File > listFiles ( Iterable < File > folders , int maxDepth , boolean addHidden , boolean addFiles , boolean addFolders ) {
2014-04-01 08:36:34 -04:00
List < File > files = new ArrayList < File > ( ) ;
// collect files from directory tree
2014-04-17 11:35:33 -04:00
for ( File it : folders ) {
if ( ! addHidden & & it . isHidden ( ) ) // ignore hidden files
continue ;
if ( it . isDirectory ( ) ) {
if ( addFolders ) {
files . add ( it ) ;
}
listFiles ( it , files , 0 , maxDepth , addHidden , addFiles , addFolders ) ;
2016-01-18 00:30:52 -05:00
} else if ( addFiles & & it . isFile ( ) ) {
2014-04-17 11:35:33 -04:00
files . add ( it ) ;
}
2014-04-01 08:36:34 -04:00
}
return files ;
}
2014-04-17 11:35:33 -04:00
private static void listFiles ( File folder , List < File > files , int depth , int maxDepth , boolean addHidden , boolean addFiles , boolean addFolders ) {
2014-04-01 08:36:34 -04:00
if ( depth > maxDepth )
return ;
2014-06-23 11:09:43 -04:00
for ( File it : getChildren ( folder ) ) {
2014-04-17 11:35:33 -04:00
if ( ! addHidden & & it . isHidden ( ) ) // ignore hidden files
2014-04-01 08:36:34 -04:00
continue ;
2014-04-17 11:35:33 -04:00
if ( it . isDirectory ( ) ) {
if ( addFolders ) {
files . add ( it ) ;
}
listFiles ( it , files , depth + 1 , maxDepth , addHidden , addFiles , addFolders ) ;
} else if ( addFiles ) {
files . add ( it ) ;
2014-04-01 08:36:34 -04:00
}
}
}
public static SortedMap < File , List < File > > mapByFolder ( Iterable < File > files ) {
SortedMap < File , List < File > > map = new TreeMap < File , List < File > > ( ) ;
for ( File file : files ) {
File key = file . getParentFile ( ) ;
if ( key = = null ) {
throw new IllegalArgumentException ( " Parent is null: " + file ) ;
}
List < File > valueList = map . get ( key ) ;
if ( valueList = = null ) {
valueList = new ArrayList < File > ( ) ;
map . put ( key , valueList ) ;
}
valueList . add ( file ) ;
}
return map ;
}
public static Map < String , List < File > > mapByExtension ( Iterable < File > files ) {
Map < String , List < File > > map = new HashMap < String , List < File > > ( ) ;
for ( File file : files ) {
String key = getExtension ( file ) ;
if ( key ! = null ) {
key = key . toLowerCase ( ) ;
}
List < File > valueList = map . get ( key ) ;
if ( valueList = = null ) {
valueList = new ArrayList < File > ( ) ;
map . put ( key , valueList ) ;
}
valueList . add ( file ) ;
}
return map ;
}
/ * *
2014-06-04 22:48:40 -04:00
* Invalid file name characters : \ , / , : , * , ? , " , <, >, |, \ r, \ n and excessive characters
2014-04-01 08:36:34 -04:00
* /
2016-01-08 09:28:31 -05:00
public static final Pattern ILLEGAL_CHARACTERS = Pattern . compile ( " [ \\ \\ /:*? \" <>| \\ r \\ n]| \\ p{Cntrl}| \\ s+$|(?<=[^.])[.]+$|(?<=.{250})(.+)(?=[.] \\ p{Alnum}{3}$) " ) ;
2014-04-01 08:36:34 -04:00
/ * *
* Strip file name of invalid characters
2015-07-25 18:47:19 -04:00
*
2014-04-01 08:36:34 -04:00
* @param filename
* original filename
* @return valid file name stripped of invalid characters
* /
public static String validateFileName ( CharSequence filename ) {
// strip invalid characters from file name
return ILLEGAL_CHARACTERS . matcher ( filename ) . replaceAll ( " " ) . replaceAll ( " \\ s+ " , " " ) . trim ( ) ;
}
public static boolean isInvalidFileName ( CharSequence filename ) {
// check if file name contains any illegal characters
return ILLEGAL_CHARACTERS . matcher ( filename ) . find ( ) ;
}
public static File validateFileName ( File file ) {
// windows drives (e.g. c:, d:, etc.) are never invalid because name will be an empty string
if ( ! isInvalidFileName ( file . getName ( ) ) )
return file ;
// validate file name only
return new File ( file . getParentFile ( ) , validateFileName ( file . getName ( ) ) ) ;
}
public static File validateFilePath ( File path ) {
Iterator < File > nodes = listPath ( path ) . iterator ( ) ;
// initialize with root node, keep original root object if possible (so we don't loose the drive on windows)
File validatedPath = validateFileName ( nodes . next ( ) ) ;
// validate the rest of the path
while ( nodes . hasNext ( ) ) {
validatedPath = new File ( validatedPath , validateFileName ( nodes . next ( ) . getName ( ) ) ) ;
}
return validatedPath ;
}
public static boolean isInvalidFilePath ( File path ) {
// check if file name contains any illegal characters
for ( File node = path ; node ! = null ; node = node . getParentFile ( ) ) {
if ( isInvalidFileName ( node . getName ( ) ) )
return true ;
}
return false ;
}
public static String normalizePathSeparators ( String path ) {
// special handling for UNC paths
if ( path . startsWith ( UNC_PREFIX ) & & path . length ( ) > 2 ) {
return UNC_PREFIX + path . substring ( 2 ) . replace ( '\\' , '/' ) ;
}
return path . replace ( '\\' , '/' ) ;
}
2016-02-21 23:34:08 -05:00
private static final Pattern PATH_SEPARATORS = Pattern . compile ( " \\ s*[ \\ \\ /]+ \\ s* " ) ;
2014-04-01 08:36:34 -04:00
public static String replacePathSeparators ( CharSequence path ) {
return replacePathSeparators ( path , " " ) ;
}
public static String replacePathSeparators ( CharSequence path , String replacement ) {
2016-02-21 23:34:08 -05:00
return PATH_SEPARATORS . matcher ( path ) . replaceAll ( replacement ) ;
2014-04-01 08:36:34 -04:00
}
2015-05-09 02:38:47 -04:00
public static String md5 ( String string ) {
return md5 ( StandardCharsets . UTF_8 . encode ( string ) ) ;
}
2015-05-08 04:20:20 -04:00
public static String md5 ( byte [ ] data ) {
return md5 ( ByteBuffer . wrap ( data ) ) ;
}
public static String md5 ( ByteBuffer data ) {
try {
MessageDigest hash = MessageDigest . getInstance ( " MD5 " ) ;
hash . update ( data ) ;
return String . format ( " %032x " , new BigInteger ( 1 , hash . digest ( ) ) ) ; // as hex string
} catch ( NoSuchAlgorithmException e ) {
throw new RuntimeException ( e ) ;
}
}
2014-04-16 13:23:25 -04:00
public static List < File > asFileList ( Object . . . paths ) {
List < File > files = new ArrayList < File > ( paths . length ) ;
for ( Object it : paths ) {
if ( it instanceof CharSequence ) {
files . add ( new File ( it . toString ( ) ) ) ;
} else if ( it instanceof File ) {
files . add ( ( File ) it ) ;
} else if ( it instanceof Path ) {
files . add ( ( ( Path ) it ) . toFile ( ) ) ;
2014-04-17 15:52:23 -04:00
} else if ( it instanceof Collection < ? > ) {
2014-04-18 15:41:39 -04:00
files . addAll ( asFileList ( ( ( Collection < ? > ) it ) . toArray ( ) ) ) ; // flatten object structure
2014-04-16 13:23:25 -04:00
}
}
return files ;
}
2014-08-17 02:56:48 -04:00
public static final int BUFFER_SIZE = 64 * 1024 ;
2014-04-01 08:36:34 -04:00
public static final long KILO = 1024 ;
public static final long MEGA = 1024 * KILO ;
public static final long GIGA = 1024 * MEGA ;
public static String formatSize ( long size ) {
2014-08-05 09:07:38 -04:00
if ( size > = GIGA )
return String . format ( " %,d GB " , size / GIGA ) ;
else if ( size > = MEGA )
2014-04-01 08:36:34 -04:00
return String . format ( " %,d MB " , size / MEGA ) ;
else if ( size > = KILO )
return String . format ( " %,d KB " , size / KILO ) ;
else
return String . format ( " %,d Byte " , size ) ;
}
public static final FileFilter FOLDERS = new FileFilter ( ) {
@Override
public boolean accept ( File file ) {
return file . isDirectory ( ) ;
}
} ;
public static final FileFilter FILES = new FileFilter ( ) {
@Override
public boolean accept ( File file ) {
return file . isFile ( ) ;
}
} ;
public static final FileFilter TEMPORARY = new FileFilter ( ) {
private final String tmpdir = System . getProperty ( " java.io.tmpdir " ) ;
@Override
public boolean accept ( File file ) {
return file . getAbsolutePath ( ) . startsWith ( tmpdir ) ;
}
} ;
2014-11-04 05:06:45 -05:00
public static final FileFilter NOT_HIDDEN = new FileFilter ( ) {
@Override
public boolean accept ( File file ) {
return ! file . isHidden ( ) ;
}
} ;
2014-04-01 08:36:34 -04:00
public static class ParentFilter implements FileFilter {
private final File folder ;
public ParentFilter ( File folder ) {
this . folder = folder ;
}
@Override
public boolean accept ( File file ) {
return listPath ( file ) . contains ( folder ) ;
}
}
2014-07-28 15:20:55 -04:00
public static class ExtensionFileFilter implements FileFilter , FilenameFilter {
2014-04-01 08:36:34 -04:00
2014-11-07 08:26:54 -05:00
public static final List < String > WILDCARD = singletonList ( " * " ) ;
2014-04-01 08:36:34 -04:00
private final String [ ] extensions ;
public ExtensionFileFilter ( String . . . extensions ) {
2014-11-07 11:05:56 -05:00
this . extensions = extensions . clone ( ) ;
2014-04-01 08:36:34 -04:00
}
public ExtensionFileFilter ( Collection < String > extensions ) {
this . extensions = extensions . toArray ( new String [ 0 ] ) ;
}
2014-07-28 15:20:55 -04:00
@Override
public boolean accept ( File dir , String name ) {
2014-11-07 11:05:56 -05:00
return accept ( name ) ;
2014-07-28 15:20:55 -04:00
}
2014-04-01 08:36:34 -04:00
@Override
public boolean accept ( File file ) {
2014-11-07 11:05:56 -05:00
return accept ( file . getName ( ) ) ;
2014-04-01 08:36:34 -04:00
}
public boolean accept ( String name ) {
2014-11-07 11:05:56 -05:00
return acceptAny ( ) | | hasExtension ( name , extensions ) ;
2014-04-01 08:36:34 -04:00
}
2014-11-07 08:26:54 -05:00
public boolean acceptAny ( ) {
return extensions . length = = 1 & & WILDCARD . get ( 0 ) . equals ( extensions [ 0 ] ) ;
}
2014-04-01 08:36:34 -04:00
public boolean acceptExtension ( String extension ) {
2014-11-07 08:26:54 -05:00
if ( acceptAny ( ) ) {
return true ;
}
2014-04-01 08:36:34 -04:00
for ( String other : extensions ) {
2014-11-07 08:26:54 -05:00
if ( other . equalsIgnoreCase ( extension ) ) {
2014-04-01 08:36:34 -04:00
return true ;
2014-11-07 08:26:54 -05:00
}
2014-04-01 08:36:34 -04:00
}
return false ;
}
public String extension ( ) {
return extensions [ 0 ] ;
}
public String [ ] extensions ( ) {
return extensions . clone ( ) ;
}
2014-07-28 15:20:55 -04:00
@Override
public String toString ( ) {
StringBuilder s = new StringBuilder ( ) ;
for ( String it : extensions ) {
if ( s . length ( ) > 0 ) {
s . append ( " , " ) ;
}
s . append ( " *. " ) . append ( it ) ;
}
return s . toString ( ) ;
}
2014-04-01 08:36:34 -04:00
}
public static class RegexFileFilter implements FileFilter , FilenameFilter {
private final Pattern pattern ;
public RegexFileFilter ( Pattern pattern ) {
this . pattern = pattern ;
}
@Override
public boolean accept ( File dir , String name ) {
return pattern . matcher ( name ) . find ( ) ;
}
@Override
public boolean accept ( File file ) {
return accept ( file . getParentFile ( ) , file . getName ( ) ) ;
}
}
public static class NotFileFilter implements FileFilter {
public FileFilter filter ;
public NotFileFilter ( FileFilter filter ) {
this . filter = filter ;
}
@Override
public boolean accept ( File file ) {
return ! filter . accept ( file ) ;
}
}
public static final Comparator < File > CASE_INSENSITIVE_PATH = new Comparator < File > ( ) {
@Override
public int compare ( File o1 , File o2 ) {
return o1 . getPath ( ) . compareToIgnoreCase ( o2 . getPath ( ) ) ;
}
} ;
/ * *
* Dummy constructor to prevent instantiation .
* /
private FileUtilities ( ) {
throw new UnsupportedOperationException ( ) ;
}
}