【问题标题】:How to read a python binary string from Standard Input in Java如何从Java中的标准输入读取python二进制字符串
【发布时间】:2013-11-14 15:29:29
【问题描述】:

我有一个使用协议缓冲区的 python 应用程序,以及一个使用协议缓冲区的 Java 应用程序。我想要做的只是能够将消息(序列化后的二进制字符串)打印到标准输出。为此,我在 Python 应用程序中执行以下操作:

def printMessage(self, protobuf_msg):

data = protobuf_msg.SerializeToString()

sys.stdout.write(数据)

sys.stdout.flush()

def main():

protobuf_msg = create_message()

controller.printMessage(protobuf_msg)

然后,我想通过管道输出此输出(python pytonApp | java javaApp)并使用 javaApp 获取此数据并对其进行解析。我尝试了两种选择,使用 Protobuf API:

protected ProtobufMsg receiveMsg() throws Exception{

ProtobufMsg 消息 = null;

message = protobuf_msg.parseFrom(System.in);

返回消息;

}

我也尝试通过以下方式对 BufferedInputStream 执行此操作:

protected ProtobufMsg receiveMsg() throws Exception{

ProtobufMsg 消息 = null;

byte[] data = receiveFromStd();

message = protobuf_msg.parseFrom(data);

返回消息;

}

public byte[] receiveFromStd() 抛出异常{

BufferedInputStream 输入 = 新的 BufferedInputStream(System.in);

字节[] out = 新字节[1024];

int i=0;

System.out.println("Entering While");

while((out[i] = (byte)input.read())!= -1){

    i++;

System.out.println("读取一个字节");

}

byte[] data_out = new byte[i];

for(int l=0; l<data_out.length; l++){

    data_out[l]=out[l];

}

return data_out;

}

所以很明显我做错了什么,但我无法意识到我做错了什么, 因为它停留在 input.read()...

编辑: 我决定改变策略,现在我首先得到数据包的大小,然后是数据包,因为我正在使用 input.read(byte []) 函数...... 我使用的脚本如下:

FIFO_FILE=/tmp/named_$$   # unique name ($$ is the PID of the bash process running this script)
mkfifo $FIFO_FILE   
export FIFO_FILE    # export the env variable
ant run &    # start a background process that reads the env variable and reads the fifo
cat > $FIFO_FILE #  reads the standard input and writes to the fifo 
rm $FIFO_FILE

我称之为:python pythonApp.py | ./script

【问题讨论】:

  • readLine() 需要行尾字符才能返回或“解除阻止”。所以也许你还需要添加sys.stdout.write('\n')
  • 提示:Stackoverflow 编辑器中的{} 按钮将选定的行转换为正确缩进、突出显示的代码。

标签: java python protocol-buffers stdin


【解决方案1】:

你不能使用readLine(),因为你有二进制数据。

  1. 不要使用Reader API,你有二进制数据。只需使用BufferedInputStream

  2. protobuf 肯定有一个 API 可以直接从流中读取。用那个。不要忘记刷新子节点的输出,否则数据将永远存在于 4K 管道缓冲区中:

    sys.stdout.write(data)
    sys.stdout.flush()
    

【讨论】:

  • 第二个不起作用,因为只有在孩子终止时才会收到 EOF。您确实需要提前知道要读取多少字节。我的印象是 protobuf 可以做到这一点,所以第一次调用应该可以工作,除非你忘记刷新孩子。
  • 谢谢,我用protobuf的API试过了:protobufMsg.parseFrom(System.in);而且,我尝试使用 BufferedInputStream: BufferedInputStream input = new BufferedInputStream(System.in); while((out[i] = (byte)input.read())!= -1){ i++; }。但在这种情况下,它会停留在 input.read() 一次并且从不读取任何字节。感谢您的帮助@AaronDigulla。
  • 我已经刷新了 python 应用程序的输出,并且我已经尝试使用 protobuf API 和 BufferedInputStream 并且仍然无法正常工作......但我不确定我是否正确使用BufferedInputStream...
  • 编辑问题并向我们展示您用来发送的 Python 代码和您用来阅读的 Java 代码。
  • sys.stdout.write(data)之后添加sys.stdout.flush()
【解决方案2】:

我无法评论 Python 方面,但如果是二进制消息你可以这样做

    FileInputStream in = new FileInputStream(fileName);

    message = Extension01.Message.parseFrom(in);

或者如果是分隔消息:

    FileInputStream in = new FileInputStream(fileName);

    message = Extension01.Message.parseDelimitedFrom(in);

不需要按字节读取

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2010-12-08
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    相关资源
    最近更新 更多