kotlin的HttpClient封装http通信工具类

目的与初衷

最近在工作中需要在后台调用第三方接口(微信,支付,华为点击回拨,三通一达物流快递接口),最近在学习Kotlin,尝试使用Kotlin和HttpClient,自己封装了一个HttpClient工具类,封装常用实现get,post工具方法类

1 什么是HttpClient

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是Apache HttpComponents 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

2 功能介绍

  • 支持自动转向
  • 支持 HTTPS 协议
  • 支持代理服务器等

3. 版本比较

注意本篇博客主要是基于 HttpClient4.5.5 版本的来讲解的,也是现在最新的版本,之所以要提供版本说明的是因为 HttpClient 3 版本和 HttpClient 4 版本差别还是很多大的,基本HttpClient里面的接口都变了,你把 HttpClient 3 版本的代码拿到 HttpClient 4 上面都运行不起来,会报错的。所以一定要注意 HtppClient 的版本问题。

4. HttpClient不能做的事情

HttpClient 不是浏览器,它是一个客户端 HTTP 协议传输类库。HttpClient 被用来发送和接受 HTTP 消息。HttpClient 不会处理 HTTP 消息的内容,不会进行 javascript 解析,不会关心 content type,如果没有明确设置,HttpClient 也不会对请求进行格式化、重定向 url,或者其他任何和 HTTP 消息传输相关的功能。

5. HttpClient使用流程

使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。

    1. 创建HttpClient对象。
    1. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
    1. 如果需要发送请求参数,可调用HttpGetsetParams方法来添加请求参数;对于HttpPost对象而言,可调用setEntity(HttpEntity entity)方法来设置请求参数。
    1. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse对象。
    1. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
    1. 释放连接。无论执行方法是否成功,都必须释放连接

6. HttpClient与Kotlin结合使用

package com.flong.kotlin.utils
import com.alibaba.fastjson.JSONObject
import com.flong.kotlin.utils.security.SSLContextSecurity
import org.apache.http.HttpStatus
import org.apache.http.NameValuePair
import org.apache.http.client.config.RequestConfig
import org.apache.http.client.entity.UrlEncodedFormEntity
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.conn.ssl.SSLContextBuilder
import org.apache.http.conn.ssl.TrustStrategy
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager
import org.apache.http.message.BasicNameValuePair
import org.apache.http.util.EntityUtils.consume
import org.apache.http.util.EntityUtils.toString
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.IOException
import java.io.InputStream
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import java.nio.charset.Charset
import java.util.*
import java.util.stream.Collectors
import javax.net.ssl.HttpsURLConnection
/**
 * object表示这个类是单例模式
 * @Description HttpClientUtil帮助类
 * @Author      liangjilong
 * @Date        2018年12月17日 上午11:36:50
 */
object HttpClientUtil {
    private val log: Logger = LoggerFactory.getLogger(HttpClientUtil::class.java)

    private var JSON_APPLICATION        = "application/json; charset=utf-8"
    private var CONNECT_TIMEOUT         = 1000 * 20
    private var MAX_TIMEOUT             = 1000 * 20
    private var DEFAULT_ENCODING        = "UTF-8"
    private var LINE                    = System.getProperty("line.separator")//换行相当于\n
    
