请各位大侠帮忙,包含取值为0的字节数组如何转成字符串

时间:2023-01-11 13:10:29
背景:网路传输字节数组,字节数组转成字符串后传输(因为用了thrift,不支持C++字节数组)。
问题:字节数组包含取值为0,字符串会把0当成结束符而出错。Base64编解码暂不考虑,原因是性能不满足,因为字节数组最大可达到100M

15 个解决方案

#1


网络传输设置的是传输的字节个数吧,不是靠结束符来判断的吧?

#2


不是底层,是thrift

#3


没明白楼主意思,说的不清楚。

不支持C++数组,那支持什么?
用的什么语言?
可以用unsigned char arr[]?

thrift介绍上说支持C++,这个没用过

#4


解释3楼的疑问:thrift定义的字节数组这个数据类型是binary,生成java代码对应的是ByteBuffer,生成C++代码对应的却是string,官网上也是描述的binary只适用java。

因为要传递的是字节数组,而对于C++和java都支持的thrift数据类型是string,因此考虑在数据传输前将字节数组转成string再传输。

#5


那就把binary转换成hex的字符串,然后再进行传输,这样就会加大传输量
另一端同样反转换就可以了

引用 4 楼 muzhi007 的回复:
解释3楼的疑问:thrift定义的字节数组这个数据类型是binary,生成java代码对应的是ByteBuffer,生成C++代码对应的却是string,官网上也是描述的binary只适用java。

因为要传递的是字节数组,而对于C++和java都支持的thrift数据类型是string,因此考虑在数据传输前将字节数组转成string再传输。

#6


该回复于2013-02-16 16:21:55被管理员删除

#7


这种方式占用太多资源,还是优先考虑二进制方式传输

Quote: 引用 5 楼 shit_moment 的回复:

那就把binary转换成hex的字符串,然后再进行传输,这样就会加大传输量
另一端同样反转换就可以了

#8


thrift会把binary转换成string,而string本身就是遇到0就结束。这是矛盾的。
资源会增加一倍的消耗,这个看选择了。
如果很大可以把hex string压缩一下再传输。
再或者想办法设置thrift把binary转换的时候,直接转换成C++的binary

引用 7 楼 muzhi007 的回复:
这种方式占用太多资源,还是优先考虑二进制方式传输

Quote: 引用 5 楼 shit_moment 的回复:
那就把binary转换成hex的字符串,然后再进行传输,这样就会加大传输量
另一端同样反转换就可以了

#9


C++有binary数据类型吗,网上没搜到,是否有资料共享下

Quote: 引用 8 楼 shit_moment 的回复:

thrift会把binary转换成string,而string本身就是遇到0就结束。这是矛盾的。
资源会增加一倍的消耗,这个看选择了。
如果很大可以把hex string压缩一下再传输。
再或者想办法设置thrift把binary转换的时候,直接转换成C++的binary

#10


以前我用string存储过含有0的数据。
这种方法属于非常规的方法,这种非常规的方法是用起来要小心。
仅供参考

#include <iostream>
#include <string>
using namespace std;

void printstr(string s)
{
cout<<"size = "<<s.size()<<endl;
string::iterator it = s.begin();
for (; it != s.end(); it++)
{
cout<<*it;
}
}

void main()
{
char arr[] = "this is a test string";
string src = arr;
char* p = (char*)src.c_str();
p[2] = '\0';
printstr(src);

return;
}


引用 9 楼 muzhi007 的回复:
C++有binary数据类型吗,网上没搜到,是否有资料共享下

Quote: 引用 8 楼 shit_moment 的回复:
thrift会把binary转换成string,而string本身就是遇到0就结束。这是矛盾的。
资源会增加一倍的消耗,这个看选择了。
如果很大可以把hex string压缩一下再传输。
再或者想办法设置thrift把binary转换的……

#11


好像不少人这样用。

#include <string>
namespace std{
typedef unsigned char byte;
typedef basic_string<byte, char_traits<byte>, allocator<byte>> sbyte;
}

#12


void HexDump(char *buf,int len) {
    int i,j,k;
    char binstr[80];

    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%04x -",i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            printf("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        printf("%s\n",binstr);
    }
}

#13


多谢各位,问题已经解决,不需要再做字符串转换了。

java发送给C++:java使用ByteBuffer发送没有问题。C++读取没有问题,因为thrift在字符串前面加了长度(ByteBuffer中的字节长度),长度也发给了C++,C++按照这个长度读取字符串,没有问题。
C++发送给java:C++发送存在问题,因为调用了string的size()方法获取字符串长度,遇到'\0'截止了。java按照ByteBuffer读没有问题。

因此,只要string的size()方法能够返回实际长度,忽略string中间'\0'就能解决问题了。具体可以使用string的assign()方法或者构造函数指定大小,则size()方法可以忽略中间的'\0。

测试代码:
std::string str;
unsigned char buff[20];
int maxSize = 20;

for (int i=0; i<maxSize; i++)
{
    buff[i] = i;
}
buff[9] = 0;
buff[19] = 0;

str.assign((const char *)buff, maxSize);

printf("size=%d\n", str.size());
printf("length=%d\n", str.length());

for (int i=0; i<maxSize; i++)
{
    printf("%d ", str.at(i));
}
printf("\n");


测试结果:
size=20
length=20
0 1 2 3 4 5 6 7 8 0 10 11 12 13 14 15 16 17 18 0

#14


ok,今天结贴

#15


引用 13 楼 muzhi007 的回复:
多谢各位,问题已经解决,不需要再做字符串转换了。

java发送给C++:java使用ByteBuffer发送没有问题。C++读取没有问题,因为thrift在字符串前面加了长度(ByteBuffer中的字节长度),长度也发给了C++,C++按照这个长度读取字符串,没有问题。
C++发送给java:C++发送存在问题,因为调用了string的size()方法获取字符串……

小心长度超长!

#1


网络传输设置的是传输的字节个数吧,不是靠结束符来判断的吧?

#2


不是底层,是thrift

#3


没明白楼主意思,说的不清楚。

不支持C++数组,那支持什么?
用的什么语言?
可以用unsigned char arr[]?

thrift介绍上说支持C++,这个没用过

#4


解释3楼的疑问:thrift定义的字节数组这个数据类型是binary,生成java代码对应的是ByteBuffer,生成C++代码对应的却是string,官网上也是描述的binary只适用java。

因为要传递的是字节数组,而对于C++和java都支持的thrift数据类型是string,因此考虑在数据传输前将字节数组转成string再传输。

#5


那就把binary转换成hex的字符串,然后再进行传输,这样就会加大传输量
另一端同样反转换就可以了

引用 4 楼 muzhi007 的回复:
解释3楼的疑问:thrift定义的字节数组这个数据类型是binary,生成java代码对应的是ByteBuffer,生成C++代码对应的却是string,官网上也是描述的binary只适用java。

因为要传递的是字节数组,而对于C++和java都支持的thrift数据类型是string,因此考虑在数据传输前将字节数组转成string再传输。

#6


该回复于2013-02-16 16:21:55被管理员删除

#7


这种方式占用太多资源,还是优先考虑二进制方式传输

Quote: 引用 5 楼 shit_moment 的回复:

那就把binary转换成hex的字符串,然后再进行传输,这样就会加大传输量
另一端同样反转换就可以了

#8


thrift会把binary转换成string,而string本身就是遇到0就结束。这是矛盾的。
资源会增加一倍的消耗,这个看选择了。
如果很大可以把hex string压缩一下再传输。
再或者想办法设置thrift把binary转换的时候,直接转换成C++的binary

引用 7 楼 muzhi007 的回复:
这种方式占用太多资源,还是优先考虑二进制方式传输

Quote: 引用 5 楼 shit_moment 的回复:
那就把binary转换成hex的字符串,然后再进行传输,这样就会加大传输量
另一端同样反转换就可以了

#9


C++有binary数据类型吗,网上没搜到,是否有资料共享下

