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

上一篇,我们遗留了一个问题,那就是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();
		}
		
  }
}


启动服务端,如下:


Python3学习(33)--序列和反序列化(二)_第1张图片


Python客户端demo


#!/usr/bin/env Python3
# -*- encoding:utf-8 -*-

import socket,pickle

class 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+b

person = 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服务端


Python3学习(33)--序列和反序列化(二)_第2张图片

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


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




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


Python3学习(33)--序列和反序列化(二)_第3张图片


这就让人不淡定了,那我怎么让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

启动服务端


Python3学习(33)--序列和反序列化(二)_第4张图片



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


#!/usr/bin/env Python3
# -*- encoding:utf-8 -*-

import socket,pickle,json

class 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+b

p1 = Employee('张三','男',35,6000.00)
#动态绑定实例的属性变量
p1.a = 4
p1.b = 5
p2 = Employee('李婷','女',25,4000.00)
p2.a = 10
p2.b = 20
p3 = Employee('王五','男',30,5000.00)
p3.a = 11
p3.b = 25

L=[]
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,主要看效果)


服务端


Python3学习(33)--序列和反序列化(二)_第5张图片


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


客户端


Python3学习(33)--序列和反序列化(二)_第6张图片



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


你可能感兴趣的:(Pyhon3.X学习)