StringUtils.java
上传用户:sxlinghang
上传日期:2022-07-20
资源大小:1405k
文件大小:16k
源码类别:

数据库编程

开发平台:

Java

  1. /*
  2.    Copyright (C) 2002 MySQL AB
  3.       This program is free software; you can redistribute it and/or modify
  4.       it under the terms of the GNU General Public License as published by
  5.       the Free Software Foundation; either version 2 of the License, or
  6.       (at your option) any later version.
  7.       This program is distributed in the hope that it will be useful,
  8.       but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.       GNU General Public License for more details.
  11.       You should have received a copy of the GNU General Public License
  12.       along with this program; if not, write to the Free Software
  13.       Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  14.  */
  15. package com.mysql.jdbc;
  16. import java.io.ByteArrayOutputStream;
  17. import java.io.UnsupportedEncodingException;
  18. import java.util.ArrayList;
  19. import java.util.List;
  20. import java.util.StringTokenizer;
  21. /**
  22.  * Various utility methods for converting to/from byte arrays in the platform
  23.  * encoding
  24.  *
  25.  * @author Mark Matthews
  26.  */
  27. public class StringUtils {
  28.     private static final int BYTE_RANGE = (1 + Byte.MAX_VALUE) - Byte.MIN_VALUE;
  29.     private static byte[] allBytes = new byte[BYTE_RANGE];
  30.     private static char[] byteToChars = new char[BYTE_RANGE];
  31.     static {
  32.         for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
  33.             allBytes[i - Byte.MIN_VALUE] = (byte) i;
  34.         }
  35.         String allBytesString = new String(allBytes, 0,
  36.                 Byte.MAX_VALUE - Byte.MIN_VALUE);
  37.         int allBytesStringLen = allBytesString.length();
  38.         for (int i = 0;
  39.                 (i < (Byte.MAX_VALUE - Byte.MIN_VALUE))
  40.                 && (i < allBytesStringLen); i++) {
  41.             byteToChars[i] = allBytesString.charAt(i);
  42.         }
  43.     }
  44.     /**
  45.      * Returns the byte[] representation of the given string using given
  46.      * encoding.
  47.      *
  48.      * @param s the string to convert
  49.      * @param encoding the character encoding to use
  50.      *
  51.      * @return byte[] representation of the string
  52.      *
  53.      * @throws UnsupportedEncodingException if an encoding unsupported by the
  54.      *         JVM is supplied.
  55.      */
  56.     public static final byte[] getBytes(String s, String encoding)
  57.         throws UnsupportedEncodingException {
  58.         SingleByteCharsetConverter converter = SingleByteCharsetConverter
  59.             .getInstance(encoding);
  60.         return getBytes(s, converter, encoding);
  61.     }
  62.     /**
  63.      * Returns the byte[] representation of the given string (re)using the
  64.      * given charset converter, and the given encoding.
  65.      *
  66.      * @param s the string to convert
  67.      * @param converter the converter to reuse
  68.      * @param encoding the character encoding to use
  69.      *
  70.      * @return byte[] representation of the string
  71.      *
  72.      * @throws UnsupportedEncodingException if an encoding unsupported by the
  73.      *         JVM is supplied.
  74.      */
  75.     public static final byte[] getBytes(String s,
  76.         SingleByteCharsetConverter converter, String encoding)
  77.         throws UnsupportedEncodingException {
  78.         byte[] b = null;
  79.         if (converter != null) {
  80.             b = converter.toBytes(s);
  81.         } else if (encoding == null) {
  82.             b = s.getBytes();
  83.         } else {
  84.             b = s.getBytes(encoding);
  85.             if (encoding.equalsIgnoreCase("SJIS")
  86.                     || encoding.equalsIgnoreCase("BIG5")
  87.                     || encoding.equalsIgnoreCase("GBK")) {
  88.                 b = escapeSJISByteStream(b, s, 0, s.length());
  89.             }
  90.         }
  91.         return b;
  92.     }
  93.     /**
  94.      * DOCUMENT ME!
  95.      *
  96.      * @param s DOCUMENT ME!
  97.      * @param converter DOCUMENT ME!
  98.      * @param encoding DOCUMENT ME!
  99.      * @param offset DOCUMENT ME!
  100.      * @param length DOCUMENT ME!
  101.      *
  102.      * @return DOCUMENT ME!
  103.      *
  104.      * @throws UnsupportedEncodingException DOCUMENT ME!
  105.      */
  106.     public static final byte[] getBytes(String s,
  107.         SingleByteCharsetConverter converter, String encoding, int offset,
  108.         int length) throws UnsupportedEncodingException {
  109.         byte[] b = null;
  110.         if (converter != null) {
  111.             b = converter.toBytes(s, offset, length);
  112.         } else if (encoding == null) {
  113.             byte[] temp = s.getBytes();
  114.             b = new byte[length];
  115.             System.arraycopy(temp, offset, b, 0, length);
  116.         } else {
  117.             byte[] temp = s.getBytes(encoding);
  118.             b = new byte[length];
  119.             System.arraycopy(temp, offset, b, 0, length);
  120.             if (encoding.equalsIgnoreCase("SJIS")
  121.                     || encoding.equalsIgnoreCase("BIG5")
  122.                     || encoding.equalsIgnoreCase("GBK")) {
  123.                 b = escapeSJISByteStream(b, s, offset, length);
  124.             }
  125.         }
  126.         return b;
  127.     }
  128.     /**
  129.      * Dumps the given bytes to STDOUT as a hex dump (up to length bytes).
  130.      *
  131.      * @param byteBuffer the data to print as hex
  132.      * @param length the number of bytes to print
  133.      */
  134.     public static final void dumpAsHex(byte[] byteBuffer, int length) {
  135.         int p = 0;
  136.         int rows = length / 8;
  137.         for (int i = 0; i < rows; i++) {
  138.             int ptemp = p;
  139.             for (int j = 0; j < 8; j++) {
  140.                 String hexVal = Integer.toHexString((int) byteBuffer[ptemp]
  141.                         & 0xff);
  142.                 if (hexVal.length() == 1) {
  143.                     hexVal = "0" + hexVal;
  144.                 }
  145.                 System.out.print(hexVal + " ");
  146.                 ptemp++;
  147.             }
  148.             System.out.print("    ");
  149.             for (int j = 0; j < 8; j++) {
  150.                 if ((byteBuffer[p] > 32) && (byteBuffer[p] < 127)) {
  151.                     System.out.print((char) byteBuffer[p] + " ");
  152.                 } else {
  153.                     System.out.print(". ");
  154.                 }
  155.                 p++;
  156.             }
  157.             System.out.println();
  158.         }
  159.         int n = 0;
  160.         for (int i = p; i < length; i++) {
  161.             String hexVal = Integer.toHexString((int) byteBuffer[i] & 0xff);
  162.             if (hexVal.length() == 1) {
  163.                 hexVal = "0" + hexVal;
  164.             }
  165.             System.out.print(hexVal + " ");
  166.             n++;
  167.         }
  168.         for (int i = n; i < 8; i++) {
  169.             System.out.print("   ");
  170.         }
  171.         System.out.print("    ");
  172.         for (int i = p; i < length; i++) {
  173.             if ((byteBuffer[i] > 32) && (byteBuffer[i] < 127)) {
  174.                 System.out.print((char) byteBuffer[i] + " ");
  175.             } else {
  176.                 System.out.print(". ");
  177.             }
  178.         }
  179.         System.out.println();
  180.     }
  181.     /**
  182.      * Returns the bytes as an ASCII String.
  183.      *
  184.      * @param buffer the bytes representing the string
  185.      *
  186.      * @return The ASCII String.
  187.      */
  188.     public static final String toAsciiString(byte[] buffer) {
  189.         return toAsciiString(buffer, 0, buffer.length);
  190.     }
  191.     /**
  192.      * Returns the bytes as an ASCII String.
  193.      *
  194.      * @param buffer the bytes to convert
  195.      * @param startPos the position to start converting
  196.      * @param length the length of the string to convert
  197.      *
  198.      * @return the ASCII string
  199.      */
  200.     public static final String toAsciiString(byte[] buffer, int startPos,
  201.         int length) {
  202.         char[] charArray = new char[length];
  203.         int readpoint = startPos;
  204.         for (int i = 0; i < length; i++) {
  205.             charArray[i] = (char) buffer[readpoint];
  206.             readpoint++;
  207.         }
  208.         return new String(charArray);
  209.     }
  210.     /**
  211.      * Unfortunately, SJIS has 0x5c as a high byte in some of its double-byte
  212.      * characters, so we need to escape it.
  213.      *
  214.      * @param origBytes the original bytes in SJIS format
  215.      * @param origString the string that had .getBytes() called on it
  216.      * @param offset where to start converting from
  217.      * @param length how many characters to convert.
  218.      *
  219.      * @return byte[] with 0x5c escaped
  220.      */
  221.     public static byte[] escapeSJISByteStream(byte[] origBytes,
  222.         String origString, int offset, int length) {
  223.         if ((origBytes == null) || (origBytes.length == 0)) {
  224.             return origBytes;
  225.         }
  226.         int bytesLen = origBytes.length;
  227.         int bufIndex = 0;
  228.         int strIndex = 0;
  229.         ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(bytesLen);
  230.         while (true) {
  231.             if (origString.charAt(strIndex) == '\') {
  232.                 // write it out as-is
  233.              bytesOut.write(origBytes[bufIndex++]);
  234.              //bytesOut.write(origBytes[bufIndex++]);
  235.             } else {
  236.                 // Grab the first byte
  237.                 int loByte = (int) origBytes[bufIndex];
  238.                 if (loByte < 0) {
  239.                     loByte += 256; // adjust for signedness/wrap-around
  240.                 }
  241.                 // We always write the first byte
  242.                 bytesOut.write(loByte);
  243.                 //
  244.                 // The codepage characters in question exist between
  245.                 // 0x81-0x9F and 0xE0-0xFC...
  246.                 //
  247.                 // See:
  248.                 //
  249.                 // http://www.microsoft.com/GLOBALDEV/Reference/dbcs/932.htm
  250.                 //
  251.                 // Problematic characters in GBK
  252.                 //
  253.                 // U+905C : CJK UNIFIED IDEOGRAPH
  254.                 //
  255.                 // Problematic characters in Big5
  256.                 //
  257.                 // B9F0 = U+5C62 : CJK UNIFIED IDEOGRAPH
  258.                 //
  259.                 if (((loByte >= 0x81) && (loByte <= 0x9F))
  260.                         || ((loByte >= 0xE0) && (loByte <= 0xFC))) {
  261.                     if (bufIndex < (bytesLen - 1)) {
  262.                         int hiByte = (int) origBytes[bufIndex + 1];
  263.                         if (hiByte < 0) {
  264.                             hiByte += 256; // adjust for signedness/wrap-around
  265.                         }
  266.                         // write the high byte here, and increment the index
  267.                         // for the high byte
  268.                         bytesOut.write(hiByte);
  269.                         bufIndex++;
  270.                         // escape 0x5c if necessary
  271.                         if (hiByte == 0x5C) {
  272.                             bytesOut.write(hiByte);
  273.                         }
  274.                     }
  275.                 } else if (loByte == 0x5c) {
  276.                     if (bufIndex < (bytesLen - 1)) {
  277.                         int hiByte = (int) origBytes[bufIndex + 1];
  278.                         if (hiByte < 0) {
  279.                             hiByte += 256; // adjust for signedness/wrap-around
  280.                         }
  281.                         if (hiByte == 0x62) {
  282.                             // we need to escape the 0x5c
  283.                             bytesOut.write(0x5c);
  284.                             bytesOut.write(0x62);
  285.                             bufIndex++;
  286.                         }
  287.                     }
  288.                 }
  289. bufIndex++;
  290.                 
  291.             }
  292. if (bufIndex >= bytesLen) {
  293. // we're done
  294. break;
  295. }
  296.             strIndex++;
  297.         }
  298.         return bytesOut.toByteArray();
  299.     }
  300.     /**
  301.      * Returns the first non whitespace char, converted to upper case
  302.      *
  303.      * @param searchIn the string to search in
  304.      *
  305.      * @return the first non-whitespace character, upper cased.
  306.      */
  307.     public static char firstNonWsCharUc(String searchIn) {
  308.         if (searchIn == null) {
  309.             return 0;
  310.         }
  311.         int length = searchIn.length();
  312.         for (int i = 0; i < length; i++) {
  313.             char c = searchIn.charAt(i);
  314.             if (!Character.isWhitespace(c)) {
  315.                 return Character.toUpperCase(c);
  316.             }
  317.         }
  318.         return 0;
  319.     }
  320.     /**
  321.      * DOCUMENT ME!
  322.      *
  323.      * @param searchIn DOCUMENT ME!
  324.      * @param searchFor DOCUMENT ME!
  325.      *
  326.      * @return DOCUMENT ME!
  327.      */
  328.     public static int indexOfIgnoreCase(String searchIn, String searchFor) {
  329.         if ((searchIn == null) || (searchFor == null)) {
  330.             return -1;
  331.         }
  332.         int patternLength = searchFor.length();
  333.         int stringLength = searchIn.length();
  334.         int i = 0;
  335.         if (patternLength == 0) {
  336.             return -1;
  337.         }
  338.         // Brute force string pattern matching
  339.         char firstCharOfPattern = Character.toUpperCase(searchFor.charAt(0));
  340. lookForFirstChar: 
  341.         while (true) {
  342.             while ((i <= stringLength)
  343.                     && (Character.toUpperCase(searchIn.charAt(i)) != firstCharOfPattern)) {
  344.                 i++;
  345.             }
  346.             if (i > stringLength) {
  347.                 return -1;
  348.             }
  349.             int j = i + 1;
  350.             int end = (j + patternLength) - 1;
  351.             int k = 1; // start at second char of pattern
  352.             while (j < end) {
  353.                 if (Character.toUpperCase(searchIn.charAt(j++)) != Character
  354.                         .toUpperCase(searchFor.charAt(k++))) {
  355.                     i++;
  356.                     // start over
  357.                     continue lookForFirstChar;
  358.                 }
  359.             }
  360.             return i; // found entire pattern
  361.         }
  362.     }
  363.     /**
  364.      * Splits stringToSplit into a list, using the given delimitter
  365.      *
  366.      * @param stringToSplit the string to split
  367.      * @param delimitter the string to split on
  368.      * @param trim should the split strings be whitespace trimmed?
  369.      *
  370.      * @return the list of strings, split by delimitter
  371.      *
  372.      * @throws IllegalArgumentException DOCUMENT ME!
  373.      */
  374.     public static final List split(String stringToSplit, String delimitter,
  375.         boolean trim) {
  376.         if (stringToSplit == null) {
  377.             return new ArrayList();
  378.         }
  379.         if (delimitter == null) {
  380.             throw new IllegalArgumentException();
  381.         }
  382.         StringTokenizer tokenizer = new StringTokenizer(stringToSplit,
  383.                 delimitter, false);
  384.         List splitTokens = new ArrayList(tokenizer.countTokens());
  385.         while (tokenizer.hasMoreTokens()) {
  386.             String token = tokenizer.nextToken();
  387.             if (trim) {
  388.                 token = token.trim();
  389.             }
  390.             splitTokens.add(token);
  391.         }
  392.         return splitTokens;
  393.     }
  394.     /**
  395.      * Determines whether or not the string 'searchIn' contains the string
  396.      * 'searchFor', dis-regarding case. Shorthand for a
  397.      * String.regionMatch(...)
  398.      *
  399.      * @param searchIn the string to search in
  400.      * @param searchFor the string to search for
  401.      *
  402.      * @return whether searchIn starts with searchFor, ignoring case
  403.      */
  404.     public static boolean startsWithIgnoreCase(String searchIn, String searchFor) {
  405.         return startsWithIgnoreCase(searchIn, 0, searchFor);
  406.     }
  407.     /**
  408.      * Determines whether or not the string 'searchIn' contains the string
  409.      * 'searchFor', dis-regarding case starting at 'startAt' Shorthand for a
  410.      * String.regionMatch(...)
  411.      *
  412.      * @param searchIn the string to search in
  413.      * @param startAt the position to start at
  414.      * @param searchFor the string to search for
  415.      *
  416.      * @return whether searchIn starts with searchFor, ignoring case
  417.      */
  418.     public static boolean startsWithIgnoreCase(String searchIn, int startAt,
  419.         String searchFor) {
  420.         return searchIn.regionMatches(true, 0, searchFor, startAt,
  421.             searchFor.length());
  422.     }
  423.     /**
  424.      * Determines whether or not the sting 'searchIn' contains the string
  425.      * 'searchFor', di-regarding case and leading whitespace
  426.      *
  427.      * @param searchIn the string to search in
  428.      * @param searchFor the string to search for
  429.      *
  430.      * @return true if the string starts with 'searchFor' ignoring whitespace
  431.      */
  432.     public static boolean startsWithIgnoreCaseAndWs(String searchIn,
  433.         String searchFor) {
  434.         int beginPos = 0;
  435.         int inLength = searchIn.length();
  436.         for (beginPos = 0; beginPos < inLength; beginPos++) {
  437.             if (!Character.isWhitespace(searchIn.charAt(beginPos))) {
  438.                 break;
  439.             }
  440.         }
  441.         return startsWithIgnoreCase(searchIn, beginPos, searchFor);
  442.     }
  443. }