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

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

The newest version!
/**
 * Copyright 2018 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
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.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 CHARSET_PATTERN = Pattern.compile("(?i)\\bcharset=\\s*(?:\"|')?([^\\s,;\"']*)");
    /**
     * 默认字符集
     */
    public static final String DEFAULT_CHARSET = "UTF-8";
    /**
     * 默认超时时间
     */
    public static final int DEFAULT_TIME_OUT = 5000;
    /**
     * 缓冲区大小
     */
    private static final int BUFFER_SIZE = 0x20000; // ~130K.
    /**
     * mime边界字符数组
     */
    private static final char[] MIME_BOUNDARY_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
            .toCharArray();
    /**
     * mime边界长度
     */
    private static final int BOUNDARY_LENGTH = 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[BUFFER_SIZE];
        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[BUFFER_SIZE];
        ByteArrayOutputStream outStream = new ByteArrayOutputStream(BUFFER_SIZE);
        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.DEFAULT_CHARSET).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 = CHARSET_PATTERN.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(BOUNDARY_LENGTH);
        final Random rand = new Random();
        for (int i = 0; i < BOUNDARY_LENGTH; i++) {
            mime.append(MIME_BOUNDARY_CHARS[rand.nextInt(MIME_BOUNDARY_CHARS.length)]);
        }
        return mime.toString();
    }

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

    /**
     * 编码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(); } public static boolean equals(String src1, String src2) { return src1 == null ? src2 == null : src1.equals(src2); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy