客户端中通过二维码传输数据的情况较多,但是直接传输可能因为数据过长导致二维码生成的太密不好扫描。
public class GZipUtils {
public static String compress(String str) {
if (str == null || str.length() == 0) {
return str;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzip = null;
try {
gzip = new GZIPOutputStream(out);
gzip.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (gzip != null) {
try {
gzip.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return android.util.Base64.encodeToString(out.toByteArray(),android.util.Base64.NO_WRAP);
//return new String(Base64.getEncoder().encode(out.toByteArray()));
}
/**
* 使用gzip解压缩
*
* @param compressedStr 压缩字符串
*/
public static String uncompress(String compressedStr) {
if (compressedStr == null) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = null;
GZIPInputStream ginzip = null;
byte[] compressed = null;
String decompressed = null;
try {
// compressed = Base64.getDecoder().decode(compressedStr);
compressed = android.util.Base64.decode(compressedStr,android.util.Base64.NO_WRAP);
in = new ByteArrayInputStream(compressed);
ginzip = new GZIPInputStream(in);
byte[] buffer = new byte[1024];
int offset = -1;
while ((offset = ginzip.read(buffer)) != -1) {
out.write(buffer, 0, offset);
}
decompressed = out.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ginzip != null) {
try {
ginzip.close();
} catch (IOException ignored) {
}
}
if (in != null) {
try {
in.close();
} catch (IOException ignored) {
}
}
try {
out.close();
} catch (IOException ignored) {
}
}
return decompressed;
}
}
测试一下:
private fun test() {
logDebug("--------------开始任务---------------------")
val str =
"qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名"
val compress = GZipUtils.compress(str)
logDebug("compress = " + compress)
val uncompress = GZipUtils.uncompress(compress)
logDebug("uncompress = " + uncompress)
logDebug("--------------任务结束---------------------")
}
2022-09-08 10:27:55 --------------开始任务---------------------
compress = H4sIAAAAAAAAACssTy0qqSzNzC9ILE5JS8/Iys6pqkguS8rLNTA0MjYxNTO3sKxTdFBWUY1T09LQjNdOOLT0UcMyMJoCRNo1jxu6Hjd0v98zX0dP/+n8vqc7mhSeLp/8dEJv4ajRo0aPGk2K0QBuPT1YjgMAAA==
uncompress = qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名
2022-09-08 10:27:55任务结束---------------------
java和Android中的差异
java中的import java.util.Base64 (在Android中使用需要api>26)
Base64.getEncoder().encode(out.toByteArray())
Base64.getDecoder().decode(compressedStr)
等同于
Android的import android.util.Base64
Base64.encodeToString(out.toByteArray(),Base64.NO_WRAP);
Base64.decode(compressedStr,Base64.NO_WRAP)
可以直接使用Android包中自带的。
android包中的第二个参数:Base64.NO_WRAP 有好几种类型
- DEFAULT 默认模式
- CRLF 指示行的编码器标志位用CRLF替代LF
- NO_CLOSE 传递给Base64OutputStream标记以指示它本身关闭时不应关闭它正在包装的输出流
- NO_PADDING 省略末尾填充的’=’字符
- NO_WRAP 省略所有的终止符
- URL_SAFE URL和文件名安全方式,替换其中不符合url安全的字符如+和/
需要注意的是,在android.util.Base64源码 发现Encoder有以下一行注释
static class Encoder extends Coder {
/**
* Emit a new line every this many output tuples. Corresponds to
* a 76-character line length (the maximum allowable according to
* <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
*/
大意就是超过76字符就会自动换一行
在对接其他平台时,有些平台使用的base64对换行后的字符串不一定能正确decode,所以需要将
android.util.Base64.encodeToString(input, Base64.DEFAULT);
换成
android.util.Base64.encodeToString(input, Base64.NO_WRAP);
我们来写个简单的例子对比下DEFAULT、NO_PADDING、NO_WRAP和URL_SAFE,看看这几种区别
public static void test() {
String str = "qwertyuiopasdfghjklzxcvbnm0123456789~!@#$%^&*()_+`¥……——+|《》?,./城市 姓名";
byte[] byteStr = str.getBytes(StandardCharsets.UTF_8);
String encode_DEFAULT = android.util.Base64.encodeToString(byteStr, android.util.Base64.DEFAULT);
String encode_NO_PADDING = android.util.Base64.encodeToString(byteStr, android.util.Base64.NO_PADDING);
String encode_NO_WRAP = android.util.Base64.encodeToString(byteStr, android.util.Base64.NO_WRAP);
String encodeURL_SAFE = android.util.Base64.encodeToString(byteStr, android.util.Base64.URL_SAFE);
Log.v("wlike","encode_DEFAULT = "+encode_DEFAULT);
Log.v("wlike","encode_NO_PADDING = "+encode_NO_PADDING);
Log.v("wlike","encode_NO_WRAP = "+encode_NO_WRAP);
Log.v("wlike","encodeURL_SAFE = "+encodeURL_SAFE);
}
打印结果:
相对于DEFAULT比较,我们可以看见
NO_PADDING只是将末尾自动补全的=号去除了
NO_WRAP去除了换行,输出始终为一整行
URL_SAFE将结果中的+变成-
总结:
1.在android客户端里自己加解码,只要encode和decode使用对应的flag即可。encode时flag为Base64.URL_SAFE,decode的flag必须为Base64.URL_SAFE。
2.如果需要和第三方对接时,因为一般第三方http请求时会主动对参数和参数值urlencode 防止乱码,所以不需要再处理+等字符,直接使用NO_WRAP来encode。如果是自己封装的http请求,没有对参数和参数值urlencode,则需要在请求时对参数和参数值urlencode下。
更多:
android.util.Base64使用
java实现生成二维码并压缩内容
Gzip在线转换测试
原文地址:https://blog.csdn.net/zx_android/article/details/126758761
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_37806.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!