📄 miscutilities.java
字号:
/* * MiscUtilities.java - Various miscallaneous utility functions * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1999, 2004 Slava Pestov * Portions copyright (C) 2000 Richard S. Hall * Portions copyright (C) 2001 Dirk Moebius * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */package org.gjt.sp.jedit;//{{{ Importsimport javax.swing.text.Segment;import javax.swing.JMenuItem;import java.lang.reflect.Method;import java.io.*;import java.net.MalformedURLException;import java.net.URL;import java.text.DecimalFormat;import java.util.*;import org.gjt.sp.jedit.io.*;import org.gjt.sp.util.Log;//}}}/** * Path name manipulation, string manipulation, and more.<p> * * The most frequently used members of this class are:<p> * * <b>Some path name methods:</b><p> * <ul> * <li>{@link #getFileName(String)}</li> * <li>{@link #getParentOfPath(String)}</li> * <li>{@link #constructPath(String,String)}</li> * </ul> * <b>String comparison:</b><p> * A {@link #compareStrings(String,String,boolean)} method that unlike * <function>String.compareTo()</function>, correctly recognizes and handles * embedded numbers.<p> * * This class also defines several inner classes for use with the * sorting features of the Java collections API: * * <ul> * <li>{@link MiscUtilities.StringCompare}</li> * <li>{@link MiscUtilities.StringICaseCompare}</li> * <li>{@link MiscUtilities.MenuItemCompare}</li> * </ul> * * For example, you might call:<p> * * <code>Arrays.sort(myListOfStrings, * new MiscUtilities.StringICaseCompare());</code> * * @author Slava Pestov * @author John Gellene (API documentation) * @version $Id: MiscUtilities.java,v 1.77 2004/08/21 01:49:05 spestov Exp $ */public class MiscUtilities{ /** * This encoding is not supported by Java, yet it is useful. * A UTF-8 file that begins with 0xEFBBBF. */ public static final String UTF_8_Y = "UTF-8Y"; //{{{ Path name methods //{{{ canonPath() method /** * Returns the canonical form of the specified path name. Currently * only expands a leading <code>~</code>. <b>For local path names * only.</b> * @param path The path name * @since jEdit 4.0pre2 */ public static String canonPath(String path) { if(path.length() == 0) return path; if(path.startsWith("file://")) path = path.substring("file://".length()); else if(path.startsWith("file:")) path = path.substring("file:".length()); else if(isURL(path)) return path; if(File.separatorChar == '\\') { // get rid of mixed paths on Windows path = path.replace('/','\\'); // also get rid of trailing spaces on Windows int trim = path.length(); while(path.charAt(trim - 1) == ' ') trim--; path = path.substring(0,trim); } else if(OperatingSystem.isMacOS()) { // do the same on OS X path = path.replace(':','/'); } if(path.startsWith("~" + File.separator)) { path = path.substring(2); String home = System.getProperty("user.home"); if(home.endsWith(File.separator)) return home + path; else return home + File.separator + path; } else if(path.equals("~")) return System.getProperty("user.home"); else return path; } //}}} //{{{ resolveSymlinks() method /** * Resolves any symbolic links in the path name specified * using <code>File.getCanonicalPath()</code>. <b>For local path * names only.</b> * @since jEdit 4.2pre1 */ public static String resolveSymlinks(String path) { if(isURL(path)) return path; // 2 aug 2003: OS/2 Java has a broken getCanonicalPath() if(OperatingSystem.isOS2()) return path; // 18 nov 2003: calling this on a drive letter on Windows causes // drive access if(OperatingSystem.isDOSDerived()) { if(path.length() == 2 || path.length() == 3) { if(path.charAt(1) == ':') return path; } } try { return new File(path).getCanonicalPath(); } catch(IOException io) { return path; } } //}}} //{{{ isAbsolutePath() method /** * Returns if the specified path name is an absolute path or URL. * @since jEdit 4.1pre11 */ public static boolean isAbsolutePath(String path) { if(isURL(path)) return true; else if(path.startsWith("~/") || path.startsWith("~" + File.separator) || path.equals("~")) return true; else if(OperatingSystem.isDOSDerived()) { if(path.length() == 2 && path.charAt(1) == ':') return true; if(path.length() > 2 && path.charAt(1) == ':' && (path.charAt(2) == '\\' || path.charAt(2) == '/')) return true; if(path.startsWith("\\\\") || path.startsWith("//")) return true; } // not sure if this is correct for OpenVMS. else if(OperatingSystem.isUnix() || OperatingSystem.isVMS()) { // nice and simple if(path.length() > 0 && path.charAt(0) == '/') return true; } return false; } //}}} //{{{ constructPath() method /** * Constructs an absolute path name from a directory and another * path name. This method is VFS-aware. * @param parent The directory * @param path The path name */ public static String constructPath(String parent, String path) { if(isAbsolutePath(path)) return canonPath(path); // have to handle this case specially on windows. // insert \ between, eg A: and myfile.txt. if(OperatingSystem.isDOSDerived()) { if(path.length() == 2 && path.charAt(1) == ':') return path; else if(path.length() > 2 && path.charAt(1) == ':' && path.charAt(2) != '\\') { path = path.substring(0,2) + '\\' + path.substring(2); return canonPath(path); } } String dd = ".." + File.separator; String d = "." + File.separator; if(parent == null) parent = System.getProperty("user.dir"); for(;;) { if(path.equals(".")) return parent; else if(path.equals("..")) return getParentOfPath(parent); else if(path.startsWith(dd) || path.startsWith("../")) { parent = getParentOfPath(parent); path = path.substring(3); } else if(path.startsWith(d) || path.startsWith("./")) path = path.substring(2); else break; } if(OperatingSystem.isDOSDerived() && !isURL(parent) && path.startsWith("\\")) parent = parent.substring(0,2); VFS vfs = VFSManager.getVFSForPath(parent); return canonPath(vfs.constructPath(parent,path)); } //}}} //{{{ constructPath() method /** * Constructs an absolute path name from three path components. * This method is VFS-aware. * @param parent The parent directory * @param path1 The first path * @param path2 The second path */ public static String constructPath(String parent, String path1, String path2) { return constructPath(constructPath(parent,path1),path2); } //}}} //{{{ concatPath() method /** * Like {@link #constructPath}, except <code>path</code> will be * appended to <code>parent</code> even if it is absolute. * <b>For local path names only.</b>. * * @param path * @param parent */ public static String concatPath(String parent, String path) { parent = canonPath(parent); path = canonPath(path); // Make all child paths relative. if (path.startsWith(File.separator)) path = path.substring(1); else if ((path.length() >= 3) && (path.charAt(1) == ':')) path = path.replace(':', File.separatorChar); if (parent == null) parent = System.getProperty("user.dir"); if (parent.endsWith(File.separator)) return parent + path; else return parent + File.separator + path; } //}}} //{{{ getFileExtension() method /** * Returns the extension of the specified filename, or an empty * string if there is none. * @param name The file name or path */ public static String getFileExtension(String name) { int fsIndex = Math.max(name.indexOf('/'), name.indexOf(File.separatorChar)); int index = name.indexOf('.',fsIndex); if(index == -1) return ""; else return name.substring(index); } //}}} //{{{ getFileName() method /** * Returns the last component of the specified path. * This method is VFS-aware. * @param path The path name */ public static String getFileName(String path) { return VFSManager.getVFSForPath(path).getFileName(path); } //}}} //{{{ getFileNameNoExtension() method /** * Returns the last component of the specified path name without the * trailing extension (if there is one). * @param path The path name * @since jEdit 4.0pre8 */ public static String getFileNameNoExtension(String path) { String name = getFileName(path); int index = name.indexOf('.'); if(index == -1) return name; else return name.substring(0,index); } //}}} //{{{ getFileParent() method /** * @deprecated Call getParentOfPath() instead */ public static String getFileParent(String path) { return getParentOfPath(path); } //}}} //{{{ getParentOfPath() method /** * Returns the parent of the specified path. This method is VFS-aware. * @param path The path name * @since jEdit 2.6pre5 */ public static String getParentOfPath(String path) { return VFSManager.getVFSForPath(path).getParentOfPath(path); } //}}} //{{{ getFileProtocol() method /** * @deprecated Call getProtocolOfURL() instead */ public static String getFileProtocol(String url) { return getProtocolOfURL(url); } //}}} //{{{ getProtocolOfURL() method /** * Returns the protocol specified by a URL. * @param url The URL * @since jEdit 2.6pre5 */ public static String getProtocolOfURL(String url) { return url.substring(0,url.indexOf(':')); } //}}} //{{{ isURL() method /** * Checks if the specified string is a URL. * @param str The string to check * @return True if the string is a URL, false otherwise */ public static boolean isURL(String str) { int fsIndex = Math.max(str.indexOf(File.separatorChar), str.indexOf('/')); if(fsIndex == 0) // /etc/passwd return false; else if(fsIndex == 2) // C:\AUTOEXEC.BAT return false; int cIndex = str.indexOf(':'); if(cIndex <= 1) // D:\WINDOWS, or doesn't contain : at all return false; String protocol = str.substring(0,cIndex); VFS vfs = VFSManager.getVFSForProtocol(protocol); if(vfs != null && !(vfs instanceof UrlVFS)) return true; try { new URL(str); return true; } catch(MalformedURLException mf) { return false; } } //}}} //{{{ saveBackup() method /** * Saves a backup (optionally numbered) of a file. * @param file A local file * @param backups The number of backups. Must be >= 1. If > 1, backup * files will be numbered. * @param backupPrefix The backup file name prefix * @param backupSuffix The backup file name suffix * @param backupDirectory The directory where to save backups; if null, * they will be saved in the same directory as the file itself. * @since jEdit 4.0pre1 */ public static void saveBackup(File file, int backups, String backupPrefix, String backupSuffix, String backupDirectory) { saveBackup(file,backups,backupPrefix,backupSuffix,backupDirectory,0); } //}}} //{{{ saveBackup() method /** * Saves a backup (optionally numbered) of a file. * @param file A local file * @param backups The number of backups. Must be >= 1. If > 1, backup * files will be numbered. * @param backupPrefix The backup file name prefix * @param backupSuffix The backup file name suffix * @param backupDirectory The directory where to save backups; if null, * they will be saved in the same directory as the file itself. * @param backupTimeDistance The minimum time in minutes when a backup * version 1 shall be moved into version 2; if 0, backups are always * moved. * @since jEdit 4.2pre5 */ public static void saveBackup(File file, int backups, String backupPrefix, String backupSuffix, String backupDirectory, int backupTimeDistance) { if(backupPrefix == null) backupPrefix = ""; if(backupSuffix == null) backupSuffix = ""; String name = file.getName(); // If backups is 1, create ~ file if(backups == 1) { File backupFile = new File(backupDirectory, backupPrefix + name + backupSuffix); long modTime = backupFile.lastModified(); /* if backup file was created less than * 'backupTimeDistance' ago, we do not * create the backup */ if(System.currentTimeMillis() - modTime >= backupTimeDistance) { backupFile.delete(); file.renameTo(backupFile); } } // If backups > 1, move old ~n~ files, create ~1~ file else { /* delete a backup created using above method */ new File(backupDirectory, backupPrefix + name + backupSuffix + backups + backupSuffix).delete(); File firstBackup = new File(backupDirectory, backupPrefix + name + backupSuffix + "1" + backupSuffix); long modTime = firstBackup.lastModified(); /* if backup file was created less than * 'backupTimeDistance' ago, we do not * create the backup */ if(System.currentTimeMillis() - modTime >= backupTimeDistance) { for(int i = backups - 1; i > 0; i--) { File backup = new File(backupDirectory, backupPrefix + name + backupSuffix + i + backupSuffix); backup.renameTo( new File(backupDirectory, backupPrefix + name + backupSuffix + (i+1) + backupSuffix)); } file.renameTo(new File(backupDirectory, backupPrefix + name + backupSuffix + "1" + backupSuffix)); } } } //}}} //{{{ fileToClass() method /** * Converts a file name to a class name. All slash characters are * replaced with periods and the trailing '.class' is removed. * @param name The file name */ public static String fileToClass(String name) { char[] clsName = name.toCharArray(); for(int i = clsName.length - 6; i >= 0; i--)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -