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

com.jianggujin.http.util.JDataUtils Maven / Gradle / Ivy

package com.jianggujin.http.util;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.IllegalCharsetNameException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 数据工具
 * 
 * @author jianggujin
 *
 */
public final class JDataUtils {
   /**
    * 字符集正则匹配模式
    */
   private static final Pattern charsetPattern = Pattern.compile("(?i)\\bcharset=\\s*(?:\"|')?([^\\s,;\"']*)");
   /**
    * 默认字符集
    */
   public static final String defaultCharset = "UTF-8";
   /**
    * 缓冲区大小
    */
   private static final int bufferSize = 0x20000; // ~130K.
   /**
    * mime边界字符数组
    */
   private static final char[] mimeBoundaryChars = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
         .toCharArray();
   /**
    * mime边界长度
    */
   private static final int boundaryLength = 32;
   /**
    * 空字符串数组
    */
   public static final String[] EMPTY_STRING_ARRAY = new String[0];

   private JDataUtils() {
   }

   /**
    * 将输入流数据写入到输出流,不关闭相关流
    * 
    * @param in
    *           输入流
    * @param out
    *           输出流
    * @throws IOException
    */
   public static void crossStreams(final InputStream in, final OutputStream out) throws IOException {
      final byte[] buffer = new byte[bufferSize];
      int len;
      while ((len = in.read(buffer)) != -1) {
         out.write(buffer, 0, len);
      }
      out.flush();
   }

   /**
    * 从输入流读取数据到字节缓冲区
    * 
    * @param in
    *           输入流
    * @param maxSize
    *           从输入流中读取的最大长度,设置为0不限制
    * @return
    * @throws IOException
    */
   public static ByteBuffer readToByteBuffer(InputStream in, int maxSize) throws IOException {
      if (maxSize < 0) {
         throw new IllegalArgumentException("maxSize must be 0 (unlimited) or larger");
      }
      final boolean capped = maxSize > 0;
      byte[] buffer = new byte[bufferSize];
      ByteArrayOutputStream outStream = new ByteArrayOutputStream(bufferSize);
      int read;
      int remaining = maxSize;

      while (true) {
         read = in.read(buffer);
         if (read == -1) {
            break;
         }
         if (capped) {
            if (read > remaining) {
               outStream.write(buffer, 0, remaining);
               break;
            }
            remaining -= read;
         }
         outStream.write(buffer, 0, read);
      }
      return ByteBuffer.wrap(outStream.toByteArray());
   }

   /**
    * 从输入流读取数据到字节缓冲区
    * 
    * @param in
    *           输入流
    * @return
    * @throws IOException
    */
   public static ByteBuffer readToByteBuffer(InputStream in) throws IOException {
      return readToByteBuffer(in, 0);
   }

   /**
    * 从文件中读取数据到字节缓冲区
    * 
    * @param file
    *           文件
    * @return
    * @throws IOException
    */
   public static ByteBuffer readFileToByteBuffer(File file) throws IOException {
      RandomAccessFile randomAccessFile = null;
      try {
         randomAccessFile = new RandomAccessFile(file, "r");
         byte[] bytes = new byte[(int) randomAccessFile.length()];
         randomAccessFile.readFully(bytes);
         return ByteBuffer.wrap(bytes);
      } finally {
         if (randomAccessFile != null) {
            randomAccessFile.close();
         }
      }
   }

   /**
    * 将输入流解析成字符串
    * 
    * @param in
    * @param charset
    * @return
    * @throws IOException
    */
   public static String readToString(InputStream in, String charset) throws IOException {
      ByteBuffer buffer = JDataUtils.readToByteBuffer(in);
      String body;
      if (charset == null) {
         body = Charset.forName(JDataUtils.defaultCharset).decode(buffer).toString();
      } else {
         body = Charset.forName(charset).decode(buffer).toString();
      }
      return body;
   }

   /**
    * 空的字节缓冲区
    * 
    * @return
    */
   public static ByteBuffer emptyByteBuffer() {
      return ByteBuffer.allocate(0);
   }

   /**
    * 从Content-Type头中解析字符集,如果该字符集不被支持则返回null
    * 
    * @param contentType
    *           示例 "text/html; charset=EUC-JP"
    * @return "EUC-JP", or null if not found. Charset is trimmed and uppercased.
    */
   public static String getCharsetFromContentType(String contentType) {
      if (contentType == null) {
         return null;
      }
      Matcher m = charsetPattern.matcher(contentType);
      if (m.find()) {
         String charset = m.group(1).trim();
         charset = charset.replace("charset=", "");
         return validateCharset(charset);
      }
      return null;
   }

   /**
    * 验证字符集
    * 
    * @param cs
    * @return
    */
   public static String validateCharset(String cs) {
      if (cs == null || cs.length() == 0) {
         return null;
      }
      cs = cs.trim().replaceAll("[\"']", "");
      try {
         if (Charset.isSupported(cs)) {
            return cs;
         }
         cs = cs.toUpperCase(Locale.ENGLISH);
         if (Charset.isSupported(cs)) {
            return cs;
         }
      } catch (IllegalCharsetNameException e) {
      }
      return null;
   }

   /**
    * 创建一个用于mime边界的随随机字符串
    */
   public static String mimeBoundary() {
      final StringBuilder mime = new StringBuilder(boundaryLength);
      final Random rand = new Random();
      for (int i = 0; i < boundaryLength; i++) {
         mime.append(mimeBoundaryChars[rand.nextInt(mimeBoundaryChars.length)]);
      }
      return mime.toString();
   }

   /**
    * 将url中的空格转化成%20
    * 
    * @param url
    * @return
    */
   public static String encodeUrl(String url) {
      if (url == null) {
         return null;
      }
      return url.replaceAll(" ", "%20");
   }

   /**
    * 创建一个新的绝对URL
    * 
    * @param base
    *           the existing absolulte base URL
    * @param relUrl
    *           the relative URL to resolve. (If it's already absolute, it will
    *           be returned)
    * @return the resolved absolute URL
    * @throws MalformedURLException
    *            if an error occurred generating the URL
    */
   public static URL resolve(URL base, String relUrl) throws MalformedURLException {
      // workaround: java resolves '//path/file + ?foo' to '//path/?foo', not
      // '//path/file?foo' as desired
      if (relUrl.startsWith("?")) {
         relUrl = base.getPath() + relUrl;
      }
      // workaround: //example.com + ./foo = //example.com/./foo, not
      // //example.com/foo
      if (relUrl.indexOf('.') == 0 && base.getFile().indexOf('/') != 0) {
         base = new URL(base.getProtocol(), base.getHost(), base.getPort(), "/" + base.getFile());
      }
      return new URL(base, relUrl);
   }

   /**
    * 创建一个新的绝对URL
    * 
    * @param baseUrl
    *           the existing absolute base URL
    * @param relUrl
    *           the relative URL to resolve. (If it's already absolute, it will
    *           be returned)
    * @return an absolute URL if one was able to be generated, or the empty
    *         string if not
    */
   public static String resolve(final String baseUrl, final String relUrl) {
      URL base;
      try {
         try {
            base = new URL(baseUrl);
         } catch (MalformedURLException e) {
            // the base is unsuitable, but the attribute/rel may be abs on its
            // own, so try that
            URL abs = new URL(relUrl);
            return abs.toExternalForm();
         }
         return resolve(base, relUrl).toExternalForm();
      } catch (MalformedURLException e) {
         return "";
      }
   }

   /**
    * 编码mime
    * 
    * @param val
    * @return
    */
   public static String encodeMimeName(String val) {
      if (val == null) {
         return null;
      }
      return val.replaceAll("\"", "%22");
   }

   /**
    * 判断字符串是否为空
    * 
    * @param str
    * @return
    */
   public static boolean isEmpty(String str) {
      return str == null || str.length() == 0;
   }

   /**
    * 用提供的数据替换掉字符串中内容
    * 
    * @param text
    * @param bindRes
    * @return
    */
   public static String resolveDynamicPropnames(String text, Map bindRes) {
      return resolveDynamicPropnames(text, bindRes, "${", "}");
   }

   /**
    * 用提供的数据替换掉字符串中内容
    * 
    * @param text
    * @param bindRes
    * @param prefix
    *           插值前缀
    * @param suffix
    *           插值后缀
    * @return
    */
   public static String resolveDynamicPropnames(String text, Map bindRes, String prefix,
         String suffix) {
      if (text == null) {
         return text;
      }
      int startIndex = text.indexOf(prefix);
      if (startIndex == -1) {
         return text;
      }

      String tempStr = text;
      StringBuilder result = new StringBuilder(text.length() + 32);
      int prefixLength = prefix.length();
      while (startIndex != -1) {
         result.append(tempStr.substring(0, startIndex));
         int endIndex = tempStr.indexOf(suffix, startIndex + prefixLength);
         if (endIndex != -1) {
            String dName = tempStr.substring(startIndex + prefixLength, endIndex);
            try {
               String pValue = null;
               if (bindRes != null) {
                  Object obj = bindRes.get(dName);
                  if (obj != null) {
                     pValue = String.valueOf(obj);
                  }
               }
               if (pValue != null) {
                  result.append(resolveDynamicPropnames(pValue, bindRes));
               } else {
                  result.append(tempStr.substring(startIndex, endIndex + 1));
               }

            } catch (Throwable ex) {
            }
            tempStr = tempStr.substring(endIndex + suffix.length());
            startIndex = tempStr.indexOf(prefix);
         } else {
            tempStr = tempStr.substring(startIndex);
            startIndex = -1;
         }
      }
      result.append(tempStr);

      return result.toString();
   }

   /**
    * 根据指定的分隔符delimiter分割一个字符串 str.
    * 

* 如果给出的字符串strnull、空串 "",则返回 * null,只包含分隔符 delimiter,则返回长度为0的字符串数组。如果给出的 字符串 * str可以分割,即不在上述情况之列,则返回一个 字符串数组,每个单元包含一个被分隔出来的字符串。 *

* 例如:

* *
    * StringProcessor.separateString("一,二,三", ",")
    *         返回 {"一", "二", "三"}
    * StringProcessor.separateString("你好,大家好!我很好。", ",!")
    *         返回 {"你好", "大家好", "我很好。"}
    * StringProcessor.separateString(null, ", \t\r\n")
    *         返回 null
    * StringProcessor.separateString(", , , , ", ", \n")
    *         返回 {}
    * 
* *
* * @param str * 要进行分割的字符串 * @param delimiter * 分隔符集合 * @return 分割后的字符串所组成的数组 */ public static String[] separateString(String str, String delimiter) { return separateString(str, delimiter, false); } /** * 根据指定的分隔符delimiter分割一个字符串 str. *

* * @param str * 要进行分割的字符串 * @param delimiter * 分隔符集合 * @param trim * 是否要对分割出来的每个字符串进行去除空格处理 * @return 分割后的字符串所组成的数组 */ public static String[] separateString(String str, String delimiter, boolean trim) { if (str == null) { return null; } int count = str.length(); if (count == 0) { return EMPTY_STRING_ARRAY; } if (isEmpty(delimiter)) { delimiter = " \t\n\r\f"; } List list = new ArrayList(); int i = 0; int begin = 0; boolean notMatch = false; if (delimiter.length() == 1) { // 仅有一个字符时用字符比较来判断 char c = delimiter.charAt(0); while (i < count) { if (str.charAt(i) == c) { if (notMatch) { list.add(trim ? str.substring(begin, i).trim() : str.substring(begin, i)); notMatch = false; } begin = ++i; continue; } notMatch = true; i++; } } else { // 有多个字符时用字符串的包含字符来判断 while (i < count) { if (delimiter.indexOf(str.charAt(i)) >= 0) { if (notMatch) { list.add(trim ? str.substring(begin, i).trim() : str.substring(begin, i)); notMatch = false; } begin = ++i; continue; } notMatch = true; i++; } } if (notMatch) { list.add(trim ? str.substring(begin, i).trim() : str.substring(begin, i)); } return (String[]) list.toArray(new String[list.size()]); } /** * 将字符串数组arr用链接符link链接成一个字符串. *

* * @param arr * 要链接的字符串数组 * @param link * 链接符 * @return 用链接符链接后的字符串 */ public static String linkStringArr(String[] arr, String link) { if (arr == null || arr.length == 0) { return ""; } if (arr.length == 1) { return arr[0]; } link = link == null ? "" : link; StringBuilder buf = new StringBuilder(arr.length * (link.length() + 16)); buf.append(arr[0]); for (int i = 1; i < arr.length; i++) { buf.append(link).append(arr[i]); } return buf.toString(); } /** * 将字符串按照一定的格式转换成Map. *

* * @param str * 要转换成Map的字符串 * @param itemDelimiter * Map元素的分隔符集合 * @param kvDelimiter * key和value的分隔符 * @return 转换后的Map对象 */ public static Map string2Map(String str, String itemDelimiter, char kvDelimiter) { return string2Map(str, itemDelimiter, kvDelimiter, true, true, null, null); } /** * 将字符串按照一定的格式转换成Map. *

* * @param str * 要转换成Map的字符串 * @param itemDelimiter * Map元素的分隔符集合 * @param kvDelimiter * key和value的分隔符 * @param trimItem * 是否要对每个元素进行trim * @param needResolve * 是否要处理文本中"${...}"的动态属性 * @param resolveRes * 处理动态属性是绑定的资源 * @param result * 将转换的结果放入此Map中 * @return 转换后的Map对象 */ public static Map string2Map(String str, String itemDelimiter, char kvDelimiter, boolean trimItem, boolean needResolve, Map resolveRes, Map result) { if (str == null) { return null; } if (result == null) { result = new HashMap(); } if (needResolve) { str = resolveDynamicPropnames(str, resolveRes); } String[] arr = separateString(str, itemDelimiter, trimItem); for (int i = 0; i < arr.length; i++) { int index = arr[i].indexOf(kvDelimiter); if (index != -1) { String k = arr[i].substring(0, index); String v = arr[i].substring(index + 1); result.put(trimItem ? k.trim() : k, trimItem ? v.trim() : v); } else if (arr[i].length() > 0) { if (trimItem) { String trimStr = arr[i].trim(); if (trimStr.length() > 0) { result.put(trimStr, ""); } } else { result.put(arr[i], ""); } } } return result; } public static void close(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (IOException e) { } } } public static String toString(Object obj) { if (obj == null || obj instanceof String) return (String) obj; return obj.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy