我正在构建一个将unsigned int32转换为ipv4地址的函数,这一切都很有效,直到我用范围的上半部分进行测试。
<cffunction name="Int32ToIPv4" returntype="string" output="false" access="public" hint="returns IPv4 address for int32 number">
<cfargument name="nInt32" type="numeric" required="yes" hint="int32 to convert to ipv4 address">
<cfreturn
bitAnd((arguments.nInt32 / 16777216), 255) & "."
& bitAnd((arguments.nInt32 / 65536), 255) & "."
& bitAnd((arguments.nInt32 / 256), 255) & "."
& bitAnd(arguments.nInt32, 255)
>
</cffunction>
ColdFusion似乎将type =“numeric”解释为签名 32位整数。
此示例有效:
Int32ToIPv4(nInt32 = 1181772947) = #Int32ToIPv4(nInt32 = 1181772947)# (expected value = 70.112.108.147)<br>
此示例失败:
Int32ToIPv4(nInt32 = 3401190660) = #Int32ToIPv4(nInt32 = 3401190660)# (expected value = 202.186.13.4)<br>
错误消息是:“无法将值3.40119066E9转换为整数,因为它无法放入整数内。”
在使用它之前,我是否必须将此数字作为字符串传递并将其转换为Java unsigned int?
我想在某些时候用ipv6地址(无符号128位整数)做类似的事情。任何有关此类数据类型的建议都将受到赞赏。
答案 0 :(得分:3)
实际上bitAnd()强加了32位整数限制,而不是cfargument。
有趣的是,如果你单独检查每个计算,前三个(3)工作正常。由于划分,传递到bitAnd()
的值实际上足够小以适合INT。但是,最后一个使用显然太大的原始值,这就是导致该特定数字的错误的原因。
bitAnd( (3401190660 / 16777216), 255 ) // Actual => 202.7267611032, 255
bitAnd( (3401190660 / 65536), 255 ) // Actual => 51898.05084233, 255
bitAnd( (3401190660 / 256), 255 ) // Actual =>13285901.0156, 255
bitAnd(3401190660, 255) // Too big!
由于CF中的大多数相关数学函数都限制为32位整数,因此我不确定是否可以(或简单地)单独使用CF来完成。假设您使用的是Java 8+,您还可以访问新的无符号方法,如Integer.parseUnsignedInt(String)。
我个人认为这将是一次很棒的学习练习。但是,除非您非常熟悉已签名与未签名的详细信息以及它与IP4和IP6地址的关系,否则您可能只想使用现有的Java库来避免常见的陷阱。例如Guava's InetAdress:
// IP4
input = 3401190660;
uint = createObject("java", "java.lang.Integer").parseUnsignedInt(input);
inet = createObject("Java", "com.google.common.net.InetAddresses");
result = inet.fromInteger(uint).getHostAddress();
答案 1 :(得分:2)
我确实想出了一个原生Java解决方案,它涉及传入一个无符号的32位int。因此,@ Leigh对于cfargument正常工作是正确的。
<cffunction name="UInt32ToIPv4" returntype="string" output="no" access="public" hint="returns IPv4 address for uint32 number">
<cfargument name="nUInt32" type="numeric" required="yes" hint="uint32 to convert to ipv4 address">
<cfset local['JavaLangInteger'] = CreateObject("java", "java.lang.Integer")>
<cfset local['JavaMathBigInteger'] = CreateObject("java", "java.math.BigInteger")>
<cfset local['JavaNetInetAddress'] = CreateObject("java", "java.net.InetAddress")>
<cfif arguments.nUInt32 EQ 0>
<cfreturn "">
</cfif>
<cftry>
<cfset local['vcIPv4'] = local.JavaNetInetAddress.getByAddress(local.JavaMathBigInteger.valueOf(local.JavaLangInteger.parseUnsignedInt(arguments.nUInt32)).toByteArray())>
<cfreturn reReplace(local.vcIPv4, "[^0-9\.]", "", "all")>
<cfcatch type="any">
<cfreturn "">
</cfcatch>
</cftry>
</cffunction>
让我知道这个解决方案是否存在任何问题,因为我认为我将使用它而不是公共java库。
我已经编写了ipv6函数来处理转换(无符号128位int到/从ipv6)。不确定是否对这些功能感兴趣。如果有,我会用该代码创建单独的问题/答案。