    private val requestConfig : RequestConfig
    init {
        // 设置连接池  
        var connMgr = PoolingHttpClientConnectionManager()
        // 设置连接池大小  
        connMgr.maxTotal = 100
        connMgr.defaultMaxPerRoute = connMgr.maxTotal

        var configBuilder = RequestConfig.custom()
        // 设置连接超时  
        configBuilder.setConnectTimeout(MAX_TIMEOUT)
        // 设置读取超时  
        configBuilder.setSocketTimeout(MAX_TIMEOUT)
        // 设置从连接池获取连接实例的超时  
        configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT)
        // 在提交请求之前 测试连接是否可用  
        configBuilder.setStaleConnectionCheckEnabled(true)
        requestConfig = configBuilder.build()

    }


    /**
     * @Description 获取参数内容
     * @Author      liangjilong
     * @Date        2017年6月6日 上午11:36:50
     * @param bodyParameters
     * @throws UnsupportedEncodingException 参数
     * @return String 返回类型
     */
    fun getConcatParams(bodyParameters: Map<String, String>, encoding :String?): String? {
        
        var content   = ""
        //?: elvis操作符(猫王),encoding? 表示if(encoding != null) encoding else 表示为空的时候默认就给 utf-8
        var charset   = encoding ?: "utf-8"
        
        var builder   = StringBuilder()
        for (i in bodyParameters.entries) {
            //将参数解析为"name=tom&age=21"的模式
            builder.append(i.key).append("=").append(URLEncoder.encode(i.value.toString(), charset)).append("&")
        }
        if (builder.length > 1) {
            content = builder.substring(0,builder.length -1)
        }
        return content
    }


    fun paramsToQueryString(bodyParameters: Map<String, String>) :String? {
        return bodyParameters.entries.stream().map({e -> e.key + "=" + e.value}).collect(Collectors.joining("&"))
    }


    //拼接参数同等getConcatParams方法,但是encode编码
    fun paramsToQueryStringUrlencoded(bodyParameters: Map<String, String>,encoding :String?): String? {
        //?: elvis操作符(猫王),encoding? 表示if(encoding != null) encoding else 表示为空的时候默认就给 utf-8
        var charset   = encoding ?: "utf-8"
        return bodyParameters.entries.stream().map({ e -> e.key + "=" + URLEncoder.encode(e.value, charset) }).collect(Collectors.joining("&"))
    }


    /**
     * @Description 请求链接返回InputStream
     * @Author        liangjl
     * @Date        2018年6月12日 下午8:37:42
     * @param reqUrl
     * @return 参数
     * @return InputStream 返回类型
     */
    fun createHttp(reqUrl: String): InputStream ? {
        try {
            var url = URL(reqUrl) // 创建URL
            var urlconn = url.openConnection() // 试图连接并取得返回状态码
            urlconn.connect()
            var httpconn = urlconn as HttpURLConnection //把Connection转换成HttpURLConnection
            if (httpconn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                log.error("createHttp方法出错,无法连接到")
            } else {
                return urlconn.getInputStream()
            } 
        } catch (e: Exception) {
            log.error("createHttp方法出错,出错原因为:" + e.message)
        }
        return null
    }

    
    //创建http
    @JvmStatic
    private fun createHttp(reqUrl :String ,method: String,bodyParams:  String,
                   headers:Map<String,String>? ,charsetName :String?): String {

        val url  = URL(reqUrl)
        val conn = url.openConnection() as HttpURLConnection
        conn.requestMethod = method
        conn.doOutput   = true
        conn.doInput = true
        conn.useCaches = false
        conn.connectTimeout = CONNECT_TIMEOUT
        conn.readTimeout = CONNECT_TIMEOUT

        setRequestProperty(headers, conn)

        if (bodyParams.isNotEmpty()) {
            if (charsetName != null && "" != charsetName) {
                IoUtils.writerOutputStream(conn.outputStream, bodyParams, charsetName)
            } else {
                IoUtils.writerOutputStream(conn.outputStream, bodyParams)
            }
        }

        return IoUtils.getInputStream(conn.inputStream, charsetName)
    }
    
    
    /**
     * @Description 建立http请求链接支持SSL请求
     * @Author      liangjilong  
     * @Date        2017年6月6日 上午11:11:56  
     * @param reqUrl
     * @param requestMethod
     * @param outputStr
     * @param headerMap请求头属性,可以为空
     * @param sslVersion  支持https的版本参数(TLSv1, TLSv1.1  TLSv1.2)
     * @param bodyParameters  
     * @return String 返回类型   
     */
    @JvmStatic
    private fun createHttps(reqUrl: String, requestMethod: String, headerMap: Map<String, String>?,
                    sslVersion: String, bodyParameters: String?, encoding: String): String {
        
        var conn :HttpsURLConnection? = null
        try {
            //这行代码必须要在创建URL对象之前,因为先校验SSL的https请求通过才可以访问http
            var ssf  = SSLContextSecurity.createIgnoreVerifySSL(sslVersion)
                
            var url  = URL(reqUrl)
         
            conn = url.openConnection() as HttpsURLConnection
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            conn.sslSocketFactory   = ssf
            conn.doOutput           = true//输出
            conn.doInput            = true//输入
            conn.useCaches          = false//是否支持缓存
            conn.connectTimeout     = CONNECT_TIMEOUT
            conn.readTimeout        = CONNECT_TIMEOUT
            addRequestProperty(headerMap, conn)
            
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod)
            // 当设置body请求参数
            if (bodyParameters != null && bodyParameters.isNotEmpty()) {  
                IoUtils.writerOutputStream(conn.getOutputStream(), bodyParameters)
            } 

            if(conn != null && conn.getResponseCode() == HttpStatus.SC_OK){
                // 从输入流读取返回内容
                return IoUtils.getInputStream(conn.getInputStream(),encoding)
            }else{
                return IoUtils.getInputStream(conn.getInputStream(),encoding)
            }
        
        } catch (e :Exception)  {
            log.error("https请求异常:{}请求链接"+reqUrl,e)
            return ""//请求系统频繁
        }finally{
            // 释放资源
            if(conn!=null){conn.disconnect()}
        }
    }
    
    
    /**
     * @Description 支持HttpClient的GET和POST请求,支持http和https协议
     * @Author  liangjl
     * @Date        2018年5月7日 下午10:05:28
     * @param reqUrl        请求链接
     * @param requestMethod 请求方法GET/POSt
     * @param bodyParameters 
     * @param encoding 编码
     * @param headerMap 请求头 
     * @return String 返回类型      
     */
   fun createHttp(reqUrl:String ,requestMethod :String, bodyParameters:Map<String,String>,
                     encoding :String?,headerMap:Map<String,String>?):String ?{  
        
        //这里是要转成Java的String,因为kotlin的String是没有忽略大小写这个方法
        //kotlin的==和equals是相同的都是比较字符串的值,而且===三个等号比较的是地址的值.
        var method  = requestMethod as java.lang.String
        
        if((reqUrl.startsWith("https") || reqUrl.contains("https") )  && method.equalsIgnoreCase("POST")) {

            return commonHttpClientPost(reqUrl, bodyParameters, encoding, headerMap, createHttpClient())

        } else if((reqUrl.startsWith("http") || reqUrl.contains("http") )  && method.equalsIgnoreCase("POST")) {
            
            return commonHttpClientPost(reqUrl, bodyParameters, encoding, headerMap, HttpClients.createDefault())
            
        }else if((reqUrl.startsWith("https") || reqUrl.contains("https") )  && method.equalsIgnoreCase("GET")) {
            
            return commonHttpClientGet(reqUrl, bodyParameters, encoding, headerMap, createHttpClient())
            
        }else {
            return commonHttpClientGet(reqUrl, bodyParameters, encoding, headerMap, HttpClients.createDefault())
        }
   }

    /**
    * @Description 发送Post请求
    * @Author      liangjilong
    * @Email       jilongliang@sina.com
    * @Date        2017年10月31日 上午11:05:40
    * @param reqUrl 请求Url
    * @param bodyParameters
    * @return 参数
    * @return String 返回类型
     */
    fun createHttpPost(reqUrl:String, bodyParameters :List<BasicNameValuePair>):String  {
        var httpClient  = createHttpClient()
        var httpPost    = HttpPost(reqUrl)//创建HttpPost
        httpPost.config = requestConfig
        httpPost.entity = UrlEncodedFormEntity(bodyParameters, DEFAULT_ENCODING)//设置entity
        var httpResponse = httpClient.execute(httpPost)

        if (httpResponse.getStatusLine() != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            var retMsg = toString(httpResponse.getEntity(), DEFAULT_ENCODING)
            if (retMsg != null && retMsg.isNotEmpty()) {
                return retMsg
            }
        } else {
            return ""
        }
        return ""
    }

     /**
     * @Description commonHttpClientGet
     *  如:{'userName':'小梁','age':'100'}
     *  
     * @Author      liangjilong  
     * @Email       jilongliang@sina.com 
     * @Date        2017年8月1日 上午10:35:09  
     * @param reqUrl 请求链接
     * @param bodyParameters 请求参数
     * @param encoding 编码,不穿默认UTF-8
     * @param headerMap 头参数:如 application/x-www-form-urlencoded charset=utf-8
     * @param httpClient
     * @return 参数  
     * @return String 返回类型
     */
     private fun commonHttpClientGet(reqUrl :String, bodyParameters:Map<String, String>?,encoding :String?,
                            headers: Map<String, String>?, httpClient:CloseableHttpClient):String? {
        var restMsg: String = ""
        var response: CloseableHttpResponse ?= null
        try {
            //把参数转换成字符串
            var reqParamStr = toString(setUrlEncodedFormEntity(bodyParameters, encoding))
            var httpGet : HttpGet?
            if (reqParamStr != null && reqParamStr.isNotEmpty()) {
                
                httpGet = HttpGet(reqUrl + "?" + reqParamStr)
                log.info(".commonHttpClientGet,reqUrl:" + reqUrl + "?" + reqParamStr)
                
            } else {
                httpGet = HttpGet(reqUrl)
            }
            /*设置请求头属性和值 */
            if (headers != null && headers.isNotEmpty()) {
            for (key in headers.keys) {
                    var value = headers.get(key)
                    httpGet.addHeader(key, value)
                }
            }
            httpGet.setConfig(requestConfig)
            
            response = httpClient.execute(httpGet)
            var entity = response. getEntity()
            if (entity != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                restMsg = toString(entity, encoding)
                log.info(".commonHttpClientGet,请求链接为:" + reqUrl + ",Response Content: " + restMsg)
            } else {
                restMsg = ""
                log.error(".ommonHttpClientGet的entity对象为空" + reqUrl)
            }
        } catch (e: IOException) {
            log.error("commonHttpClientGet出现异常,异常信息为:" + e.message)
        } finally {
            if (response != null) {
                try {
                    consume(response.getEntity())
                } catch (e: IOException) {
                }
            }
        }
        return restMsg
    }
    
    
    /**
     * @Description commonHttpClientPost
     * @Author      liangjilong  
     * @Email       jilongliang@sina.com 
     * @Date        2017年8月1日 上午10:34:43  
     * @param reqUrl
     * @param bodyParameters
     * @param contentType
     * @param encoding 编码,不传默认UTF-8
     * @param headerMap
     * @param httpClient
     * @return 参数  
     * @return String 返回类型
     */
    private fun commonHttpClientPost(reqUrl:String ,bodyParameters: Map<String, String> ?,
             encoding:String?,headerMap:Map<String, String>?,  httpClient:CloseableHttpClient):String {
        var restMsg:    String = ""
        var response:   CloseableHttpResponse? = null
        try {
            var httpPost    = setPostHeader(reqUrl, headerMap)/*设置请求头属性和值 */
            //把参数转换成字符串
            var reqParamStr = toString(setUrlEncodedFormEntity(bodyParameters, encoding))
            httpPost.setConfig(requestConfig)
            setStringEntity(reqParamStr, encoding, httpPost)
            
            response = httpClient.execute(httpPost)
            
            var entity = response.getEntity()
            
            if (entity != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                var buffer = IoUtils.getInputStream(entity.getContent(), encoding)
                log.info(".commonHttpClientPost,reqUrl:" + reqUrl + ",Response content : " + buffer.toString())
                return buffer.toString()//返回  
            } else {
                var buffer = IoUtils.getInputStream(entity.getContent(), encoding)
                log.error(".commonHttpClientPost的entity对象为空,请求链接为:" + reqUrl)
                return buffer.toString()//返回  
            }
        } catch (e: IOException) {
            log.error("commonHttpClientPost出现异常,异常信息为:" + e.message)
        } finally {
            if (response != null) {
                response.close()
            }
            if (httpClient != null) {
                httpClient.close()
            }
        }
        return restMsg
    }  
   
    
     /**
     * @Description 创建UrlEncodedFormEntity参数对象实体 
     * 相当于处理请求链接的参数如: -->http://www.yorisun.com/?username=yy&age=100
     * @Author      liangjilong  
     * @Email       jilongliang@sina.com 
     * @Date        2017年8月1日 上午10:34:25  
     * @param bodyParameters
     * @param encoding
     * @param reqParamStr
     * @throws IOException
     * @throws UnsupportedEncodingException 参数  
     * @return String 返回类型
     */
     private fun setUrlEncodedFormEntity(bodyParameters :Map<String, String>?,  encoding:String?) :UrlEncodedFormEntity ? {
        
        if(bodyParameters != null && !bodyParameters.isEmpty()){
            //封装请求参数  
            var params = ArrayList<NameValuePair>()
            for (entry in bodyParameters.entries) {  
                var key     = entry.key
                var `val`   = entry.value
                params.add(  BasicNameValuePair(key,  `val`))
            }
            var charset   = encoding ?: "utf-8"
            return  UrlEncodedFormEntity(params,Charset.forName(charset))
        }
        return null
    }  
    /**
     *设置头属性
     */
    private fun setRequestProperty(headers : Map<String, String>?, conn :HttpURLConnection) {
        
        if (headers != null && headers.isNotEmpty()) {
            for (key in headers.keys) {
                var value = headers.get(key)
                conn.setRequestProperty(key, value)
            }
        }
    }
    
     /**
     * @Description 添加请求属性
     * @Author  liangjl
     * @Date        2018年5月7日 下午9:51:54
     * @param headerMap
     * @param conn 参数
     * @return void 返回类型 
     */
     @JvmStatic
     private fun addRequestProperty(headers :Map<String,String>?, conn :HttpsURLConnection) {
        /*设置请求头属性和值 */
        if (headers != null && headers.isNotEmpty()) {
            for (key in headers.keys) {
                 var value = headers.get(key)
                 //如:conn.addRequestProperty("Authorization","123456")
                 conn.addRequestProperty(key,value)
             }
        }
    }
    
    
    
     /**
     * @Description 创建Post的头参数处理
     * @Author  liangjl
     * @Date        2018年4月25日 上午11:38:37
     * @param reqUrl
     * @param headerMap
     * @return 参数
     * @return HttpPost 返回类型 
     */
     @JvmStatic
     private  fun setPostHeader(reqUrl : String, headers :Map<String, String> ?) :HttpPost {
        var httpPost = HttpPost(reqUrl)  
        
        /*设置请求头属性和值 */
        if(headers != null &&headers.isNotEmpty()){
             for (key in  headers.keys) {
                 var value = headers.get(key)
                 //如: httpPost.addHeader("Content-Type", "application/json")  
                 httpPost.addHeader(key,value)
             }
        }
        return httpPost
    }  
    
     /**
     * @Description 设置setStringEntity参数
     * @Author  liangjl
     * @Date  2018年4月25日 下午12:23:57
     * @param bodyParameters
     * @param contentType 
     * @param encoding
     * @param httpPost 参数
     * @return void 返回类型 
     */
     @JvmStatic
     private  fun setStringEntity(bodyParameters : Any?,  encoding :String?,  httpPost :HttpPost) {
         if (bodyParameters  != null) {
             // 解决中文乱码问题
             var charset      = encoding ?: "utf-8"
             var stringEntity = StringEntity(bodyParameters.toString(), charset)

             if (encoding != null && encoding.isNotEmpty()) {
                 stringEntity.setContentEncoding(encoding)
             }
             httpPost.setEntity(stringEntity)
         }
     }
    
    
    
    //创建httpClient
    @JvmStatic
    private  fun createHttpClient():CloseableHttpClient {
         val trustStrategy = object : TrustStrategy {
             override fun isTrusted(xcert509: Array<java.security.cert.X509Certificate>, arg1: String): Boolean {
                 return true
             }
         }
         var sslcontext = SSLContextBuilder().loadTrustMaterial(null,trustStrategy).build()

         var versions   = arrayOf( "TLSv1", "TLSv1.1", "TLSv1.2")
         var sslsf      = SSLConnectionSocketFactory(sslcontext,versions, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
         return HttpClients.custom().setSSLSocketFactory(sslsf).build()
     }
     
    
    @JvmStatic //main测试
    fun main(args: Array<String>) {
        //var b = mapOf("age" to 23, "userName" to "ljl")
        
        var map3 = HashMap<String,String>()
    
        map3.put("age","23")
        map3.put("userName","寅务")

        //var p = getConcatParams(map3,null)
        //var p = paramsToQueryString(map3)
        //println(p)
        var reqUrl = "http://localhost:8080/rest/getBody"
        var method = "POST"
        var json = JSONObject()
        json.put("passWord","123456")
        json.put("userName","寅务")
        
        var header =   HashMap<String, String>()
        header.put("Content-Type", JSON_APPLICATION)
        
        var retMsg = createHttp(reqUrl,method,json.toJSONString(),header,"utf-8")
        println("retMsg=" +retMsg)

    }

}

