📄 utils.java
字号:
// Utils - assorted static utility routines//// Copyright (C)1996,1998 by Jef Poskanzer <jef@acme.com>. All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions// are met:// 1. Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// 2. Redistributions in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the distribution.//// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF// SUCH DAMAGE.//// Visit the ACME Labs Java page for up-to-date versions of this and other// fine Java utilities: http://www.acme.com/java/package Acme;import java.util.*;import java.io.*;import java.net.*;import java.text.SimpleDateFormat;/// Assorted static utility routines.// <P>// Whenever I come up with a static routine that might be of general use,// I put it here. So far the class includes:// <UL>// <LI> some string routines that were left out of java.lang.String// <LI> a general array-to-string routine// <LI> a fixed version of java.io.InputStream's byte-array read routine// <LI> a bunch of URL-hacking routines// <LI> some easy-to-use wrappers for Runtime.exec// <LI> a debugging routine to dump the current call stack// <LI> a URLDecoder to match java.net.URLEncoder// </UL>// and lots more.// <P>// <A HREF="/resources/classes/Acme/Utils.java">Fetch the software.</A><BR>// <A HREF="/resources/classes/Acme.tar.Z">Fetch the entire Acme package.</A>public class Utils { /// Returns a date string formatted in Unix ls style - if it's within // six months of now, Mmm dd hh:ss, else Mmm dd yyyy. static final SimpleDateFormat shortfmt = new SimpleDateFormat("MMM dd HH:mm"); static final SimpleDateFormat longfmt = new SimpleDateFormat("MMM dd yyyy"); public static String lsDateStr( Date date ) { if ( Math.abs( System.currentTimeMillis() - date.getTime() ) < 183L * 24L * 60L * 60L * 1000L ) return shortfmt.format(date); else return longfmt.format(date); } /// Returns "s" for numbers other than one, and "" for one. public static String pluralStr( long n ) { if ( n == 1 ) return ""; else return "s"; } // Various interval constants. Some are only approximate. public static final long INT_SECOND = 1000L; public static final long INT_MINUTE = INT_SECOND * 60L; public static final long INT_HOUR = INT_MINUTE * 60L; public static final long INT_DAY = INT_HOUR * 24L; public static final long INT_WEEK = INT_DAY * 7L; public static final long INT_MONTH = INT_DAY * 30L; public static final long INT_YEAR = INT_DAY * 365L; public static final long INT_DECADE = INT_DAY * 3652L; /// Returns a string approximately describing a given time interval. // @param interval the interval, in milliseconds public static String intervalStr( long interval ) { long decades, years, months, weeks, days, hours, minutes, seconds, millis; decades = interval / INT_DECADE; interval -= decades * INT_DECADE; years = interval / INT_YEAR; interval -= years * INT_YEAR; months = interval / INT_MONTH; interval -= months * INT_MONTH; weeks = interval / INT_WEEK; interval -= weeks * INT_WEEK; days = interval / INT_DAY; interval -= days * INT_DAY; hours = interval / INT_HOUR; interval -= hours * INT_HOUR; minutes = interval / INT_MINUTE; interval -= minutes * INT_MINUTE; seconds = interval / INT_SECOND; interval -= seconds * INT_SECOND; millis = interval; if ( decades > 0 ) if ( years == 0 ) return decades + " decade" + pluralStr( decades ); else return decades + " decade" + pluralStr( decades ) + ", " + years + " years" + pluralStr( years ); else if ( years > 0 ) if ( months == 0 ) return years + " year" + pluralStr( years ); else return years + " year" + pluralStr( years ) + ", " + months + " month" + pluralStr( months ); else if ( months > 0 ) if ( weeks == 0 ) return months + " month" + pluralStr( months ); else return months + " month" + pluralStr( months ) + ", " + weeks + " week" + pluralStr( weeks ); else if ( weeks > 0 ) if ( days == 0 ) return weeks + " week" + pluralStr( weeks ); else return weeks + " week" + pluralStr( weeks ) + ", " + days + " day" + pluralStr( days ); else if ( days > 0 ) if ( hours == 0 ) return days + " day" + pluralStr( days ); else return days + " day" + pluralStr( days ) + ", " + hours + " hour" + pluralStr( hours ); else if ( hours > 0 ) if ( minutes == 0 ) return hours + " hour" + pluralStr( hours ); else return hours + " hour" + pluralStr( hours ) + ", " + minutes + " minute" + pluralStr( minutes ); else if ( minutes > 0 ) if ( seconds == 0 ) return minutes + " minute" + pluralStr( minutes ); else return minutes + " minute" + pluralStr( minutes ) + ", " + seconds + " second" + pluralStr( seconds ); else if ( seconds > 0 ) if ( millis == 0 ) return seconds + " second" + pluralStr( seconds ); else return seconds + " second" + pluralStr( seconds ) + ", " + millis + " millisecond" + pluralStr( millis ); else return millis + " millisecond" + pluralStr( millis ); } /// Returns the length of the initial segment of str which consists // entirely of characters from charSet. public static int strSpan( String str, String charSet ) { return strSpan( str, charSet, 0 ); } /// Returns the length of the initial segment of str which consists // entirely of characters from charSet, starting at the given index. public static int strSpan( String str, String charSet, int fromIdx ) { int i; for ( i = fromIdx; i < str.length(); ++i ) if ( charSet.indexOf( str.charAt( i ) ) == -1 ) break; return i - fromIdx; } /// Returns the length of the initial segment of str which consists // entirely of characters NOT from charSet. public static int strCSpan( String str, String charSet ) { return strCSpan( str, charSet, 0 ); } /// Returns the length of the initial segment of str which consists // entirely of characters NOT from charSet, starting at the given index. public static int strCSpan( String str, String charSet, int fromIdx ) { int i; for ( i = fromIdx; i < str.length(); ++i ) if ( charSet.indexOf( str.charAt( i ) ) != -1 ) break; return i - fromIdx; } /// Checks whether a string matches a given wildcard pattern. // Only does ? and *, and multiple patterns separated by |. public static boolean match( String pattern, String string ) { for ( int p = 0; ; ++p ) { for ( int s = 0; ; ++p, ++s ) { boolean sEnd = ( s >= string.length() ); boolean pEnd = ( p >= pattern.length() || pattern.charAt( p ) == '|' ); if ( sEnd && pEnd ) return true; if ( sEnd || pEnd ) break; if ( pattern.charAt( p ) == '?' ) continue; if ( pattern.charAt( p ) == '*' ) { int i; ++p; for ( i = string.length(); i >= s; --i ) if ( match( pattern.substring( p ), string.substring( i ) ) ) /* not quite right */ return true; break; } if ( pattern.charAt( p ) != string.charAt( s ) ) break; } p = pattern.indexOf( '|', p ); if ( p == -1 ) return false; } } /// Finds the maximum length of a string that matches a given wildcard // pattern. Only does ? and *, and multiple patterns separated by |. public static int matchSpan( String pattern, String string ) { int result = 0; StringTokenizer st = new StringTokenizer(pattern, "|"); while (st.hasMoreTokens()) { int len = matchSpan1(st.nextToken(), string); if (len > result) result = len; } return result; } static int matchSpan1( String pattern, String string ) { int p=0; for (; p < string.length() && p < pattern.length(); p++) { if (pattern.charAt(p) == string.charAt(p)) continue; if (pattern.charAt(p) == '*') return p-1; return 0; } return p<(pattern.length()-1)?-1:p; } /// Returns the length of the initial segment of str1 that equals str2. public static int sameSpan( String str1, String str2 ) { int i; for ( i = 0; i < str1.length() && i < str2.length() && str1.charAt( i ) == str2.charAt( i ); ++i ) ; return i; } /// Returns the number of times the given character appears in the string. public static int charCount( String str, char c ) { int n = 0; for ( int i = 0; i < str.length(); ++i ) if ( str.charAt( i ) == c ) ++n; return n; } /// Turns a String into an array of Strings, by using StringTokenizer // to split it up at whitespace. public static String[] splitStr( String str ) { StringTokenizer st = new StringTokenizer( str ); int n = st.countTokens(); String[] strs = new String[n]; for ( int i = 0; i < n; ++i ) strs[i] = st.nextToken(); return strs; } /// Turns a String into an array of Strings, by splitting it at // the specified character. This does not use StringTokenizer, // and therefore can handle empty fields. public static String[] splitStr( String str, char delim ) { int n = 1; int index = -1; while ( true ) { index = str.indexOf( delim, index + 1 ); if ( index == -1 ) break; ++n; } String[] strs = new String[n]; index = -1; for ( int i = 0; i < n - 1; ++i ) { int nextIndex = str.indexOf( delim, index + 1 ); strs[i] = str.substring( index + 1, nextIndex ); index = nextIndex; } strs[n - 1] = str.substring( index + 1 ); return strs; } /// Turns an array of Strings into a single String, with the components // separated by spaces. public static String flattenStrarr( String[] strs ) { StringBuffer sb = new StringBuffer(); for ( int i = 0; i < strs.length; ++i ) { if ( i > 0 ) sb.append( ' ' ); sb.append( strs[i] ); } return sb.toString(); } /// Sorts an array of Strings. // Java currently has no general sort function. Sorting Strings is // common enough that it's worth making a special case. public static void sortStrings( String[] strings ) { // Just does a bubblesort. for ( int i = 0; i < strings.length - 1; ++i ) { for ( int j = i + 1; j < strings.length; ++j ) { if ( strings[i].compareTo( strings[j] ) > 0 ) { String t = strings[i]; strings[i] = strings[j]; strings[j] = t; } } } } /// Locates a String in an array of Strings. // Returns -1 if the String is not found. public static int indexOfString( String[] strings, String string ) { for ( int i = 0; i < strings.length; ++i ) if ( string.equals( strings[i] ) ) return i; return -1; } /// Locates a String in an array of Strings, ignoring case. // Returns -1 if the String is not found. public static int indexOfStringIgnoreCase( String[] strings, String string ) { for ( int i = 0; i < strings.length; ++i ) if ( string.equalsIgnoreCase( strings[i] ) ) return i; return -1; } /// Compares two arrays of Strings for equality. public static boolean equalsStrings( String[] strings1, String[] strings2 ) { if ( strings1.length != strings2.length ) return false; for ( int i = 0; i < strings1.length; ++i ) if ( ! strings1[i].equals( strings2[i] ) ) return false; return true; } /// Returns the number a raised to the power of b. Long version // of Math.pow(). Throws ArithmeticException if b is negative. public static long pow( long a, long b ) throws ArithmeticException { if ( b < 0 ) throw new ArithmeticException(); long r = 1; while ( b != 0 ) { if ( odd( b ) ) r *= a; b >>>= 1; a *= a; } return r; } /// Parse an integer, returning a default value on errors. public static int parseInt( String str, int def ) { try { return Integer.parseInt( str ); } catch ( Exception e ) { return def; } } /// Parse a long, returning a default value on errors. public static long parseLong( String str, long def ) { try { return Long.parseLong( str ); } catch ( Exception e ) { return def; } } /// An array-to-String routine. Handles arrays of arbitrary // type, including nested arrays. Sample output: // <BLOCKQUOTE><CODE><PRE> // byte[]: { (byte)0, (byte)1, (byte)2 } // char[]: { '0', '1', '2' } // short[]: { (short)0, (short)1, (short)2 } // int[]: { 0, 1, 2 } // long[]: { 0L, 1L, 2L } // float[]: { 0F, 1F, 2F } // double[]: { 0D, 1D, 2D } // String[]: { "0", "1", "2" } // int[][]: { { 0, 1, 2 }, { 3, 4, 5 } } // </PRE></CODE></BLOCKQUOTE> public static String arrayToString( Object o ) { if ( o == null ) return "null"; String cl = o.getClass().getName(); if ( ! cl.startsWith( "[" ) ) // It's not an array; just call its toString method. return o.toString(); StringBuffer sb = new StringBuffer( "{ " ); if ( o instanceof byte[] ) { byte[] ba = (byte[]) o; for ( int i = 0; i < ba.length; ++i ) { if ( i > 0 ) sb.append( ", " ); sb.append( "(byte)" ); sb.append( ba[i] ); } } else if ( o instanceof char[] ) { char[] ca = (char[]) o; for ( int i = 0; i < ca.length; ++i ) { if ( i > 0 ) sb.append( ", " ); sb.append( "'" ); sb.append( ca[i] ); sb.append( "'" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -