content: package cn.hotapk.fastandrutils.utils;
  
  
  import android.util.Base64;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.math.BigInteger;
  import java.security.DigestInputStream;
  import java.security.InvalidKeyException;
  import java.security.MessageDigest;
  import java.security.NoSuchAlgorithmException;
  import java.security.SecureRandom;
  
  import javax.crypto.Cipher;
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  
  /**
   * @author laijian
   * @version 2017/9/20
   * @Copyright (C)下午2:54 , www.hotapk.cn
   * 加密相关
   */
  public final class FEncryptUtils {
  
      private static final String DES_Algorithm = "DES";
      ///////////////////////////////////////////////////////////////////////////
      // 哈希加密相关
      ///////////////////////////////////////////////////////////////////////////
      private static final String TripleDES_Algorithm = "DESede";
      private static final String AES_Algorithm = "AES";
      private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
      /**
       * DES转变
       * <p>法算法名称/加密模式/填充方式</p>
       * <p>加密模式有：电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB</p>
       * <p>填充方式有：NoPadding、ZerosPadding、PKCS5Padding</p>
       */
      public static String DES_Transformation = "DES/ECB/NoPadding";
      /**
       * 3DES转变
       * <p>法算法名称/加密模式/填充方式</p>
       * <p>加密模式有：电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB</p>
       * <p>填充方式有：NoPadding、ZerosPadding、PKCS5Padding</p>
       */
      public static String TripleDES_Transformation = "DESede/ECB/NoPadding";
      /**
       * AES转变
       * <p>法算法名称/加密模式/填充方式</p>
       * <p>加密模式有：电子密码本模式ECB、加密块链模式CBC、加密反馈模式CFB、输出反馈模式OFB</p>
       * <p>填充方式有：NoPadding、ZerosPadding、PKCS5Padding</p>
       */
      public static String AES_Transformation = "AES/ECB/NoPadding";
  
      private FEncryptUtils() {
  
      }
  
      /**
       * MD2加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptMD2ToString(final String data) {
          return encryptMD2ToString(data.getBytes());
      }
  
      /**
       * MD2加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptMD2ToString(final byte[] data) {
          return bytes2HexString(encryptMD2(data));
      }
  
      /**
       * MD2加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptMD2(final byte[] data) {
          return hashTemplate(data, "MD2");
      }
  
      /**
       * MD5加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptMD5ToString(final String data) {
          return encryptMD5ToString(data.getBytes());
      }
  
      /**
       * MD5加密
       *
       * @param data 明文字符串
       * @param salt 盐
       * @return 16进制加盐密文
       */
      public static String encryptMD5ToString(final String data, final String salt) {
          return bytes2HexString(encryptMD5((data + salt).getBytes()));
      }
  
      /**
       * MD5加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptMD5ToString(final byte[] data) {
          return bytes2HexString(encryptMD5(data));
      }
  
      /**
       * MD5加密
       *
       * @param data 明文字节数组
       * @param salt 盐字节数组
       * @return 16进制加盐密文
       */
      public static String encryptMD5ToString(final byte[] data, final byte[] salt) {
          if (data == null || salt == null) return null;
          byte[] dataSalt = new byte[data.length + salt.length];
          System.arraycopy(data, 0, dataSalt, 0, data.length);
          System.arraycopy(salt, 0, dataSalt, data.length, salt.length);
          return bytes2HexString(encryptMD5(dataSalt));
      }
  
      /**
       * MD5加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptMD5(final byte[] data) {
          return hashTemplate(data, "MD5");
      }
  
      /**
       * MD5加密文件
       *
       * @param filePath 文件路径
       * @return 文件的16进制密文
       */
      public static String encryptMD5File2String(final String filePath) {
          File file = isSpace(filePath) ? null : new File(filePath);
          return encryptMD5File2String(file);
      }
  
      /**
       * MD5加密文件
       *
       * @param filePath 文件路径
       * @return 文件的MD5校验码
       */
      public static byte[] encryptMD5File(final String filePath) {
          File file = isSpace(filePath) ? null : new File(filePath);
          return encryptMD5File(file);
      }
  
      /**
       * MD5加密文件
       *
       * @param file 文件
       * @return 文件的16进制密文
       */
      public static String encryptMD5File2String(final File file) {
          return bytes2HexString(encryptMD5File(file));
      }
  
      /**
       * MD5加密文件
       *
       * @param file 文件
       * @return 文件的MD5校验码
       */
      public static byte[] encryptMD5File(final File file) {
          if (file == null) return null;
          FileInputStream fis = null;
          DigestInputStream digestInputStream;
          try {
              fis = new FileInputStream(file);
              MessageDigest md = MessageDigest.getInstance("MD5");
              digestInputStream = new DigestInputStream(fis, md);
              byte[] buffer = new byte[256 * 1024];
              while (true) {
                  if (!(digestInputStream.read(buffer) > 0)) break;
              }
              md = digestInputStream.getMessageDigest();
              return md.digest();
          } catch (NoSuchAlgorithmException | IOException e) {
              e.printStackTrace();
              return null;
          } finally {
              FCloseUtils.closeIO(fis);
          }
      }
  
      /**
       * SHA1加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptSHA1ToString(final String data) {
          return encryptSHA1ToString(data.getBytes());
      }
  
      /**
       * SHA1加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptSHA1ToString(final byte[] data) {
          return bytes2HexString(encryptSHA1(data));
      }
  
      /**
       * SHA1加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptSHA1(final byte[] data) {
          return hashTemplate(data, "SHA1");
      }
  
      /**
       * SHA224加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptSHA224ToString(final String data) {
          return encryptSHA224ToString(data.getBytes());
      }
  
      /**
       * SHA224加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptSHA224ToString(final byte[] data) {
          return bytes2HexString(encryptSHA224(data));
      }
  
      /**
       * SHA224加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptSHA224(final byte[] data) {
          return hashTemplate(data, "SHA224");
      }
  
      /**
       * SHA256加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptSHA256ToString(final String data) {
          return encryptSHA256ToString(data.getBytes());
      }
  
      /**
       * SHA256加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptSHA256ToString(final byte[] data) {
          return bytes2HexString(encryptSHA256(data));
      }
  
      /**
       * SHA256加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptSHA256(final byte[] data) {
          return hashTemplate(data, "SHA256");
      }
  
      /**
       * SHA384加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptSHA384ToString(final String data) {
          return encryptSHA384ToString(data.getBytes());
      }
  
      /**
       * SHA384加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptSHA384ToString(final byte[] data) {
          return bytes2HexString(encryptSHA384(data));
      }
  
      /**
       * SHA384加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptSHA384(final byte[] data) {
          return hashTemplate(data, "SHA384");
      }
  
      /**
       * SHA512加密
       *
       * @param data 明文字符串
       * @return 16进制密文
       */
      public static String encryptSHA512ToString(final String data) {
          return encryptSHA512ToString(data.getBytes());
      }
  
      /**
       * SHA512加密
       *
       * @param data 明文字节数组
       * @return 16进制密文
       */
      public static String encryptSHA512ToString(final byte[] data) {
          return bytes2HexString(encryptSHA512(data));
      }
  
      /**
       * SHA512加密
       *
       * @param data 明文字节数组
       * @return 密文字节数组
       */
      public static byte[] encryptSHA512(final byte[] data) {
          return hashTemplate(data, "SHA512");
      }
  
      /**
       * hash加密模板
       *
       * @param data      数据
       * @param algorithm 加密算法
       * @return 密文字节数组
       */
      private static byte[] hashTemplate(final byte[] data, final String algorithm) {
          if (data == null || data.length <= 0) return null;
          try {
              MessageDigest md = MessageDigest.getInstance(algorithm);
              md.update(data);
              return md.digest();
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * HmacMD5加密
       *
       * @param data 明文字符串
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacMD5ToString(final String data, final String key) {
          return encryptHmacMD5ToString(data.getBytes(), key.getBytes());
      }
  
      /**
       * HmacMD5加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacMD5ToString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptHmacMD5(data, key));
      }
  
      /**
       * HmacMD5加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 密文字节数组
       */
      public static byte[] encryptHmacMD5(final byte[] data, final byte[] key) {
          return hmacTemplate(data, key, "HmacMD5");
      }
  
      /**
       * HmacSHA1加密
       *
       * @param data 明文字符串
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA1ToString(final String data, final String key) {
          return encryptHmacSHA1ToString(data.getBytes(), key.getBytes());
      }
  
      /**
       * HmacSHA1加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA1ToString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptHmacSHA1(data, key));
      }
  
      /**
       * HmacSHA1加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 密文字节数组
       */
      public static byte[] encryptHmacSHA1(final byte[] data, final byte[] key) {
          return hmacTemplate(data, key, "HmacSHA1");
      }
  
      /**
       * HmacSHA224加密
       *
       * @param data 明文字符串
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA224ToString(final String data, final String key) {
          return encryptHmacSHA224ToString(data.getBytes(), key.getBytes());
      }
  
      /**
       * HmacSHA224加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA224ToString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptHmacSHA224(data, key));
      }
  
      /**
       * HmacSHA224加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 密文字节数组
       */
      public static byte[] encryptHmacSHA224(final byte[] data, final byte[] key) {
          return hmacTemplate(data, key, "HmacSHA224");
      }
  
      /**
       * HmacSHA256加密
       *
       * @param data 明文字符串
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA256ToString(final String data, final String key) {
          return encryptHmacSHA256ToString(data.getBytes(), key.getBytes());
      }
  
      /**
       * HmacSHA256加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA256ToString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptHmacSHA256(data, key));
      }
  
      /**
       * HmacSHA256加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 密文字节数组
       */
      public static byte[] encryptHmacSHA256(final byte[] data, final byte[] key) {
          return hmacTemplate(data, key, "HmacSHA256");
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // DES加密相关
      ///////////////////////////////////////////////////////////////////////////
  
      /**
       * HmacSHA384加密
       *
       * @param data 明文字符串
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA384ToString(final String data, final String key) {
          return encryptHmacSHA384ToString(data.getBytes(), key.getBytes());
      }
  
      /**
       * HmacSHA384加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA384ToString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptHmacSHA384(data, key));
      }
  
      /**
       * HmacSHA384加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 密文字节数组
       */
      public static byte[] encryptHmacSHA384(final byte[] data, final byte[] key) {
          return hmacTemplate(data, key, "HmacSHA384");
      }
  
      /**
       * HmacSHA512加密
       *
       * @param data 明文字符串
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA512ToString(final String data, final String key) {
          return encryptHmacSHA512ToString(data.getBytes(), key.getBytes());
      }
  
      /**
       * HmacSHA512加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 16进制密文
       */
      public static String encryptHmacSHA512ToString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptHmacSHA512(data, key));
      }
  
      /**
       * HmacSHA512加密
       *
       * @param data 明文字节数组
       * @param key  秘钥
       * @return 密文字节数组
       */
      public static byte[] encryptHmacSHA512(final byte[] data, final byte[] key) {
          return hmacTemplate(data, key, "HmacSHA512");
      }
  
      /**
       * Hmac加密模板
       *
       * @param data      数据
       * @param key       秘钥
       * @param algorithm 加密算法
       * @return 密文字节数组
       */
      private static byte[] hmacTemplate(final byte[] data, final byte[] key, final String algorithm) {
          if (data == null || data.length == 0 || key == null || key.length == 0) return null;
          try {
              SecretKeySpec secretKey = new SecretKeySpec(key, algorithm);
              Mac mac = Mac.getInstance(algorithm);
              mac.init(secretKey);
              return mac.doFinal(data);
          } catch (InvalidKeyException | NoSuchAlgorithmException e) {
              e.printStackTrace();
              return null;
          }
      }
  
      /**
       * DES加密后转为Base64编码
       *
       * @param data 明文
       * @param key  8字节秘钥
       * @return Base64密文
       */
      public static byte[] encryptDES2Base64(final byte[] data, final byte[] key) {
          return base64Encode(encryptDES(data, key));
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // 3DES加密相关
      ///////////////////////////////////////////////////////////////////////////
  
      /**
       * DES加密后转为16进制
       *
       * @param data 明文
       * @param key  8字节秘钥
       * @return 16进制密文
       */
      public static String encryptDES2HexString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptDES(data, key));
      }
  
      /**
       * DES加密
       *
       * @param data 明文
       * @param key  8字节秘钥
       * @return 密文
       */
      public static byte[] encryptDES(final byte[] data, final byte[] key) {
          return desTemplate(data, key, DES_Algorithm, DES_Transformation, true);
      }
  
      /**
       * DES解密Base64编码密文
       *
       * @param data Base64编码密文
       * @param key  8字节秘钥
       * @return 明文
       */
      public static byte[] decryptBase64DES(final byte[] data, final byte[] key) {
          return decryptDES(base64Decode(data), key);
      }
  
      /**
       * DES解密16进制密文
       *
       * @param data 16进制密文
       * @param key  8字节秘钥
       * @return 明文
       */
      public static byte[] decryptHexStringDES(final String data, final byte[] key) {
          return decryptDES(hexString2Bytes(data), key);
      }
  
      /**
       * DES解密
       *
       * @param data 密文
       * @param key  8字节秘钥
       * @return 明文
       */
      public static byte[] decryptDES(final byte[] data, final byte[] key) {
          return desTemplate(data, key, DES_Algorithm, DES_Transformation, false);
      }
  
      /**
       * 3DES加密后转为Base64编码
       *
       * @param data 明文
       * @param key  24字节秘钥
       * @return Base64密文
       */
      public static byte[] encrypt3DES2Base64(final byte[] data, final byte[] key) {
          return base64Encode(encrypt3DES(data, key));
      }
  
      /**
       * 3DES加密后转为16进制
       *
       * @param data 明文
       * @param key  24字节秘钥
       * @return 16进制密文
       */
      public static String encrypt3DES2HexString(final byte[] data, final byte[] key) {
          return bytes2HexString(encrypt3DES(data, key));
      }
  
      /**
       * 3DES加密
       *
       * @param data 明文
       * @param key  24字节密钥
       * @return 密文
       */
      public static byte[] encrypt3DES(final byte[] data, final byte[] key) {
          return desTemplate(data, key, TripleDES_Algorithm, TripleDES_Transformation, true);
      }
  
      ///////////////////////////////////////////////////////////////////////////
      // AES加密相关
      ///////////////////////////////////////////////////////////////////////////
  
      /**
       * 3DES解密Base64编码密文
       *
       * @param data Base64编码密文
       * @param key  24字节秘钥
       * @return 明文
       */
      public static byte[] decryptBase64_3DES(final byte[] data, final byte[] key) {
          return decrypt3DES(base64Decode(data), key);
      }
  
      /**
       * 3DES解密16进制密文
       *
       * @param data 16进制密文
       * @param key  24字节秘钥
       * @return 明文
       */
      public static byte[] decryptHexString3DES(final String data, final byte[] key) {
          return decrypt3DES(hexString2Bytes(data), key);
      }
  
      /**
       * 3DES解密
       *
       * @param data 密文
       * @param key  24字节密钥
       * @return 明文
       */
      public static byte[] decrypt3DES(final byte[] data, final byte[] key) {
          return desTemplate(data, key, TripleDES_Algorithm, TripleDES_Transformation, false);
      }
  
      /**
       * AES加密后转为Base64编码
       *
       * @param data 明文
       * @param key  16、24、32字节秘钥
       * @return Base64密文
       */
      public static byte[] encryptAES2Base64(final byte[] data, final byte[] key) {
          return base64Encode(encryptAES(data, key));
      }
  
      /**
       * AES加密后转为16进制
       *
       * @param data 明文
       * @param key  16、24、32字节秘钥
       * @return 16进制密文
       */
      public static String encryptAES2HexString(final byte[] data, final byte[] key) {
          return bytes2HexString(encryptAES(data, key));
      }
  
      /**
       * AES加密
       *
       * @param data 明文
       * @param key  16、24、32字节秘钥
       * @return 密文
       */
      public static byte[] encryptAES(final byte[] data, final byte[] key) {
          return desTemplate(data, key, AES_Algorithm, AES_Transformation, true);
      }
  
      /**
       * AES解密Base64编码密文
       *
       * @param data Base64编码密文
       * @param key  16、24、32字节秘钥
       * @return 明文
       */
      public static byte[] decryptBase64AES(final byte[] data, final byte[] key) {
          return decryptAES(base64Decode(data), key);
      }
  
      /**
       * AES解密16进制密文
       *
       * @param data 16进制密文
       * @param key  16、24、32字节秘钥
       * @return 明文
       */
      public static byte[] decryptHexStringAES(final String data, final byte[] key) {
          return decryptAES(hexString2Bytes(data), key);
      }
  
      /**
       * AES解密
       *
       * @param data 密文
       * @param key  16、24、32字节秘钥
       * @return 明文
       */
      public static byte[] decryptAES(final byte[] data, final byte[] key) {
          return desTemplate(data, key, AES_Algorithm, AES_Transformation, false);
      }
  
      /**
       * DES加密模板
       *
       * @param data           数据
       * @param key            秘钥
       * @param algorithm      加密算法
       * @param transformation 转变
       * @param isEncrypt      {@code true}: 加密 {@code false}: 解密
       * @return 密文或者明文，适用于DES，3DES，AES
       */
      public static byte[] desTemplate(final byte[] data, final byte[] key, final String algorithm, final String transformation, final boolean isEncrypt) {
          if (data == null || data.length == 0 || key == null || key.length == 0) return null;
          try {
              SecretKeySpec keySpec = new SecretKeySpec(key, algorithm);
              Cipher cipher = Cipher.getInstance(transformation);
              SecureRandom random = new SecureRandom();
              cipher.init(isEncrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE, keySpec, random);
              return cipher.doFinal(data);
          } catch (Throwable e) {
              e.printStackTrace();
              return null;
          }
      }
  
      private static String bytes2HexString(final byte[] bytes) {
          if (bytes == null) return null;
          int len = bytes.length;
          if (len <= 0) return null;
          char[] ret = new char[len << 1];
          for (int i = 0, j = 0; i < len; i++) {
              ret[j++] = hexDigits[bytes[i] >>> 4 & 0x0f];
              ret[j++] = hexDigits[bytes[i] & 0x0f];
          }
          return new String(ret);
      }
  
      private static byte[] hexString2Bytes(String hexString) {
          if (isSpace(hexString)) return null;
          int len = hexString.length();
          if (len % 2 != 0) {
              hexString = "0" + hexString;
              len = len + 1;
          }
          char[] hexBytes = hexString.toUpperCase().toCharArray();
          byte[] ret = new byte[len >> 1];
          for (int i = 0; i < len; i += 2) {
              ret[i >> 1] = (byte) (hex2Dec(hexBytes[i]) << 4 | hex2Dec(hexBytes[i + 1]));
          }
          return ret;
      }
  
      private static int hex2Dec(final char hexChar) {
          if (hexChar >= '0' && hexChar <= '9') {
              return hexChar - '0';
          } else if (hexChar >= 'A' && hexChar <= 'F') {
              return hexChar - 'A' + 10;
          } else {
              throw new IllegalArgumentException();
          }
      }
  
      private static byte[] base64Encode(final byte[] input) {
          return Base64.encode(input, Base64.NO_WRAP);
      }
  
      private static byte[] base64Decode(final byte[] input) {
          return Base64.decode(input, Base64.NO_WRAP);
      }
  
      /**
       * String转Base64字符串
       *
       * @param message the message
       * @return the string
       */
      public static String stringToBase64(String message) {
          return Base64.encodeToString(message.getBytes(), Base64.DEFAULT);
      }
  
      /**
       * Base64字符串转bytes
       *
       * @param base64Message the message
       * @return the string
       */
      public static byte[] base64ToByte(String base64Message) {
          return Base64.decode(base64Message, Base64.DEFAULT);
      }
  
      /**
       * 对字符串md5加密
       *
       * @param str
       * @return
       */
      public static String string2MD5(String str) {
          try {
              // 生成一个MD5加密计算摘要
              MessageDigest md = MessageDigest.getInstance("MD5");
              // 计算md5函数
              md.update(str.getBytes());
              // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
              // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
              return new BigInteger(1, md.digest()).toString(16);
          } catch (Exception e) {
              return "";
          }
      }
  
      private static boolean isSpace(final String s) {
          if (s == null) return true;
          for (int i = 0, len = s.length(); i < len; ++i) {
              if (!Character.isWhitespace(s.charAt(i))) {
                  return false;
              }
          }
          return true;
      }
  }
  