7、 ObjectUtil工具类

package com.flong.kotlin.utils

import org.apache.commons.lang3.StringUtils

import java.math.BigInteger

open class ObjectUtil {

    /**
     * @param object 关键字要用双引号
     * @return
     */
    fun isNull(`object`: Any?): Boolean {
        return if (null == `object`) true else false
    }

    /**
     * @param object
     * *
     * @return
     */
    fun isNotNull(`object`: Any): Boolean {
        return !isNull(`object`)
    }

    /**
     * @param string
     * *
     * @return
     */
    fun isEmpty(string: String): Boolean {
        return StringUtils.isEmpty(string)
    }

    fun isNotEmpty(string: String?): Boolean {
        return StringUtils.isNotEmpty(string)
    }
    
    fun stringToBytes(hexString: String?): ByteArray? {
        var hexString = hexString
        if (hexString == null || hexString == "") {
            return null
        }
        hexString = hexString.toUpperCase()
        val length = hexString.length / 2
        val hexChars = hexString.toCharArray()
        val d = ByteArray(length)
        for (i in 0..length - 1) {
            val pos = i * 2
            d[i] = (charToByte(hexChars[pos]).toInt() shl 4 or charToByte(hexChars[pos + 1]).toInt()).toByte()
        }
        return d
    }

