微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

dynamic数组和Wininet的Delphi?

我正在使用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] 举报,一经查实,本站将立刻删除。

相关推荐