java 常用工具类的使用<四>
一、连接数据库的综合类
1 package com.itjh.javaUtil; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.PreparedStatement; 6 import java.sql.ResultSet; 7 import java.sql.ResultSetMetaData; 8 import java.sql.SQLException; 9 import java.util.ArrayList; 10 import java.util.Collections; 11 import java.util.HashMap; 12 import java.util.List; 13 import java.util.Map; 14 15 import org.apache.commons.dbcp.ConnectionFactory; 16 import org.apache.commons.dbcp.DriverManagerConnectionFactory; 17 import org.apache.commons.dbcp.PoolableConnectionFactory; 18 import org.apache.commons.dbcp.PoolingDriver; 19 import org.apache.commons.dbutils.DbUtils; 20 import org.apache.commons.dbutils.QueryRunner; 21 import org.apache.commons.dbutils.handlers.MapListHandler; 22 import org.apache.commons.pool.ObjectPool; 23 import org.apache.commons.pool.impl.GenericObjectPool; 24 25 /** 26 * 连接数据库的综合类。</br> 27 * 依赖jar包:commons.dbcp-1.4,commons.dbutils-1.3,commons.pool-1.5.4包。 28 * 29 * @author 宋立君 30 * @date 2014年07月03日 31 */ 32 33 public class DBUtil { 34 35 private String dri = null; 36 private String url = null; 37 private String username = null; 38 private String password = null; 39 private String poolName = null; // 连接池名称 40 private ObjectPool connectionPool = null; // 连接池 41 // 对应的定时查询类 42 private QueryThread queryThread = null; 43 44 /** 45 * 功能:构造函数 46 * 47 * @author 宋立君 48 * @date 2014年07月03日 49 * @param dri 50 * 驱动全类名,例如:com.mysql.jdbc.Driver。 51 * @param url 52 * 数据库url连接,例如: 53 * "jdbc:mysql://127.0.0.1:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8" 54 * @param userName 55 * 数据库用户名,例如:root 56 * @param password 57 * 数据库密码,例如:abc 58 * @param poolName 59 * 创建的数据库连接池的名称,例如mypool,注意一个web容器此名称不能重复。 60 */ 61 public DBUtil(String dri, String url, String userName, String password, 62 String poolName) { 63 this.dri = dri; 64 this.url = url; 65 this.username = userName; 66 this.password = password; 67 this.poolName = poolName; 68 } 69 70 /** 71 * 执行sql。 72 * 73 * @param conn 74 * 连接 75 * @param pstm 76 * PreparedStatement 77 * @return int 执行sql对应的影响行。 78 * @throws SQLException 79 * @author 宋立君 80 * @date 2014年07月03日 81 */ 82 public int execute(Connection conn, PreparedStatement pstm) 83 throws SQLException { 84 try { 85 return pstm.executeUpdate(); 86 } finally { 87 Close(conn); 88 } 89 } 90 91 /** 92 * 查询sql。 93 * 94 * @param conn 95 * 连接 96 * @param pstm 97 * PreparedStatement 98 * @return List<Map<String,Object>> 查询的结果集 99 * @throws SQLException 100 * @author 宋立君 101 * @date 2014年07月03日 102 */ 103 public List<Map<String, Object>> query(Connection conn, 104 PreparedStatement pstm) throws SQLException { 105 try { 106 return resultSetToList(pstm.executeQuery()); 107 } finally { 108 Close(conn); 109 } 110 } 111 112 /** 113 * 功能:ResultSet 转为List<Map<String,Object>> 114 * 115 * 116 * @param rs 117 * ResultSet 原始数据集 118 * @return List<Map<String,Object>> 119 * @throws java.sql.SQLException 120 * @author 宋立君 121 * @date 2014年07月03日 122 */ 123 private List<Map<String, Object>> resultSetToList(ResultSet rs) 124 throws java.sql.SQLException { 125 if (rs == null) 126 return Collections.EMPTY_LIST; 127 128 ResultSetMetaData md = rs.getMetaData(); // 得到结果集(rs)的结构信息,比如字段数、字段名等 129 int columnCount = md.getColumnCount(); // 返回此 ResultSet 对象中的列数 130 List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); 131 Map<String, Object> rowData = new HashMap<String, Object>(); 132 while (rs.next()) { 133 rowData = new HashMap<String, Object>(columnCount); 134 for (int i = 1; i <= columnCount; i++) { 135 rowData.put(md.getColumnName(i), rs.getObject(i)); 136 } 137 list.add(rowData); 138 } 139 return list; 140 } 141 142 /** 143 * 查询sql语句。 144 * 145 * @param sql 146 * 被执行的sql语句 147 * @return List<Map<String,Object>> 148 * @throws SQLException 149 * @author 宋立君 150 * @date 2014年07月03日 151 */ 152 public List<Map<String, Object>> query(String sql) throws SQLException { 153 List<Map<String, Object>> results = null; 154 Connection conn = null; 155 try { 156 conn = getConnection(); 157 QueryRunner qr = new QueryRunner(); 158 results = qr.query(conn, sql, new MapListHandler()); 159 } finally { 160 Close(conn); 161 } 162 return results; 163 } 164 165 /** 166 * 根据参数查询sql语句 167 * 168 * @param sql 169 * sql语句 170 * @param param 171 * 参数 172 * @return List<Map<String,Object>> 173 * @throws SQLException 174 * @author 宋立君 175 * @date 2014年07月03日 176 */ 177 public List<Map<String, Object>> query(String sql, Object param) 178 throws SQLException { 179 List<Map<String, Object>> results = null; 180 Connection conn = null; 181 try { 182 conn = getConnection(); 183 QueryRunner qr = new QueryRunner(); 184 results = (List<Map<String, Object>>) qr.query(conn, sql, param, 185 new MapListHandler()); 186 } catch (SQLException e) { 187 e.printStackTrace(); 188 } finally { 189 Close(conn); 190 } 191 return results; 192 } 193 194 /** 195 * 执行sql语句 196 * 197 * @param sql 198 * 被执行的sql语句 199 * @return 受影响的行 200 * @throws Exception 201 * @author 宋立君 202 * @date 2014年07月03日 203 */ 204 public int execute(String sql) throws Exception { 205 Connection conn = getConnection(); 206 int rows = 0; 207 try { 208 QueryRunner qr = new QueryRunner(); 209 rows = qr.update(conn, sql); 210 } finally { 211 Close(conn); 212 } 213 return rows; 214 } 215 216 /** 217 * 执行含参数的sql语句 218 * 219 * @param sql 220 * 被执行的sql语句 221 * @param params 222 * 参数 223 * @return 返回受影响的行 224 * @throws Exception 225 * @author 宋立君 226 * @date 2014年07月03日 227 */ 228 public int execute(String sql, Object[] params) throws Exception { 229 Connection conn = getConnection(); 230 int rows = 0; 231 try { 232 QueryRunner qr = new QueryRunner(); 233 rows = qr.update(conn, sql, params); 234 } finally { 235 Close(conn); 236 } 237 return rows; 238 } 239 240 /** 241 * 关闭连接 242 * 243 * @param conn 244 * @throws SQLException 245 * @author 宋立君 246 * @date 2014年07月03日 247 */ 248 public void Close(Connection conn) throws SQLException { 249 if (conn != null) { 250 conn.close(); 251 } 252 DbUtils.closeQuietly(conn); 253 } 254 255 /** 256 * 启动连接池 257 * 258 * @author 宋立君 259 * @date 2014年07月03日 260 */ 261 private void StartPool() { 262 try { 263 Class.forName(dri); 264 } catch (ClassNotFoundException e1) { 265 e1.printStackTrace(); 266 } 267 if (connectionPool != null) { 268 ShutdownPool(); 269 } 270 try { 271 connectionPool = new GenericObjectPool(null); 272 ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( 273 url, username, password); 274 PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory( 275 connectionFactory, connectionPool, null, "SELECT 1", false, 276 true); 277 Class.forName("org.apache.commons.dbcp.PoolingDriver"); 278 PoolingDriver driver = (PoolingDriver) DriverManager 279 .getDriver("jdbc:apache:commons:dbcp:"); 280 driver.registerPool(poolName, poolableConnectionFactory.getPool()); 281 282 } catch (Exception e) { 283 e.printStackTrace(); 284 } 285 // 开启查询程序 286 queryThread = new QueryThread(this); 287 queryThread.start(); 288 } 289 290 /** 291 * 关闭连接池 292 * 293 * @author 宋立君 294 * @date 2014年07月03日 295 */ 296 private void ShutdownPool() { 297 try { 298 PoolingDriver driver = (PoolingDriver) DriverManager 299 .getDriver("jdbc:apache:commons:dbcp:"); 300 driver.closePool(poolName); 301 // 关闭定时查询 302 queryThread.setStartQuery(false); 303 } catch (SQLException e) { 304 e.printStackTrace(); 305 } 306 } 307 308 /** 309 * 得到一个连接 310 * 311 * @return 312 * @author 宋立君 313 * @date 2014年07月03日 314 */ 315 public synchronized Connection getConnection() { 316 Connection conn = null; 317 try { 318 if (connectionPool == null) 319 StartPool(); 320 conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:" 321 + poolName); 322 } catch (Exception e) { 323 e.printStackTrace(); 324 } 325 return conn; 326 } 327 } 328 329 /** 330 * 当连接池启动后会自动定时查询数据库,防止数据库连接超时。 331 * 332 * @author 宋立君 333 * @date 2014年07月03日 334 */ 335 class QueryThread extends Thread { 336 337 private DBUtil dbUtil = null; 338 // 是否开启查询 339 private boolean startQuery = true; 340 341 /** 342 * 功能:对应的数据库连接。 343 * 344 * @author 宋立君 345 * @date 2014年07月03日 346 * @param dbUtil 347 * 数据库连接 348 */ 349 public QueryThread(DBUtil dbUtil) { 350 this.dbUtil = dbUtil; 351 } 352 353 public void run() { 354 while (true) { 355 try { 356 if (startQuery) { 357 this.dbUtil.query("select 1"); 358 } 359 // System.out.println(startQuery+" 123"); 360 } catch (Exception e) { 361 e.printStackTrace(); 362 } finally { 363 try { 364 Thread.sleep(120000); 365 } catch (InterruptedException e) { 366 e.printStackTrace(); 367 } 368 } 369 } 370 } 371 372 public void setStartQuery(boolean startQuery) { 373 // System.out.println("startQuery shut:"+startQuery); 374 this.startQuery = startQuery; 375 } 376 }
二、DES加密和解密
1 package com.itjh.javaUtil; 2 3 import java.io.UnsupportedEncodingException; 4 import java.security.InvalidKeyException; 5 import java.security.NoSuchAlgorithmException; 6 import java.security.SecureRandom; 7 import java.security.spec.InvalidKeySpecException; 8 9 import javax.crypto.BadPaddingException; 10 import javax.crypto.Cipher; 11 import javax.crypto.IllegalBlockSizeException; 12 import javax.crypto.KeyGenerator; 13 import javax.crypto.NoSuchPaddingException; 14 import javax.crypto.SecretKey; 15 import javax.crypto.SecretKeyFactory; 16 import javax.crypto.spec.DESKeySpec; 17 18 /** 19 * DES加密和解密。 20 * 21 * @author 宋立君 22 * @date 2014年07月03日 23 */ 24 public class DESUtil { 25 26 /** 安全密钥 */ 27 private String keyData = "ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstwxyz0123456789-_."; 28 29 /** 30 * 功能:构造 31 * 32 * @author 宋立君 33 * @date 2014年07月03日 34 */ 35 public DESUtil() { 36 } 37 38 /** 39 * 功能:构造 40 * 41 * @author 宋立君 42 * @date 2014年07月03日 43 * @param keyData 44 * key 45 */ 46 public DESUtil(String key) { 47 this.keyData = key; 48 } 49 50 /** 51 * 功能:加密 (UTF-8) 52 * 53 * @author 宋立君 54 * @date 2014年07月03日 55 * @param source 56 * 源字符串 57 * @param charSet 58 * 编码 59 * @return String 60 * @throws UnsupportedEncodingException 61 * 编码异常 62 */ 63 public String encrypt(String source) throws UnsupportedEncodingException { 64 return encrypt(source, "UTF-8"); 65 } 66 67 /** 68 * 69 * 功能:解密 (UTF-8) 70 * 71 * @author 宋立君 72 * @date 2014年07月03日 73 * @param encryptedData 74 * 被加密后的字符串 75 * @return String 76 * @throws UnsupportedEncodingException 77 * 编码异常 78 */ 79 public String decrypt(String encryptedData) 80 throws UnsupportedEncodingException { 81 return decrypt(encryptedData, "UTF-8"); 82 } 83 84 /** 85 * 功能:加密 86 * 87 * @author 宋立君 88 * @date 2014年07月03日 89 * @param source 90 * 源字符串 91 * @param charSet 92 * 编码 93 * @return String 94 * @throws UnsupportedEncodingException 95 * 编码异常 96 */ 97 public String encrypt(String source, String charSet) 98 throws UnsupportedEncodingException { 99 String encrypt = null; 100 byte[] ret = encrypt(source.getBytes(charSet)); 101 encrypt = new String(Base64.encode(ret)); 102 return encrypt; 103 } 104 105 /** 106 * 107 * 功能:解密 108 * 109 * @author 宋立君 110 * @date 2014年07月03日 111 * @param encryptedData 112 * 被加密后的字符串 113 * @param charSet 114 * 编码 115 * @return String 116 * @throws UnsupportedEncodingException 117 * 编码异常 118 */ 119 public String decrypt(String encryptedData, String charSet) 120 throws UnsupportedEncodingException { 121 String descryptedData = null; 122 byte[] ret = descrypt(Base64.decode(encryptedData.toCharArray())); 123 descryptedData = new String(ret, charSet); 124 return descryptedData; 125 } 126 127 /** 128 * 加密数据 用生成的密钥加密原始数据 129 * 130 * @param primaryData 131 * 原始数据 132 * @return byte[] 133 * @author 宋立君 134 * @date 2014年07月03日 135 */ 136 private byte[] encrypt(byte[] primaryData) { 137 138 /** 取得安全密钥 */ 139 byte rawKeyData[] = getKey(); 140 141 /** DES算法要求有一个可信任的随机数源 */ 142 SecureRandom sr = new SecureRandom(); 143 144 /** 使用原始密钥数据创建DESKeySpec对象 */ 145 DESKeySpec dks = null; 146 try { 147 dks = new DESKeySpec(keyData.getBytes()); 148 } catch (InvalidKeyException e) { 149 e.printStackTrace(); 150 } 151 152 /** 创建一个密钥工厂 */ 153 SecretKeyFactory keyFactory = null; 154 try { 155 keyFactory = SecretKeyFactory.getInstance("DES"); 156 } catch (NoSuchAlgorithmException e) { 157 e.printStackTrace(); 158 } 159 160 /** 用密钥工厂把DESKeySpec转换成一个SecretKey对象 */ 161 SecretKey key = null; 162 try { 163 key = keyFactory.generateSecret(dks); 164 } catch (InvalidKeySpecException e) { 165 e.printStackTrace(); 166 } 167 168 /** Cipher对象实际完成加密操作 */ 169 Cipher cipher = null; 170 try { 171 cipher = Cipher.getInstance("DES"); 172 } catch (NoSuchAlgorithmException e) { 173 e.printStackTrace(); 174 } catch (NoSuchPaddingException e) { 175 e.printStackTrace(); 176 } 177 178 /** 用密钥初始化Cipher对象 */ 179 try { 180 cipher.init(Cipher.ENCRYPT_MODE, key, sr); 181 } catch (InvalidKeyException e) { 182 e.printStackTrace(); 183 } 184 185 /** 正式执行加密操作 */ 186 byte encryptedData[] = null; 187 try { 188 encryptedData = cipher.doFinal(primaryData); 189 } catch (IllegalStateException e) { 190 e.printStackTrace(); 191 } catch (IllegalBlockSizeException e) { 192 e.printStackTrace(); 193 } catch (BadPaddingException e) { 194 e.printStackTrace(); 195 } 196 197 /** 返回加密数据 */ 198 return encryptedData; 199 } 200 201 /** 202 * 用密钥解密数据 203 * 204 * @param encryptedData 205 * 加密后的数据 206 * @return byte[] 207 * @author 宋立君 208 * @date 2014年07月03日 209 */ 210 private byte[] descrypt(byte[] encryptedData) { 211 212 /** DES算法要求有一个可信任的随机数源 */ 213 SecureRandom sr = new SecureRandom(); 214 215 /** 取得安全密钥 */ 216 byte rawKeyData[] = getKey(); 217 218 /** 使用原始密钥数据创建DESKeySpec对象 */ 219 DESKeySpec dks = null; 220 try { 221 dks = new DESKeySpec(keyData.getBytes()); 222 } catch (InvalidKeyException e) { 223 e.printStackTrace(); 224 } 225 226 /** 创建一个密钥工厂 */ 227 SecretKeyFactory keyFactory = null; 228 try { 229 keyFactory = SecretKeyFactory.getInstance("DES"); 230 } catch (NoSuchAlgorithmException e) { 231 e.printStackTrace(); 232 } 233 234 /** 用密钥工厂把DESKeySpec转换成一个SecretKey对象 */ 235 SecretKey key = null; 236 try { 237 key = keyFactory.generateSecret(dks); 238 } catch (InvalidKeySpecException e) { 239 e.printStackTrace(); 240 } 241 242 /** Cipher对象实际完成加密操作 */ 243 Cipher cipher = null; 244 try { 245 cipher = Cipher.getInstance("DES"); 246 } catch (NoSuchAlgorithmException e) { 247 e.printStackTrace(); 248 } catch (NoSuchPaddingException e) { 249 e.printStackTrace(); 250 } 251 252 /** 用密钥初始化Cipher对象 */ 253 try { 254 cipher.init(Cipher.DECRYPT_MODE, key, sr); 255 } catch (InvalidKeyException e) { 256 e.printStackTrace(); 257 } 258 259 /** 正式执行解密操作 */ 260 byte decryptedData[] = null; 261 try { 262 decryptedData = cipher.doFinal(encryptedData); 263 } catch (IllegalStateException e) { 264 e.printStackTrace(); 265 } catch (IllegalBlockSizeException e) { 266 e.printStackTrace(); 267 } catch (BadPaddingException e) { 268 e.printStackTrace(); 269 } 270 271 return decryptedData; 272 } 273 274 /** 275 * 取得安全密钥 此方法作废,因为每次key生成都不一样导致解密加密用的密钥都不一样, 从而导致Given final block not 276 * properly padded错误. 277 * 278 * @return byte数组 279 * @author 宋立君 280 * @date 2014年07月03日 281 */ 282 private byte[] getKey() { 283 284 /** DES算法要求有一个可信任的随机数源 */ 285 SecureRandom sr = new SecureRandom(); 286 287 /** 为我们选择的DES算法生成一个密钥生成器对象 */ 288 KeyGenerator kg = null; 289 try { 290 kg = KeyGenerator.getInstance("DES"); 291 } catch (NoSuchAlgorithmException e) { 292 e.printStackTrace(); 293 } 294 kg.init(sr); 295 296 /** 生成密钥工具类 */ 297 SecretKey key = kg.generateKey(); 298 299 /** 生成密钥byte数组 */ 300 byte rawKeyData[] = key.getEncoded(); 301 302 return rawKeyData; 303 } 304 305 }
Base64.java
1 package com.itjh.javaUtil; 2 3 import java.io.*; 4 5 /** 6 * Base64 编码和解码。 7 * 8 * @author 宋立君 9 * @date 2014年07月03日 10 */ 11 public class Base64 { 12 13 public Base64() { 14 } 15 16 /** 17 * 功能:编码字符串 18 * 19 * @author 宋立君 20 * @date 2014年07月03日 21 * @param data 22 * 源字符串 23 * @return String 24 */ 25 public static String encode(String data) { 26 return new String(encode(data.getBytes())); 27 } 28 29 /** 30 * 功能:解码字符串 31 * 32 * @author 宋立君 33 * @date 2014年07月03日 34 * @param data 35 * 源字符串 36 * @return String 37 */ 38 public static String decode(String data) { 39 return new String(decode(data.toCharArray())); 40 } 41 42 /** 43 * 功能:编码byte[] 44 * 45 * @author 宋立君 46 * @date 2014年07月03日 47 * @param data 48 * 源 49 * @return char[] 50 */ 51 public static char[] encode(byte[] data) { 52 char[] out = new char[((data.length + 2) / 3) * 4]; 53 for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { 54 boolean quad = false; 55 boolean trip = false; 56 57 int val = (0xFF & (int) data[i]); 58 val <<= 8; 59 if ((i + 1) < data.length) { 60 val |= (0xFF & (int) data[i + 1]); 61 trip = true; 62 } 63 val <<= 8; 64 if ((i + 2) < data.length) { 65 val |= (0xFF & (int) data[i + 2]); 66 quad = true; 67 } 68 out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)]; 69 val >>= 6; 70 out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)]; 71 val >>= 6; 72 out[index + 1] = alphabet[val & 0x3F]; 73 val >>= 6; 74 out[index + 0] = alphabet[val & 0x3F]; 75 } 76 return out; 77 } 78 79 /** 80 * 功能:解码 81 * 82 * @author 宋立君 83 * @date 2014年07月03日 84 * @param data 85 * 编码后的字符数组 86 * @return byte[] 87 */ 88 public static byte[] decode(char[] data) { 89 90 int tempLen = data.length; 91 for (int ix = 0; ix < data.length; ix++) { 92 if ((data[ix] > 255) || codes[data[ix]] < 0) { 93 --tempLen; // ignore non-valid chars and padding 94 } 95 } 96 // calculate required length: 97 // -- 3 bytes for every 4 valid base64 chars 98 // -- plus 2 bytes if there are 3 extra base64 chars, 99 // or plus 1 byte if there are 2 extra. 100 101 int len = (tempLen / 4) * 3; 102 if ((tempLen % 4) == 3) { 103 len += 2; 104 } 105 if ((tempLen % 4) == 2) { 106 len += 1; 107 108 } 109 byte[] out = new byte[len]; 110 111 int shift = 0; // # of excess bits stored in accum 112 int accum = 0; // excess bits 113 int index = 0; 114 115 // we now go through the entire array (NOT using the 'tempLen' value) 116 for (int ix = 0; ix < data.length; ix++) { 117 int value = (data[ix] > 255) ? -1 : codes[data[ix]]; 118 119 if (value >= 0) { // skip over non-code 120 accum <<= 6; // bits shift up by 6 each time thru 121 shift += 6; // loop, with new bits being put in 122 accum |= value; // at the bottom. 123 if (shift >= 8) { // whenever there are 8 or more shifted in, 124 shift -= 8; // write them out (from the top, leaving any 125 out[index++] = // excess at the bottom for next iteration. 126 (byte) ((accum >> shift) & 0xff); 127 } 128 } 129 } 130 131 // if there is STILL something wrong we just have to throw up now! 132 if (index != out.length) { 133 throw new Error("Miscalculated data length (wrote " + index 134 + " instead of " + out.length + ")"); 135 } 136 137 return out; 138 } 139 140 /** 141 * 功能:编码文件 142 * 143 * @author 宋立君 144 * @date 2014年07月03日 145 * @param file 146 * 源文件 147 */ 148 public static void encode(File file) throws IOException { 149 if (!file.exists()) { 150 System.exit(0); 151 } 152 153 else { 154 byte[] decoded = readBytes(file); 155 char[] encoded = encode(decoded); 156 writeChars(file, encoded); 157 } 158 file = null; 159 } 160 161 /** 162 * 功能:解码文件。 163 * 164 * @author 宋立君 165 * @date 2014年07月03日 166 * @param file 167 * 源文件 168 * @throws IOException 169 */ 170 public static void decode(File file) throws IOException { 171 if (!file.exists()) { 172 System.exit(0); 173 } else { 174 char[] encoded = readChars(file); 175 byte[] decoded = decode(encoded); 176 writeBytes(file, decoded); 177 } 178 file = null; 179 } 180 181 // 182 // code characters for values 0..63 183 // 184 private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" 185 .toCharArray(); 186 187 // 188 // lookup table for converting base64 characters to value in range 0..63 189 // 190 private static byte[] codes = new byte[256]; 191 static { 192 for (int i = 0; i < 256; i++) { 193 codes[i] = -1; 194 // LoggerUtil.debug(i + "&" + codes[i] + " "); 195 } 196 for (int i = 'A'; i <= 'Z'; i++) { 197 codes[i] = (byte) (i - 'A'); 198 // LoggerUtil.debug(i + "&" + codes[i] + " "); 199 } 200 201 for (int i = 'a'; i <= 'z'; i++) { 202 codes[i] = (byte) (26 + i - 'a'); 203 // LoggerUtil.debug(i + "&" + codes[i] + " "); 204 } 205 for (int i = '0'; i <= '9'; i++) { 206 codes[i] = (byte) (52 + i - '0'); 207 // LoggerUtil.debug(i + "&" + codes[i] + " "); 208 } 209 codes['+'] = 62; 210 codes['/'] = 63; 211 } 212 213 private static byte[] readBytes(File file) throws IOException { 214 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 215 byte[] b = null; 216 InputStream fis = null; 217 InputStream is = null; 218 try { 219 fis = new FileInputStream(file); 220 is = new BufferedInputStream(fis); 221 int count = 0; 222 byte[] buf = new byte[16384]; 223 while ((count = is.read(buf)) != -1) { 224 if (count > 0) { 225 baos.write(buf, 0, count); 226 } 227 } 228 b = baos.toByteArray(); 229 230 } finally { 231 try { 232 if (fis != null) 233 fis.close(); 234 if (is != null) 235 is.close(); 236 if (baos != null) 237 baos.close(); 238 } catch (Exception e) { 239 System.out.println(e); 240 } 241 } 242 243 return b; 244 } 245 246 private static char[] readChars(File file) throws IOException { 247 CharArrayWriter caw = new CharArrayWriter(); 248 Reader fr = null; 249 Reader in = null; 250 try { 251 fr = new FileReader(file); 252 in = new BufferedReader(fr); 253 int count = 0; 254 char[] buf = new char[16384]; 255 while ((count = in.read(buf)) != -1) { 256 if (count > 0) { 257 caw.write(buf, 0, count); 258 } 259 } 260 261 } finally { 262 try { 263 if (caw != null) 264 caw.close(); 265 if (in != null) 266 in.close(); 267 if (fr != null) 268 fr.close(); 269 } catch (Exception e) { 270 System.out.println(e); 271 } 272 } 273 274 return caw.toCharArray(); 275 } 276 277 private static void writeBytes(File file, byte[] data) throws IOException { 278 OutputStream fos = null; 279 OutputStream os = null; 280 try { 281 fos = new FileOutputStream(file); 282 os = new BufferedOutputStream(fos); 283 os.write(data); 284 285 } finally { 286 try { 287 if (os != null) 288 os.close(); 289 if (fos != null) 290 fos.close(); 291 } catch (Exception e) { 292 System.out.println(e); 293 } 294 } 295 } 296 297 private static void writeChars(File file, char[] data) throws IOException { 298 Writer fos = null; 299 Writer os = null; 300 try { 301 fos = new FileWriter(file); 302 os = new BufferedWriter(fos); 303 os.write(data); 304 305 } finally { 306 try { 307 if (os != null) 308 os.close(); 309 if (fos != null) 310 fos.close(); 311 } catch (Exception e) { 312 e.printStackTrace(); 313 } 314 } 315 } 316 317 // ///////////////////////////////////////////////// 318 // end of test code. 319 // ///////////////////////////////////////////////// 320 321 }
三、ExcelUtil工具类
1 package com.itjh.javaUtil; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.io.OutputStream; 9 import java.text.DecimalFormat; 10 import java.util.LinkedList; 11 import java.util.List; 12 13 import javax.servlet.http.HttpServletResponse; 14 15 import org.apache.poi.hssf.usermodel.HSSFCell; 16 import org.apache.poi.hssf.usermodel.HSSFRichTextString; 17 import org.apache.poi.hssf.usermodel.HSSFRow; 18 import org.apache.poi.hssf.usermodel.HSSFSheet; 19 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 20 import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 21 import org.apache.poi.ss.usermodel.Cell; 22 import org.apache.poi.ss.usermodel.DateUtil; 23 import org.apache.poi.ss.usermodel.Row; 24 import org.apache.poi.ss.usermodel.Sheet; 25 import org.apache.poi.ss.usermodel.Workbook; 26 import org.apache.poi.ss.usermodel.WorkbookFactory; 27 28 /** 29 * 封装对excel的操作,包括本地读写excel和流中输出excel,支持office 2007。<br/> 30 * 依赖于poi-3.9-20121203.jar,poi-ooxml-3.9-20121203.jar,poi-ooxml-schemas-3.9- 31 * 20121203.jar,dom4j-1.6.1.jar<br/> 32 * 有参构造函数参数为excel的全路径<br/> 33 * 34 * @author 宋立君 35 * @date 2014年07月03日 36 */ 37 public class ExcelUtil { 38 39 // excel文件路径 40 private String path = ""; 41 42 // 写入excel时,是否自动扩展列宽度来符合内容。 43 private boolean autoColumnWidth = false; 44 45 /** 46 * 无参构造函数 默认 47 */ 48 public ExcelUtil() { 49 } 50 51 /** 52 * 有参构造函数 53 * 54 * @param path 55 * excel路径 56 */ 57 public ExcelUtil(String path) { 58 this.path = path; 59 } 60 61 /** 62 * 读取某个工作簿上的所有单元格的值。 63 * 64 * @param sheetOrder 65 * 工作簿序号,从0开始。 66 * @return List<Object[]> 所有单元格的值。 67 * @throws IOException 68 * 加载excel文件IO异常。 69 * @throws FileNotFoundException 70 * excel文件没有找到异常。 71 * @throws InvalidFormatException 72 * @author 宋立君 73 * @date 2014年07月03日 74 */ 75 public List<Object[]> read(int sheetOrder) throws FileNotFoundException, 76 IOException, InvalidFormatException { 77 FileInputStream fis = new FileInputStream(path); 78 Workbook workbook = WorkbookFactory.create(fis); 79 if (fis != null) { 80 fis.close(); 81 } 82 Sheet sheet = workbook.getSheetAt(sheetOrder); 83 // 用来记录excel值 84 List<Object[]> valueList = new LinkedList<Object[]>(); 85 // 循环遍历每一行、每一列。 86 for (Row row : sheet) { 87 // 每一行 88 Object[] rowObject = null; 89 for (Cell cell : row) { 90 // cell.getCellType是获得cell里面保存的值的type 91 switch (cell.getCellType()) { 92 case Cell.CELL_TYPE_BOOLEAN: 93 // 得到Boolean对象的方法 94 rowObject = CollectionUtil.addObjectToArray(rowObject, 95 cell.getBooleanCellValue()); 96 break; 97 case Cell.CELL_TYPE_NUMERIC: 98 // 先看是否是日期格式 99 if (DateUtil.isCellDateFormatted(cell)) { 100 // 读取日期格式 101 rowObject = CollectionUtil.addObjectToArray(rowObject, 102 cell.getDateCellValue()); 103 } else { 104 DecimalFormat df = new DecimalFormat(); 105 // 单元格的值,替换掉, 106 String value = df.format(cell.getNumericCellValue()) 107 .replace(",", ""); 108 // 读取数字 109 rowObject = CollectionUtil.addObjectToArray(rowObject, 110 value); 111 } 112 break; 113 case Cell.CELL_TYPE_FORMULA: 114 // 读取公式 115 rowObject = CollectionUtil.addObjectToArray(rowObject, 116 cell.getCellFormula()); 117 break; 118 case Cell.CELL_TYPE_STRING: 119 // 读取String 120 rowObject = CollectionUtil.addObjectToArray(rowObject, cell 121 .getRichStringCellValue().toString()); 122 break; 123 } 124 } 125 // 将这行添加到list。 126 valueList.add(rowObject); 127 } 128 return valueList; 129 } 130 131 /** 132 * 读取某个工作簿上的某个单元格的值。 133 * 134 * @param sheetOrder 135 * 工作簿序号,从0开始。 136 * @param colum 137 * 列数 从1开始 138 * @param row 139 * 行数 从1开始 140 * @return 单元格的值。 141 * @throws Exception 142 * 加载excel异常。 143 * @author 宋立君 144 * @date 2014年07月03日 145 */ 146 public String read(int sheetOrder, int colum, int row) throws Exception { 147 FileInputStream fis = new FileInputStream(path); 148 Workbook workbook = WorkbookFactory.create(fis); 149 if (fis != null) { 150 fis.close(); 151 } 152 Sheet sheet = workbook.getSheetAt(sheetOrder); 153 Row rows = sheet.getRow(row - 1); 154 Cell cell = rows.getCell(colum - 1); 155 String content = cell.getStringCellValue(); 156 return content; 157 } 158 159 /** 160 * 在指定的工作簿、行、列书写值。 161 * 162 * @param sheetOrder 163 * 工作簿序号,基于0. 164 * @param colum 165 * 列 基于1 166 * @param row 167 * 行 基于1 168 * @param content 169 * 将要被书写的内容。 170 * @throws Exception 171 * 书写后保存异常。 172 * @author 宋立君 173 * @date 2014年07月03日 174 */ 175 public void write(int sheetOrder, int colum, int row, String content) 176 throws Exception { 177 FileInputStream fis = new FileInputStream(path); 178 Workbook workbook = WorkbookFactory.create(fis); 179 if (fis != null) { 180 fis.close(); 181 } 182 Sheet sheet = workbook.getSheetAt(sheetOrder); 183 Row rows = sheet.createRow(row - 1); 184 Cell cell = rows.createCell(colum - 1); 185 cell.setCellValue(content); 186 FileOutputStream fileOut = new FileOutputStream(path); 187 workbook.write(fileOut); 188 fileOut.close(); 189 190 } 191 192 /** 193 * 得到一个工作区最后一条记录的序号,相当于这个工作簿共多少行数据。 194 * 195 * @param sheetOrder 196 * 工作区序号 197 * @return int 序号。 198 * @throws IOException 199 * 根据excel路径加载excel异常。 200 * @throws InvalidFormatException 201 * @author 宋立君 202 * @date 2014年07月03日 203 */ 204 public int getSheetLastRowNum(int sheetOrder) throws IOException, 205 InvalidFormatException { 206 FileInputStream fis = new FileInputStream(path); 207 Workbook workbook = WorkbookFactory.create(fis); 208 if (fis != null) { 209 fis.close(); 210 } 211 Sheet sheet = workbook.getSheetAt(sheetOrder); 212 return sheet.getLastRowNum(); 213 } 214 215 /** 216 * 在磁盘生成一个含有内容的excel,路径为path属性 217 * 218 * @param sheetName 219 * 导出的sheet名称 220 * @param fieldName 221 * 列名数组 222 * @param data 223 * 数据组 224 * @throws IOException 225 * @author 宋立君 226 * @date 2014年07月03日 227 */ 228 public void makeExcel(String sheetName, String[] fieldName, 229 List<Object[]> data) throws IOException { 230 // 在内存中生成工作薄 231 HSSFWorkbook workbook = makeWorkBook(sheetName, fieldName, data); 232 // 截取文件夹路径 233 String filePath = path.substring(0, path.lastIndexOf("\\")); 234 // 如果路径不存在,创建路径 235 File file = new File(filePath); 236 // System.out.println(path+"-----------"+file.exists()); 237 if (!file.exists()) 238 file.mkdirs(); 239 FileOutputStream fileOut = new FileOutputStream(path); 240 workbook.write(fileOut); 241 fileOut.close(); 242 } 243 244 /** 245 * 在输出流中导出excel。 246 * 247 * @param excelName 248 * 导出的excel名称 包括扩展名 249 * @param sheetName 250 * 导出的sheet名称 251 * @param fieldName 252 * 列名数组 253 * @param data 254 * 数据组 255 * @param response 256 * response 257 * @throws IOException 258 * 转换流时IO错误 259 * @author 宋立君 260 * @date 2014年07月03日 261 */ 262 public void makeStreamExcel(String excelName, String sheetName, 263 String[] fieldName, List<Object[]> data, 264 HttpServletResponse response) throws IOException { 265 OutputStream os = null; 266 response.reset(); // 清空输出流 267 os = response.getOutputStream(); // 取得输出流 268 response.setHeader("Content-disposition", "attachment; filename=" 269 + new String(excelName.getBytes(), "ISO-8859-1")); // 设定输出文件头 270 response.setContentType("application/msexcel"); // 定义输出类型 271 // 在内存中生成工作薄 272 HSSFWorkbook workbook = makeWorkBook(sheetName, fieldName, data); 273 os.flush(); 274 workbook.write(os); 275 } 276 277 /** 278 * 根据条件,生成工作薄对象到内存。 279 * 280 * @param sheetName 281 * 工作表对象名称 282 * @param fieldName 283 * 首列列名称 284 * @param data 285 * 数据 286 * @return HSSFWorkbook 287 * @author 宋立君 288 * @date 2014年07月03日 289 */ 290 private HSSFWorkbook makeWorkBook(String sheetName, String[] fieldName, 291 List<Object[]> data) { 292 // 用来记录最大列宽,自动调整列宽。 293 Integer collength[] = new Integer[fieldName.length]; 294 295 // 产生工作薄对象 296 HSSFWorkbook workbook = new HSSFWorkbook(); 297 // 产生工作表对象 298 HSSFSheet sheet = workbook.createSheet(); 299 // 为了工作表能支持中文,设置字符集为UTF_16 300 workbook.setSheetName(0, sheetName); 301 // 产生一行 302 HSSFRow row = sheet.createRow(0); 303 // 产生单元格 304 HSSFCell cell; 305 // 写入各个字段的名称 306 for (int i = 0; i < fieldName.length; i++) { 307 // 创建第一行各个字段名称的单元格 308 cell = row.createCell((short) i); 309 // 设置单元格内容为字符串型 310 cell.setCellType(HSSFCell.CELL_TYPE_STRING); 311 // 为了能在单元格中输入中文,设置字符集为UTF_16 312 // cell.setEncoding(HSSFCell.ENCODING_UTF_16); 313 // 给单元格内容赋值 314 cell.setCellValue(new HSSFRichTextString(fieldName[i])); 315 // 初始化列宽 316 collength[i] = fieldName[i].getBytes().length; 317 } 318 // 临时单元格内容 319 String tempCellContent = ""; 320 // 写入各条记录,每条记录对应excel表中的一行 321 for (int i = 0; i < data.size(); i++) { 322 Object[] tmp = data.get(i); 323 // 生成一行 324 row = sheet.createRow(i + 1); 325 for (int j = 0; j < tmp.length; j++) { 326 cell = row.createCell((short) j); 327 // 设置单元格字符类型为String 328 cell.setCellType(HSSFCell.CELL_TYPE_STRING); 329 tempCellContent = (tmp[j] == null) ? "" : tmp[j].toString(); 330 cell.setCellValue(new HSSFRichTextString(tempCellContent)); 331 332 // 如果自动调整列宽度。 333 if (autoColumnWidth) { 334 if (j >= collength.length) { // 标题列数小于数据列数时。 335 collength = CollectionUtil.addObjectToArray(collength, 336 tempCellContent.getBytes().length); 337 } else { 338 // 如果这个内容的宽度大于之前最大的,就按照这个设置宽度。 339 if (collength[j] < tempCellContent.getBytes().length) { 340 collength[j] = tempCellContent.getBytes().length; 341 } 342 } 343 } 344 } 345 } 346 347 // 自动调整列宽度。 348 if (autoColumnWidth) { 349 // 调整列为这列文字对应的最大宽度。 350 for (int i = 0; i < fieldName.length; i++) { 351 sheet.setColumnWidth(i, collength[i] * 2 * 256); 352 } 353 } 354 return workbook; 355 } 356 357 /** 358 * 功能:设置写入excel时,是否自动扩展列宽度来符合内容,默认为false。 359 * 360 * @author 宋立君 361 * @date 2014年07月03日 362 * @param autoColumnWidth 363 * true或者false 364 */ 365 public void setAutoColumnWidth(boolean autoColumnWidth) { 366 this.autoColumnWidth = autoColumnWidth; 367 } 368 }