All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.aspectran.utils.FilenameUtils Maven / Gradle / Ivy

There is a newer version: 8.1.3
Show newest version
/*
 * Copyright (c) 2008-2024 The Aspectran Project
 *
 * 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.aspectran.utils;

import com.aspectran.utils.annotation.jsr305.NonNull;

import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.StringTokenizer;

import static com.aspectran.utils.PathUtils.REGULAR_FILE_SEPARATOR;
import static com.aspectran.utils.PathUtils.WINDOWS_FILE_SEPARATOR;

/**
 * Utility methods for General filename and filepath manipulation.
 * 

* This class defines six components within a filename * (example C:\dev\project\file.txt):

*
    *
  • the prefix - C:\
  • *
  • the path - dev\project\
  • *
  • the full path - C:\dev\project\
  • *
  • the name - file.txt
  • *
  • the base name - file
  • *
  • the extension - txt
  • *
*/ public abstract class FilenameUtils { private static final String NAME_SEPARATOR = "_"; private static final String EXTENSION_SEPARATOR = "."; private static final String EXTENSIONS_SEPARATORS = " ,;\t\n\r\f"; /** * Gets the name minus the path from a full filename. *

* This method will handle a file in either Unix or Windows format. * The text after the last forward or backslash is returned.

*
     * a/b/c.txt --> c.txt
     * a.txt     --> a.txt
     * a/b/c     --> c
     * a/b/c/    --> ""
     * 
*

* The output will be the same irrespective of the machine that the code is running on.

* @param filename the filename to query, null returns null * @return the name of the file without the path, or an empty string if none exists */ @NonNull public static String getName(String filename) { Assert.notNull(filename, "'filename' must not be null"); int index = indexOfLastSeparator(filename); return filename.substring(index + 1); } /** * Gets the base name, minus the full path and extension, from a full filename. *

* This method will handle a file in either Unix or Windows format. * The text after the last forward or backslash and before the last dot is returned.

*
     * a/b/c.txt --> c
     * a.txt     --> a
     * a/b/c     --> c
     * a/b/c/    --> ""
     * 
*

* The output will be the same irrespective of the machine that the code is running on.

* @param filename the filename to query, null returns null * @return the name of the file without the path, or an empty string if none exists */ public static String getBaseName(String filename) { return removeExtension(getName(filename)); } /** * Extract the file extension from the given filename. *

* This method returns the textual part of the filename after the last dot. * There must be no directory separator after the dot.

*
     * foo.txt      --> "txt"
     * a/b/c.jpg    --> "jpg"
     * a/b.txt/c    --> ""
     * a/b/c        --> ""
     * 
*

* The output will be the same irrespective of the machine that the code is running on.

* @param filename the filename to retrieve the extension of * @return the extension of the file or an empty string if none exists */ public static String getExtension(String filename) { Assert.notNull(filename, "'filename' must not be null"); int index = indexOfExtension(filename); if (index == -1) { return StringUtils.EMPTY; } else { return filename.substring(index + 1); } } /** * Removes the extension from a filename. *

* This method returns the textual part of the filename before the last dot. * There must be no directory separator after the dot.

*
     * foo.txt    --> foo
     * a\b\c.jpg  --> a\b\c
     * a\b\c      --> a\b\c
     * a.b\c      --> a.b\c
     * 
*

* The output will be the same irrespective of the machine that the code is running on.

* @param filename the filename to query, null returns null * @return the filename minus the extension */ public static String removeExtension(String filename) { Assert.notNull(filename, "'filename' must not be null"); int index = indexOfExtension(filename); if (index == -1) { return filename; } else { return filename.substring(0, index); } } /** * Returns the index of the last directory separator character. *

* This method will handle a file in either Unix or Windows format. * The position of the last forward or backslash is returned.

*

* The output will be the same irrespective of the machine that the code is running on.

* @param filename the filename to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there * is no such character */ public static int indexOfLastSeparator(String filename) { if (filename == null) { return -1; } int lastUnixPos = filename.lastIndexOf(REGULAR_FILE_SEPARATOR); int lastWindowsPos = filename.lastIndexOf(WINDOWS_FILE_SEPARATOR); return Math.max(lastUnixPos, lastWindowsPos); } /** * Returns the index of the last extension separator character, which is a dot. *

* This method also checks that there is no directory separator after the last dot. * To do this it uses {@link #indexOfLastSeparator(String)} which will * handle a file in either Unix or Windows format.

*

* The output will be the same irrespective of the machine that the code is running on.

* @param filename the filename to find the last path separator in, null returns -1 * @return the index of the last separator character, or -1 if there * is no such character */ public static int indexOfExtension(String filename) { if (filename == null) { return -1; } int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR); int lastSeparator = indexOfLastSeparator(filename); return (lastSeparator > extensionPos ? -1 : extensionPos); } /** * Gets the path from a full filename. * @param filename a full filename * @return the path */ public static String getFullPath(String filename) { if (filename == null) { return null; } int index = indexOfLastSeparator(filename); if (index < 0) { return StringUtils.EMPTY; } return filename.substring(0, index); } /** * Gets the path with end separator from a full filename. * @param filename a full filename * @return the path */ public static String getFullPathWithEndSeparator(String filename) { if (filename == null) { return null; } int index = indexOfLastSeparator(filename); if (index < 0) { return StringUtils.EMPTY; } return filename.substring(0, index + 1); } /** * Checks whether the extension of the filename is valid. * The extension check is case-sensitive on all platforms. * @param filename the filename to query, null returns false * @param allowedFileExtensions the allowed file extensions * @param deniedFileExtensions the denied file extensions * @return true if is valid file extension; false otherwise */ public static boolean isValidFileExtension(String filename, String allowedFileExtensions, String deniedFileExtensions) { if (filename == null) { return false; } String ext = getExtension(filename).toLowerCase(); if (allowedFileExtensions != null && !allowedFileExtensions.isEmpty()) { if (ext.isEmpty()) { return false; } StringTokenizer st = new StringTokenizer(allowedFileExtensions.toLowerCase(), EXTENSIONS_SEPARATORS); while (st.hasMoreTokens()) { String ext2 = st.nextToken(); if (ext.equals(ext2)) { return true; } } return false; } if (deniedFileExtensions != null && !deniedFileExtensions.isEmpty()) { if (ext.isEmpty()) { return true; } StringTokenizer st = new StringTokenizer(deniedFileExtensions.toLowerCase(), EXTENSIONS_SEPARATORS); while (st.hasMoreTokens()) { String ext2 = st.nextToken(); if (ext.equals(ext2)) { return false; } } return true; } return true; } /** * Returns a file name that does not overlap in the specified directory. * If a duplicate file name exists, it is returned by appending a number after the file name. * @param srcFile the file to seek * @return a unique file * @throws IOException if failed to obtain a unique file */ public static File generateUniqueFile(File srcFile) throws IOException { return generateUniqueFile(srcFile, EXTENSION_SEPARATOR); } /** * Returns a file name that does not overlap in the specified directory. * If a duplicate file name exists, it is returned by appending a number after the file name. * @param srcFile the file to seek * @param extSeparator the file extension separator * @return a unique file * @throws IOException if failed to obtain a unique file */ public static File generateUniqueFile(File srcFile, String extSeparator) throws IOException { Assert.notNull(srcFile, "'srcFile' must not be null"); String path = getFullPath(srcFile.getCanonicalPath()); String name = removeExtension(srcFile.getName()); String ext = getExtension(srcFile.getName()); String newName; if (StringUtils.hasLength(ext)) { newName = name + extSeparator + ext; } else { newName = name; } File destFile = new File(path, newName); int count = 0; while (destFile.exists()) { count++; if (ext != null && !ext.isEmpty()) { newName = name + NAME_SEPARATOR + count + extSeparator + ext; } else { newName = name + NAME_SEPARATOR + count; } destFile = new File(path, newName); } return (count == 0 ? srcFile : destFile); } /** * Creates and returns a system-safe file name without duplicates in the specified directory. * If there is a duplicate file name, a number is added after the file name and returned. * File extensions are separated by '.' character. *
     * ex) 1111111111_1.txt
     * 
* @param file the file to seek * @return a unique file * @throws IOException if failed to obtain a unique file */ public static File generateSafetyUniqueFile(File file) throws IOException { return generateSafetyUniqueFile(file, EXTENSION_SEPARATOR); } /** * Creates and returns a system-safe file name without duplicates in the specified directory. * If there is a duplicate file name, a number is added after the file name and returned. * If the file extension separator is specified as '_', the file name can be obtained * in the following format. *
     * ex) 1111111111_txt
     * 
* @param file the file to seek * @return a unique file * @param extSeparator the file extension separator * @throws IOException if failed to obtain a unique file */ public static File generateSafetyUniqueFile(@NonNull File file, String extSeparator) throws IOException { String path = file.getCanonicalPath(); String ext = getExtension(path); String prefix = Long.toString(System.currentTimeMillis()); Random rnd = new Random(); String suffix = Integer.toString(rnd.nextInt(9999)); String fullName; if (ext != null && !ext.isEmpty()) { fullName = prefix + NAME_SEPARATOR + suffix + extSeparator + ext; } else { fullName = prefix + NAME_SEPARATOR + suffix; } File file2 = new File(getFullPath(path), fullName); return generateUniqueFile(file2, NAME_SEPARATOR); } /** * Recovers the extension from a unique file name. * @param uniqueFilename a unique file name * @return file name with recovered extension */ @NonNull public static String recoverExtension(String uniqueFilename) { return StringUtils.replaceLast(uniqueFilename, NAME_SEPARATOR, EXTENSION_SEPARATOR); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy