通过 redis 从 Cpp 应用程序发送到 Rust 应用程序的编码图像,无效的 UTF-8- TypeError

Encoded image sent over redis from Cpp app to Rust app, Invalid UTF-8- TypeError

提问人:lior.i 提问时间:11/7/2023 最后编辑:Christoph Rackwitzlior.i 更新时间:11/8/2023 访问量:78

问:

我正在从应用程序发送编码图像:cvredis pubsubCpp

cv::Mat output_image;
output_image = cv::Mat(pic_height, pic_width * 2, CV_8UC3);
cv::imwrite(filename, output_image);
std::vector<uchar> encoded_image;
cv::imencode(".png", output_image, encoded_image);
std::string image_str(encoded_image.begin(), encoded_image.end());
string image_msg;
image_msg = to_string(pic_id) + "~" + metadata + "~" + image_str;
RedisCommunicator::GetInstance()->Publish(image_channel, image_msg);

我正在使用以下方法在应用程序中接收图像:Rustredis-rs

let mut redis_pubsub = redis_connection.as_pubsub();

redis_pubsub.subscribe(image_channel).expect("Failed to subscribe to channel");
info!("subscribed to channel: {}", image_channel);

redis_pubsub.set_read_timeout(Some(Duration::from_secs(5))).expect("Failed to set read timeout");

for _ in 0..3 {
    info!("###### Waiting for message...");
    let log = match redis_pubsub.get_message(){
        Ok(T) => T,
        Err(e) => {info!("Failed to get message: {}", e); continue;},
    };
    let payload : String = match log.get_payload() {
        Ok(T) => T,
        Err(e) => {info!("Failed to get payload: {}", e);continue;},
    };
    if log_enabled!(Level::Debug) {
        debug!("Got log from channel: '{}', log: {}", log.get_channel_name(), payload);
    }
    info!("{{\"{}\": {}}}", image_channel, payload);
    sleep(Duration::from_secs(1));
};

我在 中收到格式错误。原木:Rust

[rusty_record] subscribed to channel: image_sender
[rusty_record] ###### Waiting for message...
[rusty_record] Failed to get payload: Invalid UTF-8- TypeError
[rusty_record] ###### Waiting for message...
[rusty_record] Failed to get payload: Invalid UTF-8- TypeError
[rusty_record] ###### Waiting for message...
[rusty_record] Failed to get payload: Invalid UTF-8- TypeError

看,频道里有消息:redis-clipubsub

redis-cli subscribe image_sender

1) "message"
2) "image_sender"
3) "3707~{\"pic_gain\":0,\"pic_exposure\":0,\"pic_time\":0,\"camera_id\":0,\"latitude\":0.000000,\"longitude\":0.000000,\"altitude\":0.000000,\"heading_degrees\":0.000000,\"auto_white_balance\":true}~\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x02\x01\x01\x01\x01\x01\x02\x01\x01\x01\x02\x02\x02\x02\x02\x04\x03\x02\x02\x02\x02\x05\x04\x04\x03\x04\x06\x05\x06\x06\x06\x05\x06\x06\x06\a\t\b\x06\a\t\a\x06\x06\b\x0b\b\t\n\n\n\n\n\x06\b\x0b\x0c\x0b\n\x0c\t\n\n\n\xff\xdb\x00C\x01\x02\x02\x02\x02\x02\x02\x05\x03\x03\x05\n\a\x06\a\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\xff\xc0\x00\x11\b\x00\xc0\x05\xa0\x03\x01\"\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1f\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\a\b\t\n\x0b\xff\xc4\x00\xb5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01}\x01\x02\x03\x00\x04\x11\x05\x12!1A\x06\x13Qa\a\"q\x142\x81\x91\xa1\b#B\xb1\xc1\x15R\xd1\xf0$3br\x82\t\n\x16\x17\x18\x19\x1a%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz\x83\x84\x85\x86\x87\x88\x89\x8a\x92\x93\x94\x95\x96\x97\x98\x99\x9a\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xb2\xb3\xb4\xb5\xb6\...

如果我发送一个常规字符串,它可以正常工作。

CPP:

string image_msg;
image_msg = to_string(pic_id) + "~" + metadata + "~" + "image_str";
RedisCommunicator::GetInstance()->Publish(image_channel, image_msg);

我在 中收到消息。原木:Rust

