import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; import javax.servlet.http.HttpServletRequest; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang.StringUtils; import com.seeyon.v3x.common.authenticate.domain.User; import com.seeyon.v3x.common.parser.StrExtractor; import com.seeyon.v3x.common.web.login.CurrentUser; /** * * @author <a href="mailto:[email protected]">Tanmf</a> * @version 1.0 2006-9-8 */ public final class Strings { /** * The number of bytes in a kilobyte. */ public static final long ONE_KB = 1024; /** * The number of bytes in a megabyte. */ public static final long ONE_MB = ONE_KB * ONE_KB; /** * The number of bytes in a gigabyte. */ public static final long ONE_GB = ONE_KB * ONE_MB; /** * 得到截取后的字符串 * * @param str * 需要截取的字符串 * @param length * 要得到的长度,以byte为单位, 此长度包括symbol的长度 * @param symbol * 用来代替被省略的信息,如“...”、“>>>”等 * @return * @throws UnsupportedEncodingException */ public static String getLimitLengthString(String content, int len, String symbol) { if(len < 0){ return content; } try { return getLimitLengthString(content, null, len, symbol); } catch (UnsupportedEncodingException e) { return content; } } /** * 得到截取后的字符串 * * @param str * 需要截取的字符串 * @param charsetName * 指定的编码 * @param length * 要得到的长度,以byte为单位, 此长度包括symbol的长度 * @param symbol * 用来代替被省略的信息,如“...”、“>>>”等 * @return * @throws UnsupportedEncodingException */ public static String getLimitLengthString(String content, String charsetName, int len, String symbol) throws UnsupportedEncodingException { if (content == null || content.length() == 0) { return content; } if (symbol == null) { symbol = ""; } int counterOfDoubleByte = 0; byte[] b; if (charsetName == null) { b = content.getBytes("GBK"); } else { b = content.getBytes(charsetName); } if (b.length <= len) { return content; } // 减去symbol占用的位置 if (len > symbol.length()) { len -= symbol.length(); } for (int i = 0; i < len; i++) { if (b[i] < 0) { counterOfDoubleByte++; } } if (counterOfDoubleByte % 2 != 0) { len--; } byte[] newBytes = new byte[len]; System.arraycopy(b, 0, newBytes, 0, len); if (charsetName == null) { return new String(newBytes,"GBK") + symbol; } else { return new String(newBytes, charsetName) + symbol; } } /** * Filter the specified message string for characters that are sensitive in * HTML. This avoids potential attacks caused by including JavaScript codes * in the request URL that is often reported in error messages. * * @param message * The message string to be filtered */ public static String toHTML(String text) { return toHTML(text, true); } /** * * @param text * @param isEscapeSpace 是否转换空格 * @return */ public static String toHTML(String text, boolean isEscapeSpace) { if (text == null || text.equals("")) { return ""; } char content[] = new char[text.length()]; text.getChars(0, text.length(), content, 0); StringBuffer result = new StringBuffer(); for (int i = 0; i < content.length; i++) { switch (content[i]) { case '\n': result.append("<br/>"); break; case '\r': result.append(""); break; case '<': result.append("<"); break; case '>': result.append(">"); break; case '&': result.append("&"); break; case '\'': result.append("'"); break; case '"': result.append("""); break; case ' ': if(isEscapeSpace){ result.append(" "); } else{ result.append(content[i]); } break; default: result.append(content[i]); } } return result.toString(); } /** * 把带有\r\n\t等字符的清理掉,只保留文字;但不转换HTML的标签<br> * 只适合于textarea输入的文本,如果是正文编辑器输入的文本请用全文检索的工具 {@link StrExtractor#getHTMLContent(String)} * @param text * @return */ public static String toText(String text) { if (text == null || text.equals("")) { return ""; } char content[] = new char[text.length()]; text.getChars(0, text.length(), content, 0); StringBuffer result = new StringBuffer(); for (int i = 0; i < content.length; i++) { switch (content[i]) { case '\n': break; case '\r': break; case '\t': break; case '\b': break; case '\f': break; default: result.append(content[i]); } } return result.toString(); } public static String toHTMLAlt(String text) { if (text == null || text.equals("")) { return ""; } char content[] = new char[text.length()]; text.getChars(0, text.length(), content, 0); StringBuffer result = new StringBuffer(); for (int i = 0; i < content.length; i++) { switch (content[i]) { case '\r': result.append(""); break; case '<': result.append("<"); break; case '>': result.append(">"); break; case '&': result.append("&"); break; case '\'': result.append("'"); break; case '"': result.append("""); break; case ' ': result.append(" "); break; default: result.append(content[i]); } } return result.toString(); } /** * 对null处理 * * @param <T> * @param str * @param defaultValue * @return */ public static <T extends Object> T escapeNULL(T str, T defaultValue) { return str == null ? defaultValue : str; } /** * 将文件大小格式化输出<br> * 如: Strings.formatFileSize(123456L, false) --> 120.47 KB<br> * Strings.formatFileSize(12345678L, false) --> 11.77 MB<br> * Strings.formatFileSize(18L, true) --> 1 KB<br> * Strings.formatFileSize(18L, false) --> 18 B<br> * * 前端显示采用<code>${v3x:formatFileSize(21433L, true)}</code> * * @param fileSize * 单位为字节 * @param isUseMinValue * 是否采用最小值显示,即:最小显示1KB * @return * @throws ArithmeticException * fileSize less than zero * @author Lucas */ public static String formatFileSize(long fileSize, boolean isUseMinValue) { if (fileSize < 0) { throw new ArithmeticException("fileSize less than zero"); } Locale locale = Locale.getDefault(); User user = CurrentUser.get(); if (user != null) { locale = user.getLocale(); } NumberFormat format = NumberFormat.getInstance(locale); format.setMaximumFractionDigits(2); format.setMinimumFractionDigits(0); if (fileSize >= ONE_GB) { float filesize = fileSize / new Long(ONE_GB).floatValue(); return format.format(filesize) + " GB"; } else if (fileSize >= ONE_MB) { float filesize = fileSize / new Long(ONE_MB).floatValue(); return format.format(filesize) + " MB"; } else if (fileSize >= ONE_KB) { float filesize = fileSize / new Long(ONE_KB).floatValue(); return format.format(filesize) + " KB"; } else if (fileSize == 0) { return "0 KB"; } else { if (isUseMinValue) { return "1 KB"; } else { return format.format(fileSize) + " B"; } } } public static String join(String separator, String... strings) { StringBuilder sb = new StringBuilder(); int i = 0; for(String str : strings) { if(i > 0){ sb.append(separator); } sb.append(str); i++; } return sb.toString(); } /** * 串联字符串,屏蔽参数中的null,''字符 * @param separator * @param strings * @return */ public static String joinDelNull(String separator, String... strings) { StringBuilder sb=new StringBuilder(); boolean hasValue=false; for(String str:strings) { hasValue=(str!=null && !"".equals(str)); if(hasValue && sb.length()>0) { sb.append(separator); } if(hasValue) { sb.append(str); } } return sb.toString(); } /** * 配合选人界面,对选择的人员进行分解 <code> * <pre> * //授权信息 * String authInfo = request.getParameter("authInfo"); * String[][] authInfos = Strings.getSelectPeopleElements(authInfo); * if (authInfos != null) { * int i = 0; * for (String[] strings : authInfos) { * TempleteAuth auth = new TempleteAuth(); * * auth.setIdIfNew(); * auth.setAuthType(strings[0]); * auth.setAuthId(Long.parseLong(strings[1])); * auth.setSort(i++); * auth.setTempleteId(templeteId); * * templete.getTempleteAuths().add(auth); * } * } * </pre> * </code> * * @param selectPeopleStr * 选人后的字符串,如Department|123|4352345,Member|234|23452 * @return String[][] 第一列是类型,第二列是Id */ public static String[][] getSelectPeopleElements(String selectPeopleStr) { String[][] results = null; if (StringUtils.isNotBlank(selectPeopleStr)) { String[] entities = selectPeopleStr.split(","); results = new String[entities.length][2]; int i = 0; for (String entity : entities) { String[] items = entity.split("[|]"); results[i][0] = items[0]; results[i][1] = items[1]; i++; } } return results; } /** * 将字符串转换成Javascript,将对\r \n < > & 空格进行转换 * * @param text * @return */ public static String escapeJavascript(String str) { if (str == null) { return str; } StringBuffer out = new StringBuffer(); int sz; sz = str.length(); for (int i = 0; i < sz; i++) { char ch = str.charAt(i); if (ch < 32) { switch (ch) { case '\b': out.append('\\'); out.append('b'); break; case '\n': out.append('\\'); out.append('n'); break; case '\t': out.append('\\'); out.append('t'); break; case '\f': out.append('\\'); out.append('f'); break; case '\r': out.append('\\'); out.append('r'); break; default: if (ch > 0xf) { out.append("\\u00" + hex(ch)); } else { out.append("\\u000" + hex(ch)); } break; } } else { switch (ch) { case '\'': out.append('\\'); out.append('\''); break; case '"': out.append("\\\""); break; case '\\': out.append('\\'); out.append('\\'); break; case '/': out.append("\\/"); break; default: out.append(ch); break; } } } return out.toString(); } public static String escapeQuot(String str) { if (str == null) { return str; } StringBuffer out = new StringBuffer(); int sz; sz = str.length(); for (int i = 0; i < sz; i++) { char ch = str.charAt(i); if (ch < 32) { switch (ch) { case '\b': out.append('\\'); out.append('b'); break; case '\n': out.append('\\'); out.append('n'); break; case '\t': out.append('\\'); out.append('t'); break; case '\f': out.append('\\'); out.append('f'); break; case '\r': out.append('\\'); out.append('r'); break; default: if (ch > 0xf) { out.append("\\u00" + hex(ch)); } else { out.append("\\u000" + hex(ch)); } break; } } else { switch (ch) { case '\'': out.append("'"); break; case '"': out.append("""); break; case '<': out.append("<"); break; case '>': out.append(">"); break; case '\\': out.append('\\'); out.append('\\'); break; default: out.append(ch); break; } } } return out.toString(); } private static String hex(char ch) { return Integer.toHexString(ch).toUpperCase(); } /** * 检测是否是null字符串, 允许空格 * * <pre> * Strings.isEmpty(null) = true * Strings.isEmpty("") = true * Strings.isEmpty(" ") = false * Strings.isEmpty("bob") = false * Strings.isEmpty(" bob ") = false * </pre> * * @param str * @return */ public static boolean isEmpty(String str){ return StringUtils.isEmpty(str); } /** * 检测是否不是null字符串, 允许空格 * * <pre> * Strings.isNotEmpty(null) = false * Strings.isNotEmpty("") = false * Strings.isNotEmpty(" ") = true * Strings.isNotEmpty("bob") = true * Strings.isNotEmpty(" bob ") = true * </pre> * * @param str * @return */ public static boolean isNotEmpty(String str){ return StringUtils.isNotEmpty(str); } /** * 检测是否是空字符串, 不允许空格 * * <pre> * Strings.isBlank(null) = true * Strings.isBlank("") = true * Strings.isBlank(" ") = true * Strings.isBlank("bob") = false * Strings.isBlank(" bob ") = false * </pre> * * @param str * @return */ public static boolean isBlank(String str){ return StringUtils.isBlank(str); } /** * 检测集合是否有数据 * * @param c * @return */ public static boolean isEmpty(Collection c){ return c == null || c.isEmpty(); } public static boolean isNotEmpty(Collection c){ return !isEmpty(c); } /** * 检测是否不是空字符串, 不允许空格 * * <pre> * Strings.isNotBlank(null) = false * Strings.isNotBlank("") = false * Strings.isNotBlank(" ") = false * Strings.isNotBlank("bob") = true * Strings.isNotBlank(" bob ") = true * </pre> * * @param str * @return */ public static boolean isNotBlank(String str){ return StringUtils.isNotBlank(str); } // public static final String REGEX_DIGIT = "(^-|[\\d])[\\d]+$"; public static final String REGEX_DIGIT ="^([-]?[\\d]*)[\\d]+$"; public static final String REGEX_WORD = "^[\\w]+$"; public static final String REGEX_I18NKey = "^[\\w.-]+$"; public static final String REGEX_NOTCHARACTER = "[\\x00-\\xff]*[^\\x00-\\xff]+[\\x00-\\xff]*"; public static final String REGEX_DECIMAL_EXCLUDEPLUS ="^([-]?)([\\d]*)([.]?)(\\d+)$"; /** * 检测是否为整形数字 * * <pre> * Strings.isDigits("1234") = true * Strings.isDigits("a123") = false * Strings.isDigits(" 123") = false * </pre> * * @param str * @return */ public static boolean isDigits(String str){ return Pattern.matches(REGEX_DIGIT, str); } public static boolean isTrue(Boolean b){ return Boolean.TRUE.equals(b); } /** * 检测是否为纯单词,只有数字、字母、下划线 * * @param str * @return */ public static boolean isWord(String str){ return Pattern.matches(REGEX_WORD, str); } /** * 是否是标准的国际化资源的key,有数字/字母/下划线/点/横线组成 * * @param key * @return */ public static boolean isI18NKey(String key){ if(isBlank(key)){ return false; } return Pattern.matches(REGEX_I18NKey, key); } /** * 转换成标准的路径 * <pre> * C:/a/b/c --> C:\a\b\c * C:/a/b/c/.. --> C:\a\b * C:/a/b/c/../.. --> C:\a * C:/a/b/../c --> C:\a\c * C:/../a/b/../c --> C:\a\c * </pre> * * @param filepath * @return */ public static String getCanonicalPath(String filepath){ return getCanonicalPath(filepath, false); } /** * 转换成标准的路径,同时创建文件夹 * * @param filepath * @return * @see getCanonicalPath(String) */ public static String getCanonicalPathAndCreate(String filepath){ return getCanonicalPath(filepath, true); } private static String getCanonicalPath(String filepath, boolean isCreate){ if(isBlank(filepath)){ return null; } String path = FilenameUtils.normalize(filepath); File f = new File(path); try { File fc = f.getCanonicalFile(); if(isCreate){ fc.mkdirs(); } return fc.getAbsolutePath(); } catch (IOException e) { } return filepath; } /** * 得到站点的基础路径:http://office.seeyon.com:80 * * @param request * @return */ public static String getBaseHref(HttpServletRequest request){ return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort(); } /** * 得到站点的基础路径+contextPath:http://office.seeyon.com:80/seeyon * * @param request * @return */ public static String getBaseContext(HttpServletRequest request){ return getBaseHref(request) + request.getContextPath(); } public static String toXmlStr(String srcStr) { String xml=srcStr; xml=xml.replaceAll("&","&"); xml=xml.replaceAll("<","<"); xml=xml.replaceAll(">",">"); xml=xml.replaceAll("'","'"); xml=xml.replaceAll("\"","""); return xml; } /** * 判断是否包括汉字等非字符 * isIncludeNotCharacter("234ds,提供电所")=true * isIncludeNotCharacter("234ds, ?\\ff3")=false * @param str * @return */ public static boolean isIncludeNotCharacter(String str) { if(str==null) return false; return Pattern.matches(REGEX_NOTCHARACTER, str); } /** * 判断是否是数字,包括-号开始,小数点,小数部分; * 整数部分能以0开始,小数部分能以0结尾,整个数字不能以.结尾; * 主要用于表单数据校验 * 34342.02 true * 02425.6 true * 232.60 true * 0.2323 true * 00.325 true * +656.32 false * -233 true * -.32 true * .32 true * @param str * @return */ public static boolean isDecimalExcludePlus(String str){ if(str == null) return false; return Pattern.matches(REGEX_DECIMAL_EXCLUDEPLUS, str); } /** * * @param <K> * @param <V> * @param map * @param k * @param v */ public static <K, V> void addToMap1(Map<K, ArrayList<V>> map, K k, V v){ ArrayList<V> list = map.get(k); if(list == null){ list = new ArrayList<V>(); map.put(k, list); } list.add(v); } public static <K, V> void addToMap(Map<K, List<V>> map, K k, V v){ List<V> list = map.get(k); if(list == null){ list = new ArrayList<V>(); map.put(k, list); } list.add(v); } /** * 将不换行空格(NO-BREAK SPACE,Unicode 0x00a0,UTF-8编码:0xC2A0)替换为普通空格。 * 用于避免因数据库字符集不兼容导致这个字符变为问号“?”的情况。 */ public static String nobreakSpaceToSpace(String str) { if (str == null) { return null; } char nbsp = 0x00a0; return str.replace(nbsp, ' '); } public static void main(String[] args) { String t = "asdf''''\nsadf</br>"; String temp = Strings.toHTMLAlt(t); System.out.println(temp); System.out.println(Strings.join("|", "a","b","c")); System.out.println(Strings.hex('A')); } }