关于 Java io 的一些问题

2020-05-08 08:45:17 +08:00
 peterpei

关于数据处理的一些问题

最近在做一个小项目,需要在 python 和 Java 之间进行数据传输,用 socket 通信。 python 代码是这样的:

    Head_Info = json.dumps(File_Dire)
    Head_Info_Len = struct.pack('i', len(Head_Info))
    #send file
    Target_Sever.send(Head_Info_Len)
    Target_Sever.send(Head_Info.encode('utf-8'))
    with open(File, 'rb') as F:
        data = F.read()
        Target_Sever.sendall(data)
        print   ("done")

大概就是把数据的长度(4 字节)+数据的一些信息(json)+数据打成一个包。 差不多是这样的:

B   {"Type": "File", "File_Name": "tempfile.fasttext", "File_Size": 6}hello!

在 python 里面是这样接收数据的:

    Head_Struct = client.recv(1024)
    Head_Len = struct.unpack('i',Head_Struct)[0]
    File_Data_Raw = client.recv(Head_Len)# receve info

但到了 Java,输入变成了 IO 流,我并不能像 python 里面一样分批次拿信息了,只能一下拿完,但是对于文件传输,这相当于破坏了文件的结构,求一个解决思路(尽量在不改动 python 结构的前提下)。

还有就是关于indexOf函数的一个问题

我想把上述的数据包中的数据信息提取出来,代码如下

          String ending = "}";
          int info = Fileline.indexOf(ending) - 4;//减去 4 字节的报头
          System.out.println(Fileline.substring(4, info));

输出的结果却是这样的

{"Type": "File", "File_Name": "tempfile.fasttext", "File_Size

请问是我在哪里出错了吗?
由于我只是对 coding 感兴趣,并没有进行系统学习,若出错,烦请指正 :)
Thanks again

2974 次点击
所在节点    Java
12 条回复
dallaslu
2020-05-08 08:56:12 +08:00
和 indexOf 关系不大。重点在于 substring 第二个参数是 endIndex, 不是 length 。

另外 Java 接收数据是怎么写的呢?
sandrew1945
2020-05-08 09:00:28 +08:00
Java 也可以按照长度分批读取流,建议用 netty 来写
luozic
2020-05-08 09:11:34 +08:00
使用一种公共的流定义,python 和 java 使用公共的定义通信,保证传输完整性的部分在流定义里面完成。
n770011
2020-05-08 09:13:57 +08:00
InputStream 函数 read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。可以分批次读。至于怎么解析,就看你数据协议怎么设计,如果不好解析那就证明你数据协议设计有问题。
HivenYang
2020-05-08 09:23:33 +08:00
拿到字节流,然后先读 4 个字节的长度,根据长度读取相应的字节数,然后进行解析,循环进行此操作,直到数据读完了,简单的么就直接用 io 包下的 ServerSocket,考虑性能么就研究下 NIO 、AIO 和 Netty
WhenAtRains
2020-05-08 09:23:54 +08:00
python 编码后,java 没有解码正确。我最近学习的 netty 里面 公共的比较简单的解码器有行编解器和固定长度编解码器。但是我觉得比较麻烦的是自己写一个编解码器,尤其是解码。
zhuangzhuang1988
2020-05-08 09:33:05 +08:00
最近刚刚在看 mercurial 的 command 传输协议,和你这个像
https://www.mercurial-scm.org/wiki/CommandServer

可以看下对应的 java 客服端怎么实现的
https://bitbucket.org/aragost/javahg/src/default/src/main/java/com/aragost/javahg/internals/HgInputStream.java
yty2012g
2020-05-08 09:53:03 +08:00
使用 netty 可以很简单的处理吧,实现一个自定义的 ByteToMessageDecoder,首先标记一下读取位置,然后读取 4byte,得到消息长度,如果 ByteBuf 的剩余长度足够,就直接读取消息长度的内容,否则 return 并等待下一次读取,直到剩余长度满足消息长度。或者如果你不想一次读完,就每次读取就放到一个 byte 数组里面,直到 byte 数组满足待读取的长度。
wysnylc
2020-05-08 10:18:12 +08:00
socket.io 少走弯路
aguesuka
2020-05-08 12:12:19 +08:00
java 里的 inputstream 的 read 方法返回的是这次读的 btye 数,比如传入长为 100 的数组,如果返回 40,那么只读到前 40 个,你需要循环 read,直到返回值为-1 或者读到了你想读的字节
aguesuka
2020-05-08 12:20:16 +08:00
比如 python 一次发了两条数据,一条长度为 8 一条为 16 。那第一次用长度为 4 的 byte[]读 4 个字节,第二次用长度为 8byte[]的读 8 个字节,便得到了第一条消息
xinQing
2020-05-13 18:06:01 +08:00
哈哈,解码错咯。建议用 netty 这样的网络库,自己用 Inputstream 拿自己做宝搞

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/669505

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX