下面列出了org.apache.commons.lang3.StringUtils#toEncodedString ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 获取TCP响应报文头中的应答描述字段
* @see 该方法返回的字符串为自动剔除原应答描述字段中的0x00字节后的字符串
* @see 沃前置系统的响应报文中,其约定的报文头格式为[6位长度码+8位应答码+14位应答日期+100位应答描述]
* @see 支付处理系统的响应报文,其约定的报文头格式为[6位长度码+8位应答码+100位应答描述+42位其它]
* @param respData 对方响应的完整报文
* @param length 报文头中自起始截止到应答描述字段时的长度,如支付处理的为114,沃前置则为128
*/
public static String getTCPMessageHeadRespDesc(String respData, int length){
byte[] srcByte = getBytes(respData, SeedConstants.DEFAULT_CHARSET);
int respDesclength = 0; //有效的应答描述字节长度
if(srcByte[length-1] != 0){ //应答描述的字节长度为固长100,不足时0x00右侧自动补齐
respDesclength = 100;
}else{
for(int i=0; i<srcByte.length; i++){
if(srcByte[i]==0){ //取到应答描述字节中第一个为0x00的下标
respDesclength = i-(length-100); //计算有效的应答描述字节长度
break;
}
}
}
byte[] destByte = new byte[respDesclength];
System.arraycopy(srcByte, length-100, destByte, 0, respDesclength); //从源数组的应答描述起始下标开始拷贝
return StringUtils.toEncodedString(destByte, Charset.forName(SeedConstants.DEFAULT_CHARSET));
}
private void assertClassGeneratedTs(String expectedClass) {
Path outputFilePath = outputDirectory.getRoot().toPath()
.resolve(expectedClass + ".ts");
String actualTs;
try {
actualTs = StringUtils
.toEncodedString(Files.readAllBytes(outputFilePath),
StandardCharsets.UTF_8);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
String expectedTs = TestUtils.readResource(getClass()
.getResource(String.format("expected-%s.ts", expectedClass)));
equalsIgnoreWhiteSpaces(
String.format("Class '%s' has unexpected json produced",
expectedClass),
expectedTs, actualTs);
}
@Override
protected Set<ShadowSocksDetailsEntity> parse(Document document) {
// SSR 订阅地址内容
String base64ssrLinks = document.text();
String ssrLinks = StringUtils.toEncodedString(Base64.decodeBase64(base64ssrLinks), StandardCharsets.UTF_8);
String[] ssrLinkList = ssrLinks.split("\n");
// log.debug("---------------->{}={}", ssrLinkList.length + "", ssrLinkList);
Set<ShadowSocksDetailsEntity> set = Collections.synchronizedSet(new HashSet<>(ssrLinkList.length));
Arrays.asList(ssrLinkList).parallelStream().forEach((str) -> {
try {
if (StringUtils.isNotBlank(str)) {
ShadowSocksDetailsEntity ss = parseLink(str.trim());
ss.setValid(false);
ss.setValidTime(new Date());
ss.setTitle("免费账号 | 云端框架");
ss.setRemarks("https://cloudfra.com/");
ss.setGroup("ShadowSocks-Share");
// 测试网络
if (isReachable(ss))
ss.setValid(true);
// 无论是否可用都入库
set.add(ss);
log.debug("*************** 第 {} 条 ***************{}{}", set.size(), System.lineSeparator(), ss);
// log.debug("{}", ss.getLink());
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
});
return set;
}
/**
* 获取TCP报文体
* @param respData 对方请求or响应的完整报文
* @param messageHeahLength 报文头长度,如支付处理响应的报文头长度固定为156,沃前置则为128
*/
public static String getTCPMessageBody(String respData, int messageHeahLength){
//计算报文体长度(报文总长度 - 报文头长度)
int messageBodyLength = Integer.parseInt(respData.substring(0,6)) - messageHeahLength;
byte[] messageBodys = new byte[messageBodyLength];
System.arraycopy(getBytes(respData, SeedConstants.DEFAULT_CHARSET), messageHeahLength, messageBodys, 0, messageBodyLength);
return StringUtils.toEncodedString(messageBodys, Charset.forName(SeedConstants.DEFAULT_CHARSET));
}
@Override
public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
byte[] message = new byte[in.limit()];
in.get(message);
String fullMessage = StringUtils.toEncodedString(message, Charset.forName(SeedConstants.DEFAULT_CHARSET));
Token token = new Token();
token.setBusiCharset(SeedConstants.DEFAULT_CHARSET);
token.setBusiType(Token.BUSI_TYPE_TCP);
token.setBusiCode(fullMessage.substring(6, 11));
token.setBusiMessage(fullMessage);
token.setFullMessage(fullMessage);
out.write(token);
return MessageDecoderResult.OK;
}
/**
* 字符串右补字节
* <ul>
* <li>若str对应的byte[]长度不小于size,则按照size截取str对应的byte[],而非原样返回str</li>
* <li>所以size参数很关键...事实上之所以这么处理,是由于支付处理系统接口文档规定了字段的最大长度</li>
* <li>若对普通字符串进行右补字符,建议{@link org.apache.commons.lang.StringUtils#rightPad(String, int, String)}</li>
* </ul>
* @param size 该参数指的不是字符串长度,而是字符串所对应的byte[]长度
* @param padStrByASCII 该值为所补字节的ASCII码,如32表示空格,48表示0,64表示@等
* @param charset 由右补字节后的字节数组生成新字符串时所采用的字符集
*/
public static String rightPadUseByte(String str, int size, int padStrByASCII, String charset){
byte[] srcByte = str.getBytes();
byte[] destByte;
if(srcByte.length >= size){
destByte = Arrays.copyOf(srcByte, size);
}else{
destByte = Arrays.copyOf(srcByte, size);
Arrays.fill(destByte, srcByte.length, size, (byte)padStrByASCII);
}
return StringUtils.toEncodedString(destByte, Charset.forName(charset));
}
/**
* 字符串左补字节
* <ul>
* <li>若str对应的byte[]长度不小于length,则按照length截取str对应的byte[],而非原样返回str</li>
* <li>所以length参数很关键...事实上之所以这么处理,是由于支付处理系统接口文档规定了字段的最大长度</li>
* </ul>
* @param padStrByASCII 该值为所补字节的ASCII码,如32表示空格,48表示0,64表示@
* @param charset 由左补字节后的字节数组生成新字符串时所采用的字符集
*/
public static String leftPadUseByte(String str, int length, int padStrByASCII, String charset){
byte[] srcByte = str.getBytes();
byte[] destByte = new byte[length];
Arrays.fill(destByte, (byte)padStrByASCII);
if(srcByte.length >= length){
System.arraycopy(srcByte, 0, destByte, 0, length);
}else{
System.arraycopy(srcByte, 0, destByte, length-srcByte.length, srcByte.length);
}
return StringUtils.toEncodedString(destByte, Charset.forName(charset));
}
@Test
public void testDecodeBase64()
{
// Test decode using hard coded values.
assertEquals("UT_SomeText", HerdStringUtils.decodeBase64("VVRfU29tZVRleHQ="));
// Test decode using random string and encoder.
String encodedText = StringUtils.toEncodedString(Base64.getEncoder().encode(STRING_VALUE.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
assertEquals(STRING_VALUE, HerdStringUtils.decodeBase64(encodedText));
}
@Override
public MessageDecoderResult decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
byte[] message = new byte[in.limit()];
in.get(message);
String fullMessage = StringUtils.toEncodedString(message, Charset.forName(SeedConstants.DEFAULT_CHARSET));
Token token = new Token();
token.setBusiCharset(SeedConstants.DEFAULT_CHARSET);
token.setBusiType(Token.BUSI_TYPE_HTTP);
token.setFullMessage(fullMessage);
if(fullMessage.startsWith("GET")){
if(fullMessage.startsWith("GET / HTTP/1.1\r\n") || fullMessage.startsWith("GET / HTTP/1.0\r\n")){
token.setBusiCode("/");
}else if(fullMessage.startsWith("GET /favicon.ico HTTP/1.1\r\n") || fullMessage.startsWith("GET /favicon.ico HTTP/1.0\r\n")){
token.setBusiCode("/favicon.ico");
}else{
//GET /login?aa=bb&cc=dd&ee=ff HTTP/1.1
if(fullMessage.substring(4, fullMessage.indexOf("\r\n")).contains("?")){
token.setBusiCode(fullMessage.substring(4, fullMessage.indexOf("?")));
token.setBusiMessage(fullMessage.substring(fullMessage.indexOf("?")+1, this.getHTTPVersionPosition(fullMessage)-1));
//GET /login HTTP/1.1
}else{
token.setBusiCode(fullMessage.substring(4, this.getHTTPVersionPosition(fullMessage)-1));
}
}
}else if(fullMessage.startsWith("POST")){
//先获取到请求报文头中的Content-Length
int contentLength = 0;
if(fullMessage.contains("Content-Length:")){
String msgLenFlag = fullMessage.substring(fullMessage.indexOf("Content-Length:") + 15);
if(msgLenFlag.contains("\r\n")){
contentLength = Integer.parseInt(msgLenFlag.substring(0, msgLenFlag.indexOf("\r\n")).trim());
if(contentLength > 0){
token.setBusiMessage(fullMessage.split("\r\n\r\n")[1]);
}
}
}
//POST /login?aa=bb&cc=dd&ee=ff HTTP/1.1
//特别说明一下:此时报文体本应该是空的,即Content-Length=0,但不能排除对方偏偏在报文体中也传了参数
//特别说明一下:所以这里的处理手段是busiMessage=请求URL中的参数串 + "`" + 报文体中的参数串(如果存在报文体的话)
if(fullMessage.substring(5, fullMessage.indexOf("\r\n")).contains("?")){
token.setBusiCode(fullMessage.substring(5, fullMessage.indexOf("?")));
String urlParam = fullMessage.substring(fullMessage.indexOf("?")+1, this.getHTTPVersionPosition(fullMessage)-1);
if(contentLength > 0){
token.setBusiMessage(urlParam + "`" + fullMessage.split("\r\n\r\n")[1]);
}else{
token.setBusiMessage(urlParam);
}
//POST /login HTTP/1.1
}else{
token.setBusiCode(fullMessage.substring(5, this.getHTTPVersionPosition(fullMessage)-1));
}
}
out.write(token);
return MessageDecoderResult.OK;
}
/**
* 校验HTTP请求报文是否已完整接收
* 目前仅授理GET和POST请求
* ----------------------------------------------------------------------------------------------
* GET /notify_yeepay?p1_MerId=11&r0_Cmd=Buy&r1_Code=1&r2_TrxId=22 HTTP/1.1^M
* Content-Type: application/x-www-form-urlencoded; charset=GBK^M
* Cache-Control: no-cache^M
* Pragma: no-cache^M
* User-Agent: Java/1.5.0_14^M
* Host: 123.125.97.248^M
* Accept: text/html, image/gif, image/jpeg, *; q=.2, 星号/*; q=.2^M
* Connection: keep-alive^M
* ^M
* ----------------------------------------------------------------------------------------------
* POST /tra/trade/noCardNoPassword.htm HTTP/1.1^M
* Content-Type: application/x-www-form-urlencoded;charset=GB18030^M
* Cache-Control: no-cache^M
* Pragma: no-cache^M
* User-Agent: Java/1.6.0_24^M
* Host: 192.168.20.1^M
* Accept: text/html, image/gif, image/jpeg, *; q=.2, 星号/*; q=.2^M
* Connection: keep-alive^M
* Content-Length: 541^M
* ^M
* cooBankNo=CMBC_CREDIT&signType=MD5&amount=499900&orderValidityNum=15&CVVNo=255
* ----------------------------------------------------------------------------------------------
* 至于上面所列的GET和POST请求原始报文中为何会出现^M
* 我的博客上有详细说明:https://jadyer.cn/2012/11/22/linux-crlf/
* ----------------------------------------------------------------------------------------------
* @param in 装载HTTP请求报文的IoBuffer
*/
private boolean isComplete(IoBuffer in){
/*
* 先获取HTTP请求的原始报文
*/
byte[] messages = new byte[in.limit()];
in.get(messages);
String message = StringUtils.toEncodedString(messages, Charset.forName(SeedConstants.DEFAULT_CHARSET));
/*
* 授理GET请求
*/
if(message.startsWith("GET")){
return message.endsWith("\r\n\r\n");
}
/*
* 授理POST请求
*/
if(message.startsWith("POST")){
if(message.contains("Content-Length:")){
//取Content-Length后的字符串
String msgLenFlag = message.substring(message.indexOf("Content-Length:") + 15);
if(msgLenFlag.contains("\r\n")){
//取Content-Length值
int contentLength = Integer.parseInt(msgLenFlag.substring(0, msgLenFlag.indexOf("\r\n")).trim());
if(contentLength == 0){
return true;
}else if(contentLength >= 0){
//取HTTP_POST请求报文体
String messageBody = message.split("\r\n\r\n")[1];
try {
if(contentLength == messageBody.getBytes(SeedConstants.DEFAULT_CHARSET).length){
return true;
}
} catch (UnsupportedEncodingException e) {
throw new IllegalArgumentException("将HTTP_POST请求报文体转为byte[]时发生异常:Unsupported Encoding-->[" + SeedConstants.DEFAULT_CHARSET + "]");
}
}
}
}
}
/*
* 仅授理GET和POST请求
*/
return false;
}
public static String convertToUTF8(String stringToConvert) {
return StringUtils.toEncodedString(stringToConvert.getBytes(), Charset.forName("utf-8"));
}
private String readFileInTempDir(String fileName) throws IOException {
Path outputPath = outputDirectory.getRoot().toPath().resolve(fileName);
return StringUtils.toEncodedString(Files.readAllBytes(outputPath),
StandardCharsets.UTF_8);
}
/**
* Decodes and return the base64 encoded string.
*
* @param base64EncodedText the base64 encoded string
*
* @return the decoded string
*/
public static String decodeBase64(String base64EncodedText)
{
return StringUtils.toEncodedString(Base64.getDecoder().decode(base64EncodedText.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
}
/**
* Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
*
* @param bytes
* The bytes to be decoded into characters, may be <code>null</code>
* @param charsetType
* 字符编码,建议使用 {@link CharsetType} 定义好的常量
* @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
* or <code>null</code> if the input byte array was <code>null</code>.
* @see String#String(byte[], String)
* @see "org.apache.commons.lang3.StringUtils#toString(byte[], String)"
* @see org.apache.commons.lang3.StringUtils#toEncodedString(byte[], Charset)
* @see "org.apache.commons.codec.binary.StringUtils#newString(byte[], String)"
* @since 1.3.0
*/
public static String newString(byte[] bytes,String charsetType){
return StringUtils.toEncodedString(bytes, Charset.forName(charsetType));
}