我正在使用WinInet连接和检索我们的服务器之一的信息。 我正在使用以下内容:
indexdata: array of byte[1..5000] of byte; infoBuffer: array [0..5000] of char; BufferSize: DWORD; reserved: DWORD; text: string; BufferSize := Length(infoBuffer); res := HttpQueryInfo(hHttpRequest,HTTP_QUERY_RAW_HEADERS_CRLF,@infoBuffer,BufferSize,Reserved); Reserved := 0; InternetReadFile(hHttpRequest,@indexdata,sizeof(indexdata),Reserved); SetLength(text,Reserved); copyMemory(@text[1],@indexdata[1],Reserved);
到目前为止,这两个字节数组已经足够了。 事情变了。 服务器现在可以返回可以大于或小于5000的信息; 最糟糕的是,InternetReadFile可以在infoBuffer中返回一个可变的大小。
所以我试图声明索引数据和infobuffer作为字节数组,然后使用SetLength设置其长度,但发生了2件事情。
1)我仍然不知道服务器将返回的索引数据的大小,所以我不能正确设置它,例如,100000。
io_submit等待所有oracle dbwriter I / O
将命令中的值存储到数组bash中
C shell:如何从一行标准input创build多个数组?
从dynamic数组中find唯一的整数和
空间的静态分配有多大?
2)我不能使用(因为它现在)copyMemory传递低(indexdata)复制索引数据到一个简单的stringvariables,所以我可以使用的数据。
如何在Delphi中处理这个问题? 我可以用C来做,但我似乎无法在Delphi中正确地做到这一点。
代码表示赞赏
谢谢!
字符数组到LPCTSTR转换c
传递一个数组作为Linux内核模块的命令行参数
在c中如何处理string数组
将IP地址格式化为数组和parsing输出
字符数组问题
你知道char是自2009年Delphi以来的一个Unicode字符 ,但在Delphi 2009之前是ANSI字符。同样,在Delphi 2009中,一个string是一个UnicodeString ,而不是一个AnsiString 。
所以,当你写SetLength(text,Reserved)时,你将SetLength(text,Reserved)的字符数设置为Reserved 。 但是字节数将是2*Reserved 。
换句话说,在Delphi 2009+中,一个char不是一个byte ,而是两个字节。
您可以通过用AnsiString替换所有带有AnsiChar string和所有string来取回旧的行为。
更新
既然你没有发布你的整个代码,我真的不知道问题是什么。 不过,你可能会发现阅读我在Delphi中使用InternetReadFile的例子很有意思。 看到我对这个问题的回答 。 这是一个充分的工作示例,如何使用Delphi和InternetReadFile从Internet读取文本文件。
为了您的方便,我也粘贴下面的代码:
要从Internet上读取数据,请使用InternetReadFile函数。 我使用下面的代码从Internet读取一个小的(单行)文本文件:
function WebGetData(const UserAgent: string; const server: string; const Resource: string): string; var hInet: HINTERNET; hURL: HINTERNET; Buffer: array[0..1023] of AnsiChar; i,BufferLen: cardinal; begin result := ''; hInet := Internetopen(PChar(UserAgent),INTERNET_OPEN_TYPE_PRECONfig,nil,0); try hURL := InternetopenUrl(hInet,PChar('http://' + server + Resource),0); try repeat InternetReadFile(hURL,@Buffer,SizeOf(Buffer),BufferLen); if BufferLen = SizeOf(Buffer) then result := result + AnsiString(Buffer) else if BufferLen > 0 then for i := 0 to BufferLen - 1 do result := result + Buffer[i]; until BufferLen = 0; finally InternetCloseHandle(hURL); end; finally InternetCloseHandle(hInet); end; end;
示例用法:
WebGetData('My UserAgent','www.rejbrand.se','/MyDir/update/ver.txt')
而不是copyMemory,尝试使用移动例程,如下所示:
Move(indexdata[1],text[1],reserved);
(是的,没有@符号。)这应该解决问题#2。 至于问题1,那是你和服务器之间的问题。 你需要有一些方法来知道它将返回的大小的上限,并使你的缓冲区至少大。 你应该能够在文档中找到它,或者先调用另一个API来获得传入数据的大小。
也放一些检查,如果它返回的东西比你的缓冲区,它立即引发异常。 如果你的缓冲区溢出,你应该假设你的程序正在受到攻击,并作出相应的反应。
Windows函数返回一个未知大小的缓冲区,如果传递的是一个太小的缓冲区,通常会返回缓冲区的require大小。 这样你就不需要事先确定一个足够容纳最大数据的缓冲区大小 – 通过一个小缓冲区(甚至是一个零长度),该函数将返回缓冲区的大小。 然后你可以调整你的缓冲区的大小,并再次传递函数来读取数据 – 例如在MSDN中检查HttpQueryInfo()的解释。 要在Delphi中处理未知大小的缓冲区,有两种方法。
使用动态数组和SetLength()
使用GetMem()和FreeMem()动态分配缓冲区,非常类似于C
例如:
var Buf: Pointer; BufSize: DWORD; Rez: DWORD; ... const InitialBufSize = 1024; ... BufSize := InitialBufSize; GetMem(Buf,BufSize); try if not HttpQueryInfo(hRequest,dwInfoLevel,Buf,BufSize,lpdwIndex) then begin Rez := GetLastError; if Rez = ERROR_INSUFFICIENT_BUFFER then begin FreeMem(Buf,InitialBufSize); GetMem((Buf,BufSize); if not HttpQueryInfo(hRequest,lpdwIndex) then Rez := GetLastError end; ... finally FreeMem(Buf,BufSize); end;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。