关于Redis 二进制内容的 可视化尝试
二进制内容的 能否可视化? 网上的资料比较少啊!
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
有时候通过 可视化工具,比如redis DesktopManager 查看 redis 的key 的值的时候,发现是 二进制内容, 如下:
出现二进制的内容, 丝毫不奇怪,因为我set的时候value就是key。怪的是, 为什么有的 英文字母 能够展示出来, 其他就都是\x ,可能是 这个工具本身做了一些处理吧。 但其实不然, 如果命令行登录进去一看,发现也是一样的 结果:
127.0.0.1:[]> get DISCUSS:TOPIC:3d28016e7cb34119aab718da2d4d1fe5::count
"\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x00"
可以看到其中 java.lang.Integer java.lang.Number 都是 类名。
另外注意到 如果 notepad++打开一个二进制文件, 比如class文件,那么也会看到这样的 乱码和 英文夹杂的情况。 为什么会这样 ?
写个程序测试下:
package com.lkk; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.lkk.ppm.discuss.domain.entity.ELComment;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import org.apache.commons.codec.binary.Hex;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.lettuce.LettuceConnection;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.util.ByteUtils; import javax.xml.bind.DatatypeConverter;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.net.URL;
import java.nio.ByteBuffer; /**
* @author Administrator
* @date 2019/9/5 0005 12:40
* @Description
*/
public class TestRedisSerializer { private static final int CURRENT = 111;
private static final int SIZE = 222; static RedisSerializer serial;
static RedisSerializationContext.SerializationPair serializationPair;
static RedisStringCommands redisStringCommands; static {
RedisURI redisURI = RedisURI.create("192.168.11.200", 6380);
redisURI.setPassword("Redis!123");
long jedis = 100000L;
RedisConnection connection = new LettuceConnection(jedis, RedisClient.create(redisURI));
connection.select(2); redisStringCommands = connection.stringCommands();
// 切换 序列化组件
serial = new JdkSerializationRedisSerializer();// 默认就是 JdkSerializationRedisSerializer // StringRedisSerializer 只能够序列化字符串, 不能序列化 对象。 好像没啥用!
// serial = new StringRedisSerializer(); // GenericFastJsonRedisSerializer 可以将对象序列化为 json格式字符串
// serial = new GenericFastJsonRedisSerializer(); serializationPair = RedisSerializationContext.SerializationPair.fromSerializer(serial);
} @Test
public void testHex() throws Exception {
// ByteUtils.getBytes(this.cacheConfig.getValueSerializationPair().write(value)
// ByteUtils.getBytes(this.cacheConfig.getValueSerializationPair().write(value)
// org.apache.commons.compress.utils.ByteUtils. String foo = "hello";
byte[] bytes = foo.getBytes("unicode");
bytes = foo.getBytes();
// bytes = foo.getBytes("gb2312"); /**
* 虽然foo 是纯英文字母,但 下面的方法都 无法将bytes 还原到上面的hello 了。。 TODO
*/
System.out.println( Hex.encodeHexString( bytes ) );// 结果是 纯16进制的内容 68656c6c6f,不带 \ x 无法查看
String s = DatatypeConverter.printHexBinary(bytes);;// 结果是 纯16进制的内容 68656c6c6f, 无法查看
System.out.println("s = " + s);
// byte[] decoded = Hex.decodeHex("00A0BF");
// System.out.println("decoded = " + new String(decoded)); /**
* 还原到上面的hello
*/
dumpBytesToHex(bytes); // 尝试读取class文件
// 当前文件
String fileFullName = "E:\\dev\\erdp2\\erdp_discuss\\erdp_discuss_service\\target\\test-classes\\com\\lkk\\TestRedisSerializer.class";
FileInputStream fis = new FileInputStream(fileFullName);
// fis.getChannel()
// ByteArrayInputStream
// fis.read()
int available = fis.available();
byte[] classBytes = new byte[available];
int read = fis.read(classBytes); String s1 = dumpBytesToHex(classBytes);// 除了换行符,基本上 得到了 和 notepad++ 一样的效果。
Assert.assertTrue(s1.contains("TestRedisSerializer")); ClassLoader classLoader = TestRedisSerializer.class.getClassLoader(); } @Test
public void testWrite() throws Exception {
String key = "RESOURCE:ITEM:FILE::9fd04b83e33844b1a21ffa1c05978fc1_content.js";
// key = "RESOURCE:ITEM:FILE::3fa4bbdff660490092ba9af971980838_template.html";
// key = "DISCUSS:TOPIC:3d28016e7cb34119aab718da2d4d1fe5::count";
key = "DISCUSS:TOPIC:xxx::count";
write(key);
}
private void write(Object key) throws Exception {
/**
* CURRENT SIZE 测试read 要用到
*/
Page<ELComment> page = new Page<>(CURRENT, SIZE);
String s2 = JSONObject.toJSONString(page);
// byte[] bytes = ByteUtils.getBytes(serializationPair.write(key)); //如果是 JdkSerializationRedisSerializer : write 1 结果是 "\xac\xed\x00\x05sr\x00\x11java.lang.Integer\x12\xe2\xa0\xa4\xf7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xac\x95\x1d\x0b\x94\xe0\x8b\x02\x00\x00xp\x00\x00\x00\x01"
// byte[] bytes = ByteUtils.getBytes(serializationPair.write(1)); byte[] bytes = ByteUtils.getBytes(serializationPair.write(page));
Boolean set = redisStringCommands.set(key.toString().getBytes(), bytes);
// System.out.println("set = " + set);
// byte[] bytes = ByteUtils.getBytes(RedisSerializationContext.SerializationPair.fromSerializer(serial).write(new String("abc阿斯蒂芬")));
// System.out.println("bytes = " + bytes.length);
String s = dumpBytesToHex(bytes);
Assert.assertTrue(s.contains("com.baomidou.mybatisplus.plugins.Page"));
}
@Test
public void testRead() throws Exception {
String key = "DISCUSS:TOPIC:xxx::count";
read(key);
} private void read(String key) {
byte[] bytes1 = redisStringCommands.get(key.getBytes());
System.out.println("TestRedis.aaa");
System.out.println("bytes1 === " + new String(bytes1));// 直接打印 二进制内容
System.out.println("TestRedis.bbb");
dumpBytesToHex(bytes1);// 打印 16 进制内容 Page<ELComment> read = (Page<ELComment>) serializationPair.read(ByteBuffer.wrap(bytes1));
System.out.println("read = " + read);
int pages = read.getPages();
int size = read.getSize();
System.out.println("size = " + size);
Assert.assertEquals(read.getSize(), SIZE);
Assert.assertEquals(read.getCurrent(), CURRENT);
} /**
* 转换为16进制 再打印
* @param bytes
* @return
*/
public static String dumpBytesToHex(byte[] bytes) {
String s = bytesToHex(bytes);
System.out.println("Hex String:\n" + s);
return s;
} private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); public static String bytesToHex66(byte[] bytes) {
StringBuffer sb = new StringBuffer();
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
byte aByte = bytes[j];
if (aByte > 33 && aByte < 128) {
sb.append((char) aByte);
continue;
}
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F]; String hex = Integer.toHexString(aByte & 0xFF);
sb.append("\\x");
sb.append(hex);
if (hex.length() < 2) {
if (aByte == 0) {
// continue; // Fixme ,
} else {
}
sb.append(0); // Fixme ,
}
}
// return new String(hexChars);
return sb.toString();
} /**
* @param bytes
* @return
*/
public static String bytesToHex(byte[] bytes) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
byte aByte = bytes[i]; /**
* 这一段是做 ascii码字符 转换
*/
if (aByte > 33 && aByte < 128) {
sb.append((char) aByte);
continue;
}
String hex = Integer.toHexString(aByte & 0xFF);
sb.append("\\x");
sb.append(hex);
if (hex.length() < 2) {
if (aByte == 0) {
// continue;
} else {
}
sb.append(0);
}
}
return sb.toString();
} }
Binary Viewer 查看的 结果是:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
总结:
二进制的内容, 可以用hex 查看/编辑器 进行查看, 一般情况下 是无法直接转换为 字符串的!! 二进制的内容 如果 用hex 查看器查看,发现确实有字符串,那么可能就是 它本身就是 刚好被查看器支持直接展示了吧。
网上很多的二进制转 16进制的 所谓工具, 其实 其结果并不是Redis 客户端展示的结果,不是我想要的。。 因为它对 字符串的不能直接解析出来。。
16 进制不能阅读, 可以尝试转换为ascii。 二进制其实就是内存的内容,任何文件都可以转换为二进制。 软件把它展示出来, 它需要按照特定的 编码格式。文本内容是 天生可以用 文本编辑器 查看的。 其他的 , 比如 图片, 需要图片查看器, 依次类推。 class文件 呢? 其实也有专门的 查看器。。
注意到 其中 \ x 其实是一个 方便终端展示的一个 程序添加的 字符。 并不是 二进制内容自带的。
StringRedisTemplate默认使用的是StringRedisSerializer, 默认只能用来存储value类型为 string 的值。。
Redis 自带的序列化器是的JdkSerializationRedisSerializer,也就是我们 生成我们 class 文件的 二进制序列化器。 其生成的结果很臃肿, 效率是比较低的!
参考:
https://www.jianshu.com/p/23f2c4c92093
https://blog.csdn.net/Eric_Blog_CSDN/article/details/78904679
关于Redis 二进制内容的 可视化尝试的更多相关文章
- Redis二进制安全
为了便于理解,举一个例子: 在很多编辑器中,都会默认/n是换行字符,也就意味着一串字符存进去,涉及/n都会做一个默认的转义处理,这在编辑语言中,C也有这个特性,例如字符串Hello,\0 World! ...
- Redis安装教程及可视化工具RedisDesktopManager下载安装
Redis安装教程: 1. Windows下安装教程: 下载:https://github.com/MSOpenTech/redis/releases Redis 支持 32 位和 64 位.这个需要 ...
- Redis 配置内容总结
命令 Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf. 你可以通过 CONFIG 命令查看或设置配置项. (1)config get config_setting_ ...
- 循序渐进redis(一) —— redis的安装及可视化工具的使用
1.安装 注意事项: 1.安装gcc 2.编译带参数: make MALLOC=libc 2.可视化客户端工具 推荐使用RedisClient,提供了基本的CRUD以及过期设置等操作的图形化接口,在项 ...
- Redis二进制安全概念
二进制安全是指,在传输数据时,保证二进制数据的信息安全,也就是不被篡改.破译等,如果被攻击,能够及时检测出来. 二进制安全包含了密码学的一些东西,比如加解密.签名等. 举个例子,你把数据1111000 ...
- Redis二进制反转算法分析
在 redis 源码中 dictScan 算法中用到了用到了非常经典的二进制反转算法,该算法对二进制的反转高效而实用,同时对于理解位运算也有非常大的帮助.先呈现源码: /* Function to r ...
- 99%的人都搞错了的java方法区存储内容,通过可视化工具HSDB和代码示例一次就弄明白了
https://zhuanlan.zhihu.com/p/269134063 番茄番茄我是西瓜 那是我日夜思念深深爱着的人啊~ 已关注 6 人赞同了该文章 前言 本篇是java内存区域管理系列教 ...
- 通达OA 在工作流中直接查询表单内容的开发尝试(图文)
一个朋友提出要在工作里直接查询表单内容的需求,原来他们把工作流当做业务系统来用.也算把工作流用到极致了.为了实现像软件里直接的查询功能,他想在办理工作流的时候直接能查询到表单里面的内容. 通过研究通达 ...
- 爬虫3 requests基础之下载图片用content(二进制内容)
res = requests.get('http://soso3.gtimg.cn/sosopic/0/11129365531347748413/640') # print(res.content) ...
随机推荐
- 面试阿里被“吊打”,一问Spring三不知,半年后二战终拿下offer
Spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发. 近两年来,许多大厂在面 ...
- 重启testjenkins的步骤
在linux下编译caffe的过程中,发生错误,导致linux系统蹦了,没办法,重启linux系统. 之前安装在docker下的jenkins也停掉了. 先启动jenkins的步骤如下: 1.先启动d ...
- matlab实现PSNR
目录 1.PSNR原理 2.PSNR的matlab实现代码 3.针对彩色图像的PSNR的matlab代码 @ 1.PSNR原理 PSNR,峰值信噪比,通常用来评价一幅图像压缩后和原图像相比质量的好坏, ...
- ruby方法名之命名方式
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 modify_my_object!,这个方法名是以 ! 结尾,在 ruby 的对象里边是用于表达修改本身的意思. 比如 String#gsub ...
- 鲲鹏性能优化十板斧(二)——CPU与内存子系统性能调优
1.1 CPU与内存子系统性能调优简介 调优思路 性能优化的思路如下: l 如果CPU的利用率不高,说明资源没有充分利用,可以通过工具(如strace)查看应用程序阻塞在哪里,一般为磁盘,网络或应 ...
- 09-Python-Socket编程
一.Python-Socket编程 1.1.弄懂HTTP.Socket.TCP这几个概念 什么是HTTP协议?浏览器的本质就是一个socket客户端遵循HTTP协议,HTTP协议的本质:通过\r\n分 ...
- 使用Fiddler 对ios 设备进行HTTPS 的抓取
http://blog.csdn.net/skylin19840101/article/details/43485911 使用Fiddler 对ios 设备进行HTTPS 的抓取
- 洛谷 题解 P2296 【寻找道路】
Problem P2296 [寻找道路] solution 首先声明,这题我用了spfa,而: 关于spfa:它死了. 杀手: NOI 2018−T1 出题人 感谢出题人,没有卡spfa 用时: 20 ...
- 决策树(三)决策树与Jupyter小部件的交互式可视化
简介 决策树是广泛用于分类和回归任务的监督模型. 在本文中,我们将讨论决策树分类器以及如何动态可视化它们. 这些分类器在训练数据上构建一系列简单的if / else规则,通过它们预测目标值. 在本演 ...
- SpringBoot+SpringDataJPA如何实现自定义查询[多表,多条件,分页,自定义sql封装]
举个例子:我们要在已经搭建好了的JPA环境下实现联合多表,多条件,多排序条件,分页查询一个表格数据,下面的表格 返回类MyJSON: public class MyJSON { private Str ...