Quote: 引用 8 楼 shit_moment 的回复:

thrift会把binary转换成string,而string本身就是遇到0就结束。这是矛盾的。
资源会增加一倍的消耗,这个看选择了。
如果很大可以把hex string压缩一下再传输。
再或者想办法设置thrift把binary转换的时候,直接转换成C++的binary

#10


以前我用string存储过含有0的数据。
这种方法属于非常规的方法,这种非常规的方法是用起来要小心。
仅供参考

#include <iostream>
#include <string>
using namespace std;

void printstr(string s)
{
cout<<"size = "<<s.size()<<endl;
string::iterator it = s.begin();
for (; it != s.end(); it++)
{
cout<<*it;
}
}

void main()
{
char arr[] = "this is a test string";
string src = arr;
char* p = (char*)src.c_str();
p[2] = '\0';
printstr(src);

return;
}


引用 9 楼 muzhi007 的回复:
C++有binary数据类型吗,网上没搜到,是否有资料共享下

Quote: 引用 8 楼 shit_moment 的回复:
thrift会把binary转换成string,而string本身就是遇到0就结束。这是矛盾的。
资源会增加一倍的消耗,这个看选择了。
如果很大可以把hex string压缩一下再传输。
再或者想办法设置thrift把binary转换的……

#11


好像不少人这样用。

#include <string>
namespace std{
typedef unsigned char byte;
typedef basic_string<byte, char_traits<byte>, allocator<byte>> sbyte;
}

#12


void HexDump(char *buf,int len) {
    int i,j,k;
    char binstr[80];

    for (i=0;i<len;i++) {
        if (0==(i%16)) {
            sprintf(binstr,"%04x -",i);
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        } else if (15==(i%16)) {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
            sprintf(binstr,"%s  ",binstr);
            for (j=i-15;j<=i;j++) {
                sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
            }
            printf("%s\n",binstr);
        } else {
            sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);
        }
    }
    if (0!=(i%16)) {
        k=16-(i%16);
        for (j=0;j<k;j++) {
            sprintf(binstr,"%s   ",binstr);
        }
        sprintf(binstr,"%s  ",binstr);
        k=16-k;
        for (j=i-k;j<i;j++) {
            sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');
        }
        printf("%s\n",binstr);
    }
}

#13


多谢各位,问题已经解决,不需要再做字符串转换了。

java发送给C++:java使用ByteBuffer发送没有问题。C++读取没有问题,因为thrift在字符串前面加了长度(ByteBuffer中的字节长度),长度也发给了C++,C++按照这个长度读取字符串,没有问题。
C++发送给java:C++发送存在问题,因为调用了string的size()方法获取字符串长度,遇到'\0'截止了。java按照ByteBuffer读没有问题。

因此,只要string的size()方法能够返回实际长度,忽略string中间'\0'就能解决问题了。具体可以使用string的assign()方法或者构造函数指定大小,则size()方法可以忽略中间的'\0。

测试代码:
std::string str;
unsigned char buff[20];
int maxSize = 20;

for (int i=0; i<maxSize; i++)
{
    buff[i] = i;
}
buff[9] = 0;
buff[19] = 0;

str.assign((const char *)buff, maxSize);

printf("size=%d\n", str.size());
printf("length=%d\n", str.length());

for (int i=0; i<maxSize; i++)
{
    printf("%d ", str.at(i));
}
printf("\n");


测试结果:
size=20
length=20
0 1 2 3 4 5 6 7 8 0 10 11 12 13 14 15 16 17 18 0

#14


ok,今天结贴

#15


引用 13 楼 muzhi007 的回复:
多谢各位,问题已经解决,不需要再做字符串转换了。

java发送给C++:java使用ByteBuffer发送没有问题。C++读取没有问题,因为thrift在字符串前面加了长度(ByteBuffer中的字节长度),长度也发给了C++,C++按照这个长度读取字符串,没有问题。
C++发送给java:C++发送存在问题,因为调用了string的size()方法获取字符串……

小心长度超长!