[rusty_record] subscribed to channel: image_sender
[rusty_record] ###### Waiting for message...
[rusty_record] Got log from channel: 'image_handler_0', log: 7812~{"pic_gain":0,"pic_exposure":0,"pic_time":0,"camera_id":0,"latitude":0.000000,"longitude":0.000000,"altitude":0.000000,"heading_degrees":0.000000,"auto_white_balance":true}~image_str
[rusty_record] {"image_sender": 7812~{"pic_gain":0,"pic_exposure":0,"pic_time":0,"camera_id":0,"latitude":0.000000,"longitude":0.000000,"altitude":0.000000,"heading_degrees":0.000000,"auto_white_balance":true}~image_str}
[rusty_record] ###### Waiting for message...
[rusty_record] Got log from channel: 'image_handler_0', log: 7813~{"pic_gain":0,"pic_exposure":0,"pic_time":0,"camera_id":0,"latitude":0.000000,"longitude":0.000000,"altitude":0.000000,"heading_degrees":0.000000,"auto_white_balance":true}~image_str
[rusty_record] {"image_sender": 7813~{"pic_gain":0,"pic_exposure":0,"pic_time":0,"camera_id":0,"latitude":0.000000,"longitude":0.000000,"altitude":0.000000,"heading_degrees":0.000000,"auto_white_balance":true}~image_str}
[rusty_record] ###### Waiting for message...
[rusty_record] Got log from channel: 'image_handler_0', log: 7814~{"pic_gain":0,"pic_exposure":0,"pic_time":0,"camera_id":0,"latitude":0.000000,"longitude":0.000000,"altitude":0.000000,"heading_degrees":0.000000,"auto_white_balance":true}~image_str
[rusty_record] {"image_sender": 7814~{"pic_gain":0,"pic_exposure":0,"pic_time":0,"camera_id":0,"latitude":0.000000,"longitude":0.000000,"altitude":0.000000,"heading_degrees":0.000000,"auto_white_balance":true}~image_str}

** 还是新手,如果有一些新手错误,请见谅。Rust

C++ Rust Redis UTF-8

评论

0赞 Retired Ninja 11/7/2023
我想知道是否只是将直接二进制数据转储到字符串中。如果是这样,您可能需要一个额外的步骤,例如对输出进行 base64 编码,以便将其用作文本。imencode
0赞 lior.i 11/7/2023
感谢@RetiredNinja,看起来imencode压缩了图像并将其存储在内存缓冲区中。
5赞 Jmb 11/7/2023
StringRust 中的 s 应该是 UTF-8 编码的文本。您应该用于二进制数据,例如图像。Vec<u8>
3赞 Christoph Rackwitz 11/7/2023
答案是肯定的OpenCV 的 imencode 为您提供直接的二进制数据,您可以将其转储到文件中。没有理由它应该额外将其转换为十六进制或 Base64。完全没有。-- Redis 可以做二进制数据。发送二进制数据,而不是字符串。字符串不是二进制数据。redis.io/docs/interact/programmability/triggers-and-functions/......
3赞 Jmb 11/7/2023
如果用于有效负载,则可以使用 splitn (2, '~') 拆分消息,然后使用 str::from_utf8 将文本字段转换为字符串。Vec<u8>

答:

2赞 Jmb 11/8/2023 #1

StringRust 中的 s 应该是 UTF-8 编码的文本。您应该用于二进制数据,例如图像。大多数“字符串”操作函数也存在于字节切片中,以及像 这样的类型,因此您可以像 一样轻松地解析 a(使用 splitn)并使用 str::from_utf8 转换包含文本的部分Vec<u8>&[u8]Vec<u8>Vec<u8>String

let mut redis_pubsub = redis_connection.as_pubsub();

redis_pubsub.subscribe(image_channel).expect("Failed to subscribe to channel");
info!("subscribed to channel: {}", image_channel);

redis_pubsub.set_read_timeout(Some(Duration::from_secs(5))).expect("Failed to set read timeout");

for _ in 0..3 {
    info!("###### Waiting for message...");
    let log = match redis_pubsub.get_message(){
        Ok(T) => T,
        Err(e) => {info!("Failed to get message: {}", e); continue;},
    };
    let payload : Vec<u8> = match log.get_payload() {
        Ok(T) => T,
        Err(e) => {info!("Failed to get payload: {}", e);continue;},
    };
    if log_enabled!(Level::Debug) {
        debug!("Got log from channel: '{}', log: {}", log.get_channel_name(), payload);
    }
    let parts: Vec<_> = payload.splitn (3, |&c| c == b'~').collect();

    info!("id: {:?}", str::from_utf8 (parts[0]));
    info!("metadata: {:?}", str::from_utf8 (parts[1]));
    info!("data: {:?}", parts[2]);
    sleep(Duration::from_secs(1));
};

评论

0赞 lior.i 11/8/2023
我认为这应该是因为是项目的数量splitn (3, |&c| c == b'~')n
0赞 Jmb 11/8/2023
@lior.i 你是对的,编辑过。