    /**
     * Convert char to byte
     * @param c char
     * *
     * @return byte
     */
    private fun charToByte(c: Char): Byte {
        return "0123456789ABCDEF".indexOf(c).toByte()
    }
    
    companion object{
        /**
         * 逗号
         */
        private const val COMMA_NAME: String = ","
    }


    /**
     * String 数组 转换成 BigInteger 数组
     *
     * @param array String 数组
     * @return BigInteger 数组
     */
    fun string2BigInteger(array: Array<String>): ArrayList<BigInteger>? {
        val idArray: ArrayList<BigInteger> = arrayListOf()
        var id: BigInteger?
        for (i: Int in array.indices) {
            id = array[i].toBigIntegerOrNull()
            if (null != id && BigInteger.ZERO < id) {
                idArray.add(id)
            }
        }
        return idArray
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * String 数组 转换成 BigInteger 数组
     *
     * @param array String 数组
     * @return BigInteger 数组
     */
    fun string2BigIntegerArray(array: Array<String>): Array<BigInteger>? {
        val idArray: Array<BigInteger> = Array(array.size, { BigInteger.ZERO })
        var id: BigInteger?
        for (i: Int in array.indices) {
            id = array[i].toBigIntegerOrNull()
            if (null != id && BigInteger.ZERO < id) {
                idArray[i] = id
            }
        }
        return idArray
    }

    // -------------------------------------------------------------------------------------------------

    /**
     * String 转换成 BigInteger 数组
     * @param str String
     * @return BigInteger 数组
     */
    fun string2BigInteger(str: String): Array<BigInteger>? {

        val strAry: List<String> = str.split(COMMA_NAME)
        val idArray: Array<BigInteger> = Array(strAry.size, { BigInteger.ZERO })
        var id: BigInteger?
        for ((i: Int, strValue: String) in strAry.withIndex()) {
            id = strValue.toBigIntegerOrNull()
            if (null != id && BigInteger.ZERO < id) {
                idArray[i] = id
            }
        }
        return idArray
    }
}

8、IoUtils工具类

package com.flong.kotlin.utils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.DataOutputStream
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.Arrays
import java.io.InputStreamReader
import java.io.BufferedReader
import java.lang.Byte
object IoUtils{
    private val log: Logger = LoggerFactory.getLogger(IoUtils::class.java) 
    /**
     * 点名称
     */
    private const val DOT: String = "."

