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

org.tinygroup.commons.tools.FileUtil Maven / Gradle / Ivy

There is a newer version: 2.2.3
Show newest version
/**
 *  Copyright (c) 1997-2013, www.tinygroup.org ([email protected]).
 *
 *  Licensed under the GPL, Version 3.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.gnu.org/licenses/gpl.html
 *
 *  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 org.tinygroup.commons.tools;


import org.tinygroup.commons.exceptions.IllegalPathException;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.tinygroup.commons.tools.StringUtil.*;

/**
 * 操作文件的工具类
 * 
 * @author renhui
 * 
 */
public class FileUtil {

	public static String readFileContent(File file, String encoding)
			throws Exception {
		FileInputStream fis = new FileInputStream(file);
		return readStreamContent(fis, encoding);
	}

	public static String readStreamContent(InputStream stream, String encoding)
			throws Exception {
		StringBuilder content = new StringBuilder("");
		byte[] bytearray = new byte[stream.available()];
		int bytetotal = stream.available();
		while (stream.read(bytearray, 0, bytetotal) != -1) {
			String temp = new String(bytearray, 0, bytetotal, encoding);
			content.append(temp);
		}
		return content.toString();
	}
	

    // ==========================================================================
    // 规格化路径。
    // ==========================================================================

    /**
     * 规格化绝对路径。
     * 

* 该方法返回以“/”开始的绝对路径。转换规则如下: *

*
    *
  1. 路径为空,则返回""
  2. *
  3. 将所有backslash("\\")转化成slash("/")。
  4. *
  5. 去除重复的"/"或"\\"。
  6. *
  7. 去除".",如果发现"..",则向上朔一级目录。
  8. *
  9. 保留路径末尾的"/"(如果有的话,除了空路径)。
  10. *
  11. 对于绝对路径,如果".."上朔的路径超过了根目录,则看作非法路径,抛出异常。
  12. *
* * @param path 要规格化的路径 * @return 规格化后的路径 * @throws IllegalPathException 如果路径非法 */ public static String normalizeAbsolutePath(String path) throws IllegalPathException { return normalizePath(path, true, false, false); } /** * 规格化绝对路径。 *

* 该方法返回以“/”开始的绝对路径。转换规则如下: *

*
    *
  1. 路径为空,则返回""
  2. *
  3. 将所有backslash("\\")转化成slash("/")。
  4. *
  5. 去除重复的"/"或"\\"。
  6. *
  7. 去除".",如果发现"..",则向上朔一级目录。
  8. *
  9. 保留路径末尾的"/"(如果有的话,除了空路径和强制指定removeTrailingSlash==true)。
  10. *
  11. 对于绝对路径,如果".."上朔的路径超过了根目录,则看作非法路径,抛出异常。
  12. *
* * @param path 要规格化的路径 * @param removeTrailingSlash 是否强制移除末尾的"/" * @return 规格化后的路径 * @throws IllegalPathException 如果路径非法 */ public static String normalizeAbsolutePath(String path, boolean removeTrailingSlash) throws IllegalPathException { return normalizePath(path, true, false, removeTrailingSlash); } /** * 规格化相对路径。 *

* 该方法返回不以“/”开始的相对路径。转换规则如下: *

*
    *
  1. 路径为空,则返回""
  2. *
  3. 将所有backslash("\\")转化成slash("/")。
  4. *
  5. 去除重复的"/"或"\\"。
  6. *
  7. 去除".",如果发现"..",则向上朔一级目录。
  8. *
  9. 空相对路径返回""。
  10. *
  11. 保留路径末尾的"/"(如果有的话,除了空路径)。
  12. *
* * @param path 要规格化的路径 * @return 规格化后的路径 * @throws IllegalPathException 如果路径非法 */ public static String normalizeRelativePath(String path) throws IllegalPathException { return normalizePath(path, false, true, false); } /** * 规格化相对路径。 *

* 该方法返回不以“/”开始的相对路径。转换规则如下: *

*
    *
  1. 路径为空,则返回""
  2. *
  3. 将所有backslash("\\")转化成slash("/")。
  4. *
  5. 去除重复的"/"或"\\"。
  6. *
  7. 去除".",如果发现"..",则向上朔一级目录。
  8. *
  9. 空相对路径返回""。
  10. *
  11. 保留路径末尾的"/"(如果有的话,除了空路径和强制指定removeTrailingSlash==true)。
  12. *
* * @param path 要规格化的路径 * @param removeTrailingSlash 是否强制移除末尾的"/" * @return 规格化后的路径 * @throws IllegalPathException 如果路径非法 */ public static String normalizeRelativePath(String path, boolean removeTrailingSlash) throws IllegalPathException { return normalizePath(path, false, true, removeTrailingSlash); } /** * 规格化路径。规则如下: *
    *
  1. 路径为空,则返回""
  2. *
  3. 将所有backslash("\\")转化成slash("/")。
  4. *
  5. 去除重复的"/"或"\\"。
  6. *
  7. 去除".",如果发现"..",则向上朔一级目录。
  8. *
  9. 空绝对路径返回"/",空相对路径返回""。
  10. *
  11. 保留路径末尾的"/"(如果有的话,除了空路径)。
  12. *
  13. 对于绝对路径,如果".."上朔的路径超过了根目录,则看作非法路径,抛出异常。
  14. *
* * @param path 要规格化的路径 * @return 规格化后的路径 * @throws IllegalPathException 如果路径非法 */ public static String normalizePath(String path) throws IllegalPathException { return normalizePath(path, false, false, false); } /** * 规格化路径。规则如下: *
    *
  1. 路径为空,则返回""
  2. *
  3. 将所有backslash("\\")转化成slash("/")。
  4. *
  5. 去除重复的"/"或"\\"。
  6. *
  7. 去除".",如果发现"..",则向上朔一级目录。
  8. *
  9. 空绝对路径返回"/",空相对路径返回""。
  10. *
  11. 保留路径末尾的"/"(如果有的话,除了空路径和强制指定removeTrailingSlash==true)。
  12. *
  13. 对于绝对路径,如果".."上朔的路径超过了根目录,则看作非法路径,抛出异常。
  14. *
* * @param path 要规格化的路径 * @param removeTrailingSlash 是否强制移除末尾的"/" * @return 规格化后的路径 * @throws IllegalPathException 如果路径非法 */ public static String normalizePath(String path, boolean removeTrailingSlash) throws IllegalPathException { return normalizePath(path, false, false, removeTrailingSlash); } private static String normalizePath(String path, boolean forceAbsolute, boolean forceRelative, boolean removeTrailingSlash) throws IllegalPathException { char[] pathChars = trimToEmpty(path).toCharArray(); int length = pathChars.length; // 检查绝对路径,以及path尾部的"/" boolean startsWithSlash = false; boolean endsWithSlash = false; if (length > 0) { char firstChar = pathChars[0]; char lastChar = pathChars[length - 1]; startsWithSlash = firstChar == '/' || firstChar == '\\'; endsWithSlash = lastChar == '/' || lastChar == '\\'; } StringBuilder buf = new StringBuilder(length); boolean isAbsolutePath = forceAbsolute || !forceRelative && startsWithSlash; int index = startsWithSlash ? 0 : -1; int level = 0; if (isAbsolutePath) { buf.append("/"); } while (index < length) { // 跳到第一个非slash字符,或末尾 index = indexOfSlash(pathChars, index + 1, false); if (index == length) { break; } // 取得下一个slash index,或末尾 int nextSlashIndex = indexOfSlash(pathChars, index, true); String element = new String(pathChars, index, nextSlashIndex - index); index = nextSlashIndex; // 忽略"." if (".".equals(element)) { continue; } // 回朔".." if ("..".equals(element)) { if (level == 0) { // 如果是绝对路径,../试图越过最上层目录,这是不可能的, // 抛出路径非法的异常。 if (isAbsolutePath) { throw new IllegalPathException(path); } else { buf.append("../"); } } else { buf.setLength(pathChars[--level]); } continue; } // 添加到path pathChars[level++] = (char) buf.length(); // 将已经读过的chars空间用于记录指定level的index buf.append(element).append('/'); } // 除去最后的"/" if (buf.length() > 0) { if (!endsWithSlash || removeTrailingSlash) { buf.setLength(buf.length() - 1); } } return buf.toString(); } private static int indexOfSlash(char[] chars, int beginIndex, boolean slash) { int i = beginIndex; for (; i < chars.length; i++) { char ch = chars[i]; if (slash) { if (ch == '/' || ch == '\\') { break; // if a slash } } else { if (ch != '/' && ch != '\\') { break; // if not a slash } } } return i; } // ========================================================================== // 取得基于指定basedir规格化路径。 // ========================================================================== /** * 如果指定路径已经是绝对路径,则规格化后直接返回之,否则取得基于指定basedir的规格化路径。 * * @param basedir 根目录,如果path为相对路径,表示基于此目录 * @param path 要检查的路径 * @return 规格化的绝对路径 * @throws IllegalPathException 如果路径非法 */ public static String getAbsolutePathBasedOn(String basedir, String path) throws IllegalPathException { // 如果path为绝对路径,则规格化后返回 boolean isAbsolutePath = false; path = trimToEmpty(path); if (path.length() > 0) { char firstChar = path.charAt(0); isAbsolutePath = firstChar == '/' || firstChar == '\\'; } if (!isAbsolutePath) { // 如果path为相对路径,将它和basedir合并。 if (path.length() > 0) { path = trimToEmpty(basedir) + "/" + path; } else { path = trimToEmpty(basedir); } } return normalizeAbsolutePath(path); } /** * 取得和系统相关的绝对路径。 * * @throws IllegalPathException 如果basedir不是绝对路径 */ public static String getSystemDependentAbsolutePathBasedOn(String basedir, String path) { path = trimToEmpty(path); boolean endsWithSlash = path.endsWith("/") || path.endsWith("\\"); File pathFile = new File(path); if (pathFile.isAbsolute()) { // 如果path已经是绝对路径了,则直接返回之。 path = pathFile.getAbsolutePath(); } else { // 否则以basedir为基本路径。 // 下面确保basedir本身为绝对路径。 basedir = trimToEmpty(basedir); File baseFile = new File(basedir); if (baseFile.isAbsolute()) { path = new File(baseFile, path).getAbsolutePath(); } else { throw new IllegalPathException("Basedir is not absolute path: " + basedir); } } if (endsWithSlash) { path = path + '/'; } return normalizePath(path); } // ========================================================================== // 取得相对于指定basedir相对路径。 // ========================================================================== /** * 取得相对于指定根目录的相对路径。 * * @param basedir 根目录 * @param path 要计算的路径 * @return 如果pathbasedir是兼容的,则返回相对于 * basedir的相对路径,否则返回path本身。 * @throws IllegalPathException 如果路径非法 */ public static String getRelativePath(String basedir, String path) throws IllegalPathException { // 取得规格化的basedir,确保其为绝对路径 basedir = normalizeAbsolutePath(basedir); // 取得规格化的path path = getAbsolutePathBasedOn(basedir, path); // 保留path尾部的"/" boolean endsWithSlash = path.endsWith("/"); // 按"/"分隔basedir和path String[] baseParts = StringUtil.split(basedir, '/'); String[] parts = StringUtil.split(path, '/'); StringBuilder buf = new StringBuilder(); int i = 0; while (i < baseParts.length && i < parts.length && baseParts[i].equals(parts[i])) { i++; } if (i < baseParts.length && i < parts.length) { for (int j = i; j < baseParts.length; j++) { buf.append("..").append('/'); } } for (; i < parts.length; i++) { buf.append(parts[i]); if (i < parts.length - 1) { buf.append('/'); } } if (endsWithSlash && buf.length() > 0 && buf.charAt(buf.length() - 1) != '/') { buf.append('/'); } return buf.toString(); } // ========================================================================== // 取得文件名后缀。 // ========================================================================== /** * 取得文件路径的后缀。 *
    *
  • 未指定文件名 - 返回null
  • *
  • 文件名没有后缀 - 返回null
  • *
*/ public static String getExtension(String fileName) { return getExtension(fileName, null, false); } /** * 取得文件路径的后缀。 *
    *
  • 未指定文件名 - 返回null
  • *
  • 文件名没有后缀 - 返回null
  • *
*/ public static String getExtension(String fileName, boolean toLowerCase) { return getExtension(fileName, null, toLowerCase); } /** * 取得文件路径的后缀。 *
    *
  • 未指定文件名 - 返回null
  • *
  • 文件名没有后缀 - 返回指定字符串nullExt
  • *
*/ public static String getExtension(String fileName, String nullExt) { return getExtension(fileName, nullExt, false); } /** * 取得文件路径的后缀。 *
    *
  • 未指定文件名 - 返回null
  • *
  • 文件名没有后缀 - 返回指定字符串nullExt
  • *
*/ public static String getExtension(String fileName, String nullExt, boolean toLowerCase) { fileName = trimToNull(fileName); if (fileName == null) { return null; } fileName = fileName.replace('\\', '/'); fileName = fileName.substring(fileName.lastIndexOf("/") + 1); int index = fileName.lastIndexOf("."); String ext = null; if (index >= 0) { ext = trimToNull(fileName.substring(index + 1)); } if (ext == null) { return nullExt; } else { return toLowerCase ? ext.toLowerCase() : ext; } } /** * 取得指定路径的名称和后缀。 * * @param path 路径 * @return 路径和后缀 */ public static FileNameAndExtension getFileNameAndExtension(String path) { return getFileNameAndExtension(path, false); } /** * 取得指定路径的名称和后缀。 * * @param path 路径 * @return 路径和后缀 */ public static FileNameAndExtension getFileNameAndExtension(String path, boolean extensionToLowerCase) { path = StringUtil.trimToEmpty(path); String fileName = path; String extension = null; if (!StringUtil.isEmpty(path)) { // 如果找到后缀,则index >= 0,且extension != null(除非name以.结尾) int index = path.lastIndexOf('.'); if (index >= 0) { extension = StringUtil.trimToNull(StringUtil.substring(path, index + 1)); if (!StringUtil.containsNone(extension, "/\\")) { extension = null; index = -1; } } if (index >= 0) { fileName = StringUtil.substring(path, 0, index); } } return new FileNameAndExtension(fileName, extension, extensionToLowerCase); } /** * 规格化文件名后缀。 *
    *
  • 除去两边空白。
  • *
  • 转成小写。
  • *
  • 除去开头的“.”。
  • *
  • 对空白的后缀,返回null
  • *
*/ public static String normalizeExtension(String ext) { ext = trimToNull(ext); if (ext != null) { ext = ext.toLowerCase(); if (ext.startsWith(".")) { ext = trimToNull(ext.substring(1)); } } return ext; } private static final Pattern schemePrefixPattern = Pattern.compile( "(file:*[a-z]:)|(\\w+://.+?/)|((jar|zip):.+!/)|(\\w+:)", Pattern.CASE_INSENSITIVE); /** * 根据指定url和相对路径,计算出相对路径所对应的完整url。类似于URI.resolve() * 方法,然后后者不能正确处理jar类型的URL。 */ public static String resolve(String url, String relativePath) { url = trimToEmpty(url); Matcher m = schemePrefixPattern.matcher(url); int index = 0; if (m.find()) { index = m.end(); if (url.charAt(index - 1) == '/') { index--; } } return url.substring(0, index) + normalizeAbsolutePath(url.substring(index) + "/../" + relativePath); } public static void delete(File file) { if (file != null && file.exists()) { if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { File files[] = file.listFiles(); for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy