Python3学习(33)--序列和反序列化(二)

来源:互联网 发布:快压压缩软件 编辑:程序博客网 时间:2024/06/05 04:32

上一篇,我们遗留了一个问题,那就是Python的pickle模块,序列化后的字节流bytes,如果通过socket传给Java,Java可以反序列化吗?


我们看下demo案列(案列很简单,就是简单的信息传输,不涉及多线程和回写),验证一下就知道了:




Java服务端demo


import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.ServerSocket;import java.net.Socket;public class Test2 {  public static void main(String[] args){ ServerSocket serverSocket;try {serverSocket = new ServerSocket(9999);System.out.println("等待连接.......");Socket socket;socket = serverSocket.accept();//一直阻塞System.out.println("客户端已连接!");InputStream ins = socket.getInputStream();InputStreamReader isr = new InputStreamReader(ins,"utf-8");BufferedReader bReader = new BufferedReader(isr);String line = "";StringBuffer buffer = new StringBuffer();while(!("==END==").equals(line=bReader.readLine())){System.out.println("客户端:"+line);buffer.append(line+"\n");}System.out.println("接收到的完整buffer:"+buffer.toString());ByteArrayOutputStream baos = new ByteArrayOutputStream();          ObjectOutputStream oos = new ObjectOutputStream(baos);            String str = new String(buffer);        oos.writeObject(str);  byte [] strData = baos.toByteArray();ByteArrayInputStream baoi = new ByteArrayInputStream(strData);ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(baoi));try {Object Obj = ois.readObject();System.out.println(Obj.getClass());System.out.println("对象反序列化成功!");} catch (ClassNotFoundException e) {e.printStackTrace();}    finally {serverSocket.close();socket.close();ins.close();isr.close();baos.close();baoi.close();oos.close();} } catch (IOException e) {e.printStackTrace();}  }}


启动服务端,如下:




Python客户端demo


#!/usr/bin/env Python3# -*- encoding:utf-8 -*-import socket,pickleclass Employee:    def __init__(self,name,sex,age,salary):        self.name  = name    #姓名        self.sex   = sex     #性别         self.__age = age     #年龄 私有变量         self.salary= salary  #薪资 按月算    @property    def age(self):            #age的getter属性,还记得装饰器@property的用法吗?        return self.__age    @age.setter    def age(self,value):      #age的setter属性        self.__age = value    def add(self,a,b):        return a+bperson = Employee('张三','男',35,6000.00)s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(('127.0.0.1',9999))  s.send(pickle.dumps(person)+bytes('\n==END==\n',encoding='utf-8'))

运行客户端,由于客户端没有接收部分,所以,我们直接看Java服务端



为了使Java服务端正常的运作,耍了一下小聪明,我们用Python传过来的字节流初始化了一个String对象str,因为谁也没告诉我,Python传过来的字节流里面装的究竟是啥(一堆乱码,我Java一脸懵逼),我就假设一下是字符串对象,显然,字符串对象序列化后,在反序列化后仍然是字符串,也就是Python传过来的内容,我Java这边只能胡乱猜测,猜测的结果就是又绕回去了。这就牵扯到了不同语言之间的序列化共性问题了,也就是你Python序列化后的字节流,你自己清楚该怎么反序列回去,而我Java则是按照自己的序列化规则走,因此,就导致,双方无法通过序列化后的字节流进行交流。


我们看下,Python是不是可以识别这些"乱码"




在Python中用pickle.load反序列1.txt里面的内容,还原对象如下




这就让人不淡定了,那我怎么让Python的对象序列化后的内容分享给Java,让Java也能看到呢?

记住,不管你是哪种编程语言,你肯定能识别字符串对吧,基本数据类型啊,连这都识别不了,你想干嘛,是不是想上上天啊?


好了,既然是字符串,结合上一篇所讲,在Python中,我们引入json模块,使用dumps函数将对象序列化成json串,然后,我们拿这个json串再交给Java,Java不就能识别了嘛,而且,Java还能对json串进行详细的解析,不信吗?不信,我们就来看一下demo案列:



服务端依然由Java来接收(Java需要引入相关的Jar包,这里是讲Python,Java不是重点):


import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.ServerSocket;import java.net.Socket;import com.google.gson.JsonArray;import com.google.gson.JsonObject;import com.google.gson.JsonParser;public class ServerTest {public static void main(String[] args) {       try {ServerSocket serverSocket = new ServerSocket(9999);System.out.println("等待连接.......");Socket socket = serverSocket.accept();//一直阻塞System.out.println("客户端已连接!");//如果连上了 执行下面的语句//读取输入流 看看客户端说了什么InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is,"GBK");BufferedReader bReader = new BufferedReader(isr);String line = "";while(!"==END==".equals(line =bReader.readLine())){System.out.println("客户端:"+line); JsonParser parser=new JsonParser();  //创建JSON解析器         JsonObject object=(JsonObject) parser.parse(line);  //创建JsonObject对象         JsonArray array=object.get("data").getAsJsonArray();    //得到为json的数组         for(int i=0;i<array.size();i++){             System.out.println("---------------");             JsonObject subObject=array.get(i).getAsJsonObject();             System.out.println("name="+subObject.get("name").getAsString());             System.out.println("sex="+subObject.get("sex").getAsString());            // System.out.println("age"+subObject.get("_Employee__age").getAsString());             System.out.println("age="+subObject.get("age").getAsString());             System.out.println("sum="+subObject.get("sum").getAsInt());            }}socket.shutdownInput();//关闭输入流//响应连接用户信息OutputStream os = socket.getOutputStream();PrintWriter  writer = new PrintWriter(os);writer.write("服务端: "+socket.getInetAddress().toString().replaceAll("/", "")+",您好!你传过来的JSON数据,我已成功接收并解析。");writer.flush();    writer.close();    os.close();    bReader.close();    isr.close();    is.close();    socket.close();} catch (IOException e) {e.printStackTrace();}       }}

启动服务端





客户端由我们的Python来处理数据(demo和上一篇如出一辙,就不细说了)


#!/usr/bin/env Python3# -*- encoding:utf-8 -*-import socket,pickle,jsonclass Employee:    def __init__(self,name,sex,age,salary):        self.name  = name    #姓名        self.sex   = sex     #性别         self.__age = age     #年龄 私有变量         self.salary= salary  #薪资 按月算    @property    def age(self):            #age的getter属性,还记得装饰器@property的用法吗?        return self.__age    @age.setter    def age(self,value):      #age的setter属性        self.__age = value    def add(self,a,b):        return a+bp1 = Employee('张三','男',35,6000.00)#动态绑定实例的属性变量p1.a = 4p1.b = 5p2 = Employee('李婷','女',25,4000.00)p2.a = 10p2.b = 20p3 = Employee('王五','男',30,5000.00)p3.a = 11p3.b = 25L=[]L.append(p1)L.append(p2)L.append(p3)def ToJson(obj):    return {        'name'  :obj.name,        'sex'   :obj.sex ,        'age'   :obj.age ,        'salary':obj.salary,        'sum'   :obj.add(obj.a,obj.b)     }        data = json.dumps(L,default=ToJson)s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.connect(('192.168.1.54',9999))  #s.send(bytes(data,encoding='utf-8'))data = '{ "data":'+data+'}'s.send(bytes(data+'\n==END==\n',encoding='utf-8'))buff = []while True:    b = s.recv(1024)    if b:        buff.append(b)    else:        break;  for msg in buff:    #print(msg.decode('utf-8'))    print(msg.decode('gb2312'))s.close()

运行客户端,走你(不要注重demo,主要看效果)


服务端




Java处理完Python发过来的json数据之后,会告诉Python,兄弟,谢谢你啊,数据我收到了!当然,这是我说的。


客户端





本篇是对上一篇的承诺,如果我们只知道Python有个序列化和反序列化,而不知道怎么用的话,或者,我们就是自己跟自己玩,这种情况,完全不必担心反序列化会出问题,照着函数用就行;万一,让你和其他语言一起玩,你是不是就愣住了,这时候,不要怕,只要你会用Python的json模块,你就可以跟其他语言掰掰手腕了:"你要数据是吧,没问题,扔给你一个json字符串,自己玩去吧!",


原创粉丝点击