package com.duqing.missions.retrofit.utils; import com.duqing.missions.BuildConfig; import com.duqing.missions.util.GsonUtils; import com.duqing.missions.util.MyLog; import java.io.EOFException; import java.util.ArrayList; import okio.Buffer; /** * My father is Object, ites purpose of 单例模式 保证synchronized方法的线程安全性 * * @purpose Created by Runt (qingingrunt2010@qq.com) on 2021-5-13. */ public class HttpPrintUtils { String TAG = "HttpPrintUtils"; static HttpPrintUtils instance; public static HttpPrintUtils getInstance(){ if(instance == null){ instance = new HttpPrintUtils(); } return instance; } /** * 打印log * @param list */ public synchronized void printLog(ArrayList list, boolean info){ int length = 0 ;//计算每行最长的长度 ArrayList logArrays = new ArrayList<>(); for(String str : list){ if(str.indexOf("\n")>-1){//有换行的拆分处理 String[] split = str.split("\n"); for(String s : split){ s = s.replace("\t"," ");//缩进替换空格 if(length300){ length = 300; } String head = "HTTP REQUEST START"; logArrays.add(" \n\n\n"+"\n"); //打印头部 String logHead = "┏"+getEmptyStr((length-head.length())/2,"━")+head+getEmptyStr((length-head.length())/2,"━")+"┓"; logArrays.add(logHead+"\n"); //打印内容 for(String str : list){ String logStr = ""; if(str.indexOf("\n")>-1){//内部换行替换 splitStr(str,logHead.length(),logArrays); }else{ if(str.length()> logHead.length()){ outOflength(str,logHead.length(),logArrays); }else { logStr = "┃ " + str + getEmptyStr((length - 14 - str.length()), " "); //处理中文间距,保证打印无偏差 logArrays.add(logStr + getEmptyStr((logHead.length() - logStr.length() - 1 - hasCNchar(logStr)), " ") + "┃ \n"); } } } String end = "HTTP REQUEST END"; //打印结尾 logArrays.add("┗"+getEmptyStr((length-end.length())/2,"━")+end+getEmptyStr((length-end.length())/2,"━")+"┛\n"); logArrays.add(" \n\n\n"); //Logger.DEFAULT.log(sb.toString());//打印log,避免多个log语句,导致log输出时其他线程的log输出切入此输出阵列内 if(BuildConfig.DEBUG) { for(int i = 0 ; i < logArrays.size() ; i ++ ){ String str = logArrays.get(i); if (info) { MyLog.i(TAG , str.replace("\n","")+" "+logArrays.size()+" "+i); } else { MyLog.e(TAG , str.replace("\n","")+" "+logArrays.size()+" "+i); } } } } /** * 拆分 * @param str * @param totalLength * @param list */ private void splitStr(String str,int totalLength,ArrayList list){ String logStr = ""; String[] split = str.split("\n"); for(String s : split){ if(s.length()/totalLength>3){ s = s.substring(0,totalLength*3)+"..."; } s = s.replace("\t"," ");//缩进替换空格 if(s.indexOf("\":{\"")>-1 || s.indexOf("\":[{\"")>-1 || s.indexOf("\":[[")>-1){//内容非校正缩进,且为json字符规范 splitStr(s.substring(0,s.indexOf("\":")+2)+ GsonUtils.retractJson(s.substring(s.indexOf("\":")+2)),totalLength,list); }else { if(s.length()> totalLength){ outOflength(s,totalLength,list); }else { logStr = "┃ " + s + getEmptyStr((totalLength - 16 - s.length()), " "); //处理中文间距,保证打印无偏差 list.add(logStr + getEmptyStr((totalLength - logStr.length() - 1 - hasCNchar(logStr)), " ") + "┃ "/*+logStr.length()+" "+logStr.getBytes().length+" "+(" ").getBytes().length +" "+hasCNchar(s)*/ + "\n"); } } } } /** * 超长字符拆分 * @param str * @param total * @param list */ private void outOflength(String str,int total,ArrayList list){ String logStr = ""; //缩进空间 String space = getEmptyStr(str.length() - str.trim().length()+4," "); //要拆分的实际长度 int length = (str.length()-space.length()); //每行数量 int count = total-16-space.length();//总长度-间距-缩进空间是每行的数量 //最终拆分数量 int lines = (length/count) + (length%(count)>0?1:0); for(int i = 0 ; i < lines ; i ++){ int start = space.length() + (count * (i+1));//起始位 int end = start+count;//结束位 String s = ""; if(start > str.length() && i > 0){ break; } else if(end > str.length() && i > 0 || i == lines-1){ s = str.substring(start); } else if(i == 0 ){ s = str.substring(0, start); } else { s = str.substring(start, end); } if(i>0) { s = space + s; } logStr = "┃ " + s + getEmptyStr((total - 16 - s.length()), " "); list.add(logStr + getEmptyStr((total - logStr.length() - 1 - hasCNchar(logStr)), " ") + "┃ \n"); } } //返回包含中文数量, private int hasCNchar(String str){ str = str.replace("┃",""); int size = 0 ; for(int i = 0 ; i < str.length() ; i ++){ char c = str.charAt(i); if((c >= 0x0391 && c <= 0xFFE5)) { //中文字符 size++; } } return size>0?(int)(size/3.0*2):0;//+1为修正在log中与英文字符短一位 } /** * 占位符填充 * @param length 占位数量 * @param space 占位符 * @return */ private String getEmptyStr(int length,String space){ StringBuilder sb = new StringBuilder(); for(int i = 0 ; i < length ; i ++){ sb.append(space); } return sb.toString(); } /** * Returns true if the body in question probably contains human readable text. Uses a small sample * of code points to detect unicode control characters commonly used in binary file signatures. */ static boolean isPlaintext(Buffer buffer) { try { Buffer prefix = new Buffer(); long byteCount = buffer.size() < 64 ? buffer.size() : 64; buffer.copyTo(prefix, 0, byteCount); for (int i = 0; i < 16; i++) { if (prefix.exhausted()) { break; } int codePoint = prefix.readUtf8CodePoint(); if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { return false; } } return true; } catch (EOFException e) { return false; // Truncated UTF-8 sequence. } } }