delphi中的动态数组和wininet?
我正在使用 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 中返回可变大小。
所以我尝试将索引数据和信息缓冲区声明为字节数组,然后使用 SetLength 设置其长度,但发生了两件事。
1)我仍然不知道服务器将返回的索引数据的大小,因此我无法正确地将其设置为100000。2
)我无法使用(就像现在一样)CopyMemory传递Low(indexdata)将索引数据复制到一个简单的字符串变量,这样我就可以使用数据。
在Delphi中我该如何处理这个问题?我可以在 C 中做到这一点,但我似乎无法在 Delphi 中正确做到这一点。
感谢代码
!
I'm using WinInet to connect and retrieve information from one of our server. I'm using the following:
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);
The two array of bytes were enough up until now. Things changed. The server can return now information that can be bigger or smaller than 5000; worst yet, in InternetReadFile can return a variable size in the infoBuffer.
So i tried declaring the indexdata and infobuffer as array of byte and then using SetLength to set its length, but 2 things happened.
1) I still don't know the size of indexdata that the server will return so I cannot properly set it to, say, 100000.
2) I cannot use (as it is now) CopyMemory passing Low(indexdata) to copy indexdata to a simple string variable so I can use the data.
How do I handle this in Delphi? I can do it in C but I can't seem to be able to do it properly in Delphi.
Code is appreciated
thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您确实知道,自 Delphi 2009 以来,
char
是 Unicode 字符,但在 Delphi 2009 之前是 ANSI 字符。同样,在 Delphi 2009 中,string< /code> 是
UnicodeString
,而不是AnsiString
。因此,当您编写
SetLength(text, Reserve)
时,您确实将text
中的字符数设置为Reserved
。但字节数将为2*Reserved
。换句话说,在Delphi 2009+中,一个
char
不是一个byte
,而是两个字节。您可以通过将所有
char
替换为AnsiChar
并将所有string
替换为AnsiString
来恢复旧行为。更新
由于您没有发布整个代码,我无法真正说出问题是什么。尽管如此,您可能会发现阅读我在 Delphi 中使用 InternetReadFile 的示例很有趣。请参阅我对这个问题的回答。这是一个完整的示例,说明如何使用 Delphi 和 InternetReadFile 从 Internet 读取文本文件。
为了方便起见,我还将我的代码粘贴在下面:
要从 Internet 读取数据,请使用
InternetReadFile
函数。我使用以下代码从 Internet 读取一个小型(单行)文本文件:示例用法:
You do know that
char
is a Unicode character since Delphi 2009, but an ANSI character prior to Delphi 2009. In the same way, in Delphi 2009 astring
is aUnicodeString
, not anAnsiString
.So, when you write
SetLength(text, Reserved)
you do set the number of characters intext
toReserved
. But the number of bytes will be2*Reserved
.In other words, in Delphi 2009+, one
char
is not onebyte
, but two bytes.You can get back the old behaviour by replacing all
char
withAnsiChar
and allstring
withAnsiString
.Update
Since you did not post your entire code, I cannot really say what the problem is. Nevertheless, you might find it interesting to read my example usage of InternetReadFile in Delphi. See my answer to this question. It is a fully-working example of how to read a text file from the Internet using Delphi and
InternetReadFile
.For your convinience, I paste my code below as well:
To read data from the Internet, use
InternetReadFile
function. I use the following code to read a small (one-line) text file from the Internet:Sample usage:
尝试使用 Move 例程而不是 CopyMemory,如下所示:(
是的,没有 @ 符号。)这应该可以解决问题 #2。至于问题#1,这是你和服务器之间的问题。您需要有某种方法来知道它将返回的大小的上限是多少,并使您的缓冲区至少有那么大。您应该能够在文档中找到它,或者首先调用另一个 API,该 API 将为您提供传入数据的大小。
还要在那里进行一些检查,以便如果它返回的内容大于缓冲区,它会立即引发异常。如果您的缓冲区溢出,您应该假设您的程序受到攻击并做出相应的反应。
Instead of CopyMemory, try using the Move routine, like so:
(Yes, without the @ symbols.) That should solve problem #2. As for problem #1, that's between you and the server. You need to have some way to know what the upper bound is on the size that it will return, and make your buffer at least that large. You should either be able to find this in the documentation, or call another API first that will give you the size of the incoming data.
Also put some check on there so that if it returns something larger than your buffer, it immediately raises an exception. If your buffer is overrun, you should assume that your program is under attack and react accordingly.
返回未知大小的缓冲区的 Windows 函数,如果传递的缓冲区太小,通常会返回所需的缓冲区大小。这样,您不需要提前设置足够大的缓冲区来容纳最大数据 - 传递一个小缓冲区(即使是零长度的缓冲区),该函数将返回缓冲区应该有多大。然后,您可以调整缓冲区大小并再次将其传递给读取数据的函数 - 检查 MSDN 中的 HttpQueryInfo() 解释。
要在 Delphi 中处理未知大小的缓冲区,有两种方法。
例如:
Windows functions that return a buffer of unknown size, usually return the require size of the buffer if a too small buffer is passed. This way you do not need to size in advance a buffer large enough to hold the largest data - pass a small buffer (even a zero length one), and the function will return how large the buffer should be. Then you can size your buffer and pass it again the the function to read data - check for example HttpQueryInfo() explanation in MSDN.
To handle buffer of an unknown size in Delphi, you have two ways.
For example: