字符串中含有\x00 怎么解决?

benjiam 2005-07-31 10:54:41
string aaa;
我将输入的信息保存在aaa 里面

现在需要保存一个文件的内容

因为是2进制文件 所以里面有\x00 字符

所以在输入的时候 会断掉
aaa += "\x0D\x0A\x0D\x0A\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x00\x00\x00\xFF\xFF\xFF\x21\xF9\x04\x01\x00\x00\x01\x00\x2C\x00\x00"
在中途会断掉

我想这个问题 只要是网络传输都会遇到
比如人家传给你一个含有\x00 的字符串 那么缓存中就有\x00 字符了 但不是缓存结束的地方
这时候用strlen 取缓存长度 再取数据 显然不对
你怎么处理呢?

...全文
7580 39 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
39 条回复
切换为时间正序
请发表友善的回复…
发表回复
beepbug 2005-08-03
  • 打赏
  • 举报
回复
一般来说,不能用字符串来处理二进制文件。只有一些很特殊的场合除外。
你应该按照这个二进制文件内容的特点,用字节、字节流、数值型等来处理。
benjiam 2005-08-03
  • 打赏
  • 举报
回复
谢谢
因为要支持http 协议 和 其他的2个协议 所以传来的文件大小未知 buff[] 无法保证一定能包含整个命令
所以才这么做的




Alan S1 2005-08-02
  • 打赏
  • 举报
回复
mark
benjiam 2005-08-02
  • 打赏
  • 举报
回复
因为很多地方都需要用string 所以我才要坚持用string

而且string 也并非不能插入 \x00 字符串 ( 我测试的结果)
例如 string aa ="aaaaaaaa";
cout << aa.size() << endl;
aa += "ddd";
cout << aa.size() << endl;
aa[5] = 0x00;
cout << aa.size() << endl;

for (int i =0 ; i < aa.size(); i++)
cout << (int) aa[i] << endl;

string 有很多字符数组所不具有的优点 在简洁 内存分配 效率上都强过你自己写的代码


至于态度问题 我感觉我没有过错 我感谢大家的帮助 但是对于你帮助中的错误
我仍然会指出 如果这就是所谓 态度不好 我真是无话可说
大家都是在讨论问题
mayflowers 2005-08-02
  • 打赏
  • 举报
回复
如果你的数据包不太大,在一个你的应用可以容忍大小的buffer里面能够放得下一个数据包,你可以直接在buffer上解析,得到其中任何你感兴趣的数据,比你用buffer的内容构造一个string,然后再用string解析要高效不少。

比如说:
class BufferReader
{
public:
BufferReader(unsigned char* buffer, unsigned int len);

int ReadInt(); // 从buffer中读取一个整数
short ReadShort();
string ReadString(int strlen); // 从buffer中读取固定长度的字符串

void SkipBytes(int len); // 跳过几个无用的字符

private:
unsigned char* pbuffer;
unsigned int currentPos;
unsigned int length;
}

当然这个仅仅是语法解析器,你还需要用它来构造自己的语义解析器。如果你的数据结构(字节流的结构)比较简单,也可以用几个函数代替,不用这个类。

如果一个buffer不能完全容纳一个数据包,需要别的方法。
等有空的时候把代码贴出来。
benjiam 2005-08-02
  • 打赏
  • 举报
回复
谢谢 黯然神伤)

你的代码基本能完成我的要求了

这里不用sting 的话 用什么比较好呢?

因为我从tcp 连接中读取字符流 然后从中分辨出命令 参数 或者是文件

我的想法是 tcp-> buff[] -> string
不同的函数对string 进行分析
因为string 带有find size 等参数 操作起来很方便
mayflowers 2005-08-02
  • 打赏
  • 举报
回复
btw: 最后的std::cin >> str仅仅是为了最后命令行在运行时不退出。习惯,呵呵。
mayflowers 2005-08-02
  • 打赏
  • 举报
回复
如果真的想用,string可以容纳任何你需要的字符,只是这样子并不是string应该被使用的方法。
string的length并不是每次都遍历整个“字符串”得到的。

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

int main(int argc, char* argv[])
{
string str;

str = "heiheihei";
str = str + (char)0; // 在“字符串”插入0x00
str = str + "hohohoho";

std::cout << str.length() << std::endl; // length is 18

string str2(str.c_str(), str.length()); // 构造一个包含0x00的“字符串”

std::cout << str2.length() << std::endl; // length is 18

std::cin >> str;

return 0;
}

如果你真的需要,上面的两种方法可以满足你。

但是,如上面几个人(我看来都是好心)所说,你并不太懂得“协议”这个词的含义;而且这个地方实在不怎么适合用string。认真的补充一下这方面的知识,相信可以有更大的收获,而不仅仅是你现在的程序。多听多想多看才可以进步的比较快。
crystal_heart 2005-08-02
  • 打赏
  • 举报
回复
>刚问过一个朋友,用string也没有问题。

你所有解决问题的方案,都是基于这一基础之上吗?
benjiam 2005-08-02
  • 打赏
  • 举报
回复
\x00->\xcc \xcc 会和原来的\xcc 混在一起阿

当然 我想到 接受->base64 ->string那是可以的 但是代价好像太大了
CSDNWW 2005-08-02
  • 打赏
  • 举报
回复
接收->char[](把\x00转成\xcc, 呵呵)->string, 反之就反向操作, 不是都ok吗?
dirdirdir3 2005-08-01
  • 打赏
  • 举报
回复
用二进制数组来进行处理。
benjiam 2005-08-01
  • 打赏
  • 举报
回复
那么我获取的字节流 应该怎么保存起来 比较常用的方法是保存在什么对象里面呢?

比如一个http 连接

我从http head 的context length 参数部分 取得长度

然后获取后面那么多字节 我应该存放在什么地方

如果没有\x00 那么字符串是个很简单的应用

现在无法保证这个条件 因为如果传文件 过来 里面肯定有\x00
我怎么存放这个传来字节流呢?
僵哥 2005-08-01
  • 打赏
  • 举报
回复
对着这样滴贴子,以及这样滴楼主,偶是见多了,更多还是学习不认真,既然楼上朋友都已经把问题说清楚了,而楼主去一味采用自己的所以然去理解,而不接受人家所讲述的“知识”那实在没有办法。偶对这样滴人也无能为力。
偶随便抓一贴给大家看看^_^
http://community.csdn.net/Expert/topic/4046/4046119.xml?temp=.739422

所以,偶对着如此滴楼主,只有两字“无语”!
benjiam 2005-08-01
  • 打赏
  • 举报
回复
刚问过一个朋友,用string也没有问题。
how to ?


因为水平差 很多地方都是用string 要全部修改 量太大了
windcandle 2005-08-01
  • 打赏
  • 举报
回复
boxban(冻酸梨) ( ) 说的不错。

“所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息”是对的,比如VB6里的winsock控件,在接收到数据的时候,有两个有用的属性值bytestotal(接收的总字节数)和bytesreceived(已经接收到的字节数),通过这两个值就可以判断数据是否已经接收完。

如果底层协议无法返回收到的字节数,那么就要在应用一层定义这个协议。比如定一个协议报文:
报文长度(4字节)+报文内容(变长)
使用报文长度这4字节表示报文内容的长度,这样,应用程序先接收4字节数据,就知道后续报文的长度了,然后再接收这么长的数据就OK了。

不管是字节流还是含有0x00的字符串,总之不能用strlen来取长度,用sizeof也不对(我见过很多初学者,一旦strlen的返回值不对了,就开始用sizeof,瞎蒙...),必须要根据实际情况正确地算法来取长度。一般来讲应用程序里出现含不可见字符(包括0x00)时,字符串的长度都应该是已知的,否则你怎么来对其进行操作啊,那就完全是程序设计者的问题了。
boxban 2005-08-01
  • 打赏
  • 举报
回复
你说得问题基本上无法解决的。
所有有用的网络协议都能够通过在数据包首部包含指示长度的方式提供你需要的信息。如果你使用的协议无法提供这个信息,或者是协议设计缺陷,或者你还没有完全理解这个协议。

另外,你的话实际上是个病语“传给你一个含有\x00 的字符串”:在C里面字符串是如何定义的呢?准确地讲,他传给你的是“字节流”,而不是字符串。
Atomictry 2005-08-01
  • 打赏
  • 举报
回复
对于这种情况,不要用strcpy,string这些东东,用memcpy函数。网络传输中包的长度是包含在包中的。
benjiam 2005-08-01
  • 打赏
  • 举报
回复
对于缓冲区的实际大小问题,如果当中可能传递'\0',那么除非wchar_t *,或者数据整体本身并非单一个字符串,在这种情况下若是参数,通常需要带入数据长度。
我并不知道要传来的数据的长度。我需要检测数据内容 才知道是否内容结束
OpenHero 2005-08-01
  • 打赏
  • 举报
回复
shellcode里面有一种解决方法~~~
把所有的code都 与 一个高的数 for example: \x99 then unencode
加载更多回复(19)

65,199

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