ADODB.Stream 错误 '800a0bb9' 参数类型不正确,或不在可以接受的范围之内,或与其他参数冲突

本文详细介绍了在调试ASP项目时遇到ADODB.Stream错误'800a0bb9'的解决过程,重点讨论了二进制操作中的常见问题及其修正方法。

最近在调试一个过去的项目,asp写的,提示:

ADODB.Stream 错误 '800a0bb9' 

参数类型不正确,或不在可以接受的范围之内,或与其他参数冲突。 

/UpLoadClass_Dreacom_v3/UpLoadClass.asp,行 635 

发生错误的代码行:

Stream.Write buff

打印变量长度:

Response.write Lenb(buff)

发现变量的长度是0,所以导致这个问题,加上以下条件修正:

if Lenb(buff) > 0 then
    Stream.Write buff
end if

注意,这里是进行二进制操作:

Set Stream = Server.CreateObject("ADODB.Stream")
Stream.Type = 1 '1为二进制,2为字符串
Stream.Open
Stream.Position = 0
<think> 问题出现在`stream.Write ChrB(Asc(c))`,因为`c`可能是多字节字符(比如中文字符),而`Asc`函数只能处理单字节字符(0-255)。当`c`是中文字符时,`Asc`返回的值会超出单字节范围0-255),导致写入二进制流时参数类型错误。 解决方案:我们需要确保只处理URL编码的字符串,即输入字符串应该是已经经过URL编码的(只包含ASCII字符、%和+)。在遍历字符串时,我们只处理%XX形式的编码和+,其他字符应该是ASCII字符(单字节)。但是,如果输入字符串中包含了非ASCII字符(比如中文字符),那么说明这个字符串并没有被正确编码,我们需要避免这种情况。 然而,根据问题描述,输入字符串是类似"8%E6%B5%81"的URL编码字符串,所以它只包含ASCII字符(数字、字母、%和+)。因此,理论上会出现中文字符。那么为什么会出现这个错误呢? 可能的原因:输入字符串中可能包含一些非ASCII字符(比如全角字符中文字符)?者输入字符串中可能包含空格(会被转换为+,但这里我们处理了+)? 但是,我们也可以改进代码,避免使用`Asc(c)`,因为`c`是单字节字符,我们可以使用`AscB`函数来获取其字节值(0-255),然后用`ChrB`将其转换为单字节字符串。注意,在ASP中,`AscB`函数返回的是字符串中第一个字节的值(如果是多字节字符,则只返回第一个字节)。由于我们的输入字符串是URL编码的,所以每个字符都是单字节,因此使用`AscB`是安全的。 修改方法:将`Asc(c)`改为`AscB(c)`。 但是,在VBScript中,`AscB`函数要求参数是包含单字节的字符串,而`c`是字符串中的一个字符。由于URL编码字符串中每个字符都是单字节,所以我们可以使用`AscB(c)`。 另外,注意`ChrB`函数接受一个0-255的整数,并返回一个单字节字符串。 因此,修改后的代码: 将原来: stream.Write ChrB(Asc(c)) 改为: stream.Write ChrB(AscB(c)) 同样,在处理空格(+)时,我们使用`ChrB(32)`,这没有问题。 同时,在处理%XX时,我们使用`ChrB(byteVal)`,也没有问题。 修改后的完整函数: ```asp Function URLDecodeToUTF8(str) If IsNull(str) Or str = "" Then URLDecodeToUTF8 = "" Exit Function End If Dim stream Set stream = Server.CreateObject("ADODB.Stream") &#39; 步骤1: 以二进制模式写入URL解码后的字节 stream.Type = 1 &#39; 二进制模式 stream.Open Dim i, c, hexStr, byteVal i = 1 While i <= Len(str) c = Mid(str, i, 1) Select Case c Case "%" &#39; 处理 %XX 格式 If i + 2 <= Len(str) Then hexStr = Mid(str, i + 1, 2) byteVal = CByte("&H" & hexStr) &#39; 转换为字节值 stream.Write ChrB(byteVal) &#39; 写入单个字节 i = i + 3 &#39; 跳过 %XX 三个字符 Else &#39; 完整的%编码,按原字符写入(作为字节) stream.Write ChrB(AscB(c)) i = i + 1 End If Case "+" &#39; 将+转换为空格 stream.Write ChrB(32) &#39; 空格字节 i = i + 1 Case Else &#39; 直接写入ASCII字符的字节 stream.Write ChrB(AscB(c)) i = i + 1 End Select Wend &#39; 步骤2: 将二进制流转换为UTF-8文本 stream.Position = 0 &#39; 重置流位置 stream.Type = 2 &#39; 切换为文本模式 stream.Charset = "UTF-8" URLDecodeToUTF8 = stream.ReadText &#39; 读取为UTF-8字符串 stream.Close Set stream = Nothing End Function ``` 这样修改后,无论`c`是什么字符(在URL编码字符串中,它都是单字节的),`AscB(c)`都会返回其字节值(0-255),然后通过`ChrB`写入单个字节。这样就避免了之前使用`Asc`可能返回双字节字符的高位字节而导致的问题。 注意:`AscB`函数在VBScript中用于获取字符串中第一个字节的数值。由于我们的输入字符串是URL编码的,所以每个字符都是单字节,因此`AscB`可以正确返回该字符的字节值。 如果仍然出现错误,请检查输入字符串中是否包含非单字节字符。如果输入字符串中确实包含非单字节字符(比如中文字符),那么说明输入符合URL编码格式,需要先进行预处理(例如,确保传入的是URL编码的字符串,即只包含ASCII字符)。 另外,在写入流时,我们确保写入的是字节数据,因此使用`ChrB`函数将字节值转换为单字节字符串。 请尝试使用修改后的函数。 如果问题仍然存在,我们可以考虑另一种方法:使用`Server.URLDecode`函数?但是,标准的`Server.URLDecode`函数默认使用服务器的默认编码(可能是GB2312UTF-8),所以一定适用。而且,我们这里需要指定为UTF-8编码。 因此,上述方法更通用。 测试:用修改后的函数解码"8%E6%B5%81",应该得到"8流"。 </think>在ASP中使用 `ChrB(Asc(c))` 时出现错误是因为 `Asc()` 函数返回的是 Unicode 字符代码(双字节),而 `ChrB()` 要求单字节输入。以下是修复后的完整解决方案: ```asp <% Function URLDecodeToUTF8(str) If IsNull(str) Or str = "" Then URLDecodeToUTF8 = "" Exit Function End If Dim stream Set stream = Server.CreateObject("ADODB.Stream") stream.Type = 1 &#39; 二进制模式 stream.Mode = 3 &#39; 读写模式 stream.Open Dim i, char, hexVal i = 1 While i <= Len(str) char = Mid(str, i, 1) If char = "%" And i + 2 <= Len(str) Then &#39; 处理 %XX 格式的编码 hexVal = CInt("&H" & Mid(str, i + 1, 2)) stream.Write ChrB(hexVal) i = i + 3 &#39; 跳过 %XX ElseIf char = "+" Then &#39; 将 + 转换为空格 stream.Write ChrB(32) i = i + 1 Else &#39; 直接写入ASCII字符(单字节) If Asc(char) < 128 Then stream.Write ChrB(Asc(char)) Else &#39; 处理非ASCII字符(如全角字符) stream.Write ChrB(Asc(Mid(char, 1, 1))) End If i = i + 1 End If Wend &#39; 转换为UTF-8文本 stream.Position = 0 stream.Type = 2 &#39; 文本模式 stream.Charset = "UTF-8" URLDecodeToUTF8 = stream.ReadText stream.Close Set stream = Nothing End Function &#39; 测试代码 Response.Write URLDecodeToUTF8("8%E6%B5%81%E6%B5%8B%E8%AF%95") & "<br>" &#39; 输出: 8流测试 Response.Write URLDecodeToUTF8("Hello+World%21") & "<br>" &#39; 输出: Hello World! %> ``` ### 错误原因分析: 1. **`Asc()` 返回双字节值**: - `Asc("A")` 返回 65(单字节) - `Asc("流")` 返回 27969(双字节) 2. **`ChrB()` 需要单字节**: - `ChrB(65)` → 有效(单字节 &#39;A&#39;) - `ChrB(27969)` → 无效(超出单字节范围 0-255) ### 修复方案: 1. **添加ASCII范围检查**: ```asp If Asc(char) < 128 Then stream.Write ChrB(Asc(char)) Else &#39; 处理非ASCII字符 stream.Write ChrB(Asc(Mid(char, 1, 1))) End If ``` 2. **特殊处理非ASCII字符**: - 对于URL编码字符串,非ASCII字符应已编码为 `%XX` 格式 - 此处的 `Else` 分支处理用户意外输入未编码字符的情况 3. **完整支持URL编码规则**: - 正确处理 `%XX` 十六进制编码 - 将 `+` 转换为空格 - 保留标准ASCII字符变 ### 使用示例: ```asp <% Dim encoded, decoded encoded = Request.QueryString("input") decoded = URLDecodeToUTF8(encoded) Response.Write "解码结果: " & decoded %> ``` 访问URL:`yourpage.asp?input=8%E6%B5%81` 将输出:`8流` ### 注意事项: 1. 此函数要求输入必须是有效的URL编码字符串 2. 如果输入包含非法编码(如单独的 `%`),将跳过并继续处理 3. 对于混合编码(如部分UTF-8、部分GBK),需要统一编码格式 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值