    /**
     * 点名称
     */
    private const val SIZE_2MB: Long = 1024 * 1024 * 2
    
    /**
     * 获取 classpath
     */
    val classpath: String?
        get() {
            var path: String? = Thread.currentThread().contextClassLoader.getResource("/").path
            if (null != path && 1 != path.indexOf(":")) {
                path = File.separator + path
            }
            return path
        }
    
    /**
     * 根据文件名 获取其后缀信息
     *
     * @param fileSize 文件大小
     * @return String
     */
    @JvmStatic
    fun gt2Mb(fileSize: Long): Boolean {
        return fileSize > SIZE_2MB
    }
     /**
     * 根据文件名 获取其后缀信息
     * @param filename 文件名
     * @return String
     */
    @JvmStatic
    fun getSuffixByFilename(filename: String): String {
        return filename.substring(filename.lastIndexOf(DOT) + 1).toLowerCase()
    }

    /**
     * 只删除此路径的最末路径下所有文件和文件夹
     * @param folderPath 文件路径
     */
    fun delFolder(folderPath: String) {
        try {
            // 删除完里面所有内容
            delAllFile(folderPath)
            val myFilePath = File(folderPath)
            // 删除空文件夹
            myFilePath.delete()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 删除指定文件夹下所有文件
     * @param path 文件夹完整绝对路径
     * @return true/false
     */
    private fun delAllFile(path: String): Boolean {
        var flag = false
        val file = File(path)
        if (!file.exists()) {
            return false
        }
        if (!file.isDirectory) {
            return false
        }
        val tempList: Array<String>? = file.list()
        var temp: File
        if (null != tempList) {
            for (aTempList: String in tempList) {
                temp = if (path.endsWith(File.separator)) {
                    File(path + aTempList)
                } else {
                    File(path + File.separator + aTempList)
                }
                if (temp.isFile) {
                    temp.delete()
                }
                if (temp.isDirectory) {
                    // 先删除文件夹里面的文件
                    delAllFile("$path/$aTempList")
                    // 再删除空文件夹
                    delFolder("$path/$aTempList")
                    flag = true
                }
            }
        }
        return flag
    }

    // ------------------------------------------------

    /**
     * 创建文件夹
     * @param path 文件夹路径
     * @return 文件夹路径
     */
    @JvmStatic
    fun createPath(path: String): File {
        val file = File(path)
        try {
            if (!file.exists()) {
                file.mkdirs()
            }
        } catch (e: Exception) {
            //throw BaseException(">>创建[$path]文件夹失败<<<<<")
            log.error(">>>创建[$path]文件夹失败<<<<<<")
        }
        return file
    }
    
    
    //通过闭包返回来实现
    fun writeClo(`in`: InputStream, output: OutputStream) {
        try {
            var read: Int = -1
            `in`.use { input ->
                output.use {
                    while ({ read = input.read();read }() != -1) {
                        it.write(read)
                    }
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }
    }

    //通过正常写法来实现
    fun writeDef(`in`: InputStream, output: OutputStream) {
        try {
            var read: Int = `in`.read()
            `in`.use { input ->
                output.use {
                    while (read != -1) {
                        it.write(read)
                        read = input.read()
                    }
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }
    }
    
    
    
    //通过使用also扩展函数来实现
    fun writeAlso(`in`: InputStream, output: OutputStream) {
        try {
            var read: Int = -1
            `in`.use { input ->
                output.use {
                    while (input.read().also { read = it } != -1) {
                        it.write(read)
                    }
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }
    }
    
    
    //拼接参数
    fun parameter(map: Map<String, Array<String>>): String {
         val stringBuilder = StringBuilder("")
         for ((key: String, value: Array<String>) in map) {
             stringBuilder.append("{")
             stringBuilder.append(key)
             stringBuilder.append("=")
             stringBuilder.append(Arrays.toString(value))
             stringBuilder.append("}")
             stringBuilder.append(",")
         }
         if (1 < stringBuilder.length) {
             stringBuilder.deleteCharAt(stringBuilder.toString().length - 1)
         }
         return stringBuilder.toString()
     }
    
    
    /*
     *读取流的信息
     */
    fun getInputStream(`is` :InputStream, charsetName :String?):String {
        var charset = charsetName ?: "utf-8"
        val br = BufferedReader(InputStreamReader(`is`, charset))
        var line: String? = null
        val sb = StringBuilder()
        for (line in br.readLines()) {
            line?.let { sb.append(line) }
        }
        //关闭流
        if (br != null)   br.close();
        if (`is` != null) `is`.close();
        return sb.toString()
    }
    /**
     * @Description writerOutputStream
     * @Author  liangjl
     * @Date    2018年4月25日 下午12:05:16 参数
     * @return void 返回类型 
     */
    fun writerOutputStream(outputStream: OutputStream, bodyParameters: String) {
        var out = DataOutputStream(outputStream);
        out.writeBytes(bodyParameters);
        out.flush();
        out.close();
    }
    //写入流处理
    fun writerOutputStream(outputStream: OutputStream, bodyParameters: String, encoding: String) {
        //强制转换成Java的String对象
        var bodyParams = bodyParameters  as java.lang.String  
        var out = DataOutputStream(outputStream);
        out.write(bodyParams.getBytes(encoding))
        out.flush();
        out.close();
    }
} 

备注:此文章属于本人原创,欢迎转载和收藏.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • http-client-utli httpClient 工具类 github地址:https://github....
    杨文杰阅读 5,094评论 0 5
  • 前言 前面一章中,笔者向大家详细讲解了如何让你的开发环境支持 Kotlin 以及如何在项目中配置使用 Kotlin...
    WangJie0822阅读 4,284评论 0 4
  • 在一个春季的早晨醒来,我突然忘记了曾经的故事是怎样的一个开始,只有那些断断续续的记忆在慵懒的思绪里温馨流淌。 一个...
    kaffu阅读 372评论 0 0
  • 汤汤是我从小一起长大的闺蜜。我们有时很久不联系,然后忽然某一次定好时间地点直接约起,废话不多说,吃喝玩乐直奔主题。...
    八月牧歌阅读 231评论 0 2
  • 因为同事的建议,参加了第三期的大头早起成长营,也是因为读书组的这个作业,让我这很久没写过读书笔记的人,静心心来想想...
    天天天蓝201314阅读 88评论 0 0