算法描述:
以”-”将其分成两部分。
在intervals中添加这两部分的二进制表示形式。(与上面CIDR形式的处理情形类似,不再举例。)
单个IP形式的处理:
intervals.Add(New Interval(IpToLong(txt), IpToLong(txt)))
算法描述:在intervals中添加两个一样的单个IP的二进制表示形式。(为了方便下面的Merge函数处理。)
4.4 LongToIP Public Shared Function LongToIP(longIP As Long) As String Dim sb As New StringBuilder sb.Append(longIP >> 24) sb.Append(".") sb.Append((longIP And &HFFFFFF) >> 16) sb.Append(".") sb.Append((longIP And &HFFFF) >> 8) sb.Append(".") sb.Append((longIP And &HFF)) Return sb.ToString End Function
将二进制形式表示的IP转换成点分十进制格式表示的IP
算法描述:
二进制形式表示的IP右移24位。 二进制形式表示的IP与0XFFFFFF做与运算后右移16位。 二进制形式表示的IP与0XFFFF做与运算后右移8位。 二进制形式表示的IP与0XFF做与运算。 将上面4部分及每次计算后连接的.拼接起来即点分十进制表示的IP,返回。
4.5 Merge Public Function Merge(ByVal intervals As List(Of Interval)) As List(Of Interval) Dim res As New List(Of Interval) If intervals.Count = 0 Then Return res intervals = intervals.OrderBy(Function(i) i.st).ToList res.Add(intervals(0)) For i As Long = 1 To intervals.Count - 1 If intervals(i).st <= res(res.Count - 1).ed Then res(res.Count - 1).ed = Math.Max(intervals(i).ed, res(res.Count - 1).ed) Else res.Add(intervals(i)) End If Next Return res End Function
这应该算是核心部分了,将IP区间合并。
算法描述:
将intervals中各个区间按起始IP升序排列。 在res中添加intervals的第一个区间。(res作为最后的处理结果返回) 将intervals中从第二个区间开始的每个区间的起始IP与res中最后一个区间的结束IP作比较,如果小于或者相等,则将intervals中该区间的结束IP与res中最后一个区间的结束IP中的较大值赋给res中最后一个区间的结束IP。 如果大于,则将intervals中的该区间直接添加到res中。
4.6 输出合并结果 For Each item In IPRes If item.st <> item.ed Then appstr.AppendLine(LongToIP(item.st) & "-" & LongToIP(item.ed)) Else appstr.AppendLine(LongToIP(item.st)) End If Next
4.7 总结这一部分就是将合并后的结果输出:如果起始IP与结束IP不同,则以包含分隔符的形式输出;如果相同,则只输出起始IP。
五、IP区间合并工具.vb较exe改进部分
一开始只把exe文件下载下来试了试效果,但是在有192.168.0.0/26时,结果是0.0.0.0。(打码有点丑,见谅。)
用ILSPY反编译后可以看到:
exe版本只能处理/8、/16、/24、/32的CIDR形式的IP地址,这也就是为什么在有192.168.0.0/26时,结果是0.0.0.0了。改进部分如下(可以回看0×04.3):
BitString = BitString.Substring(0, CInt(ip2)).PadRight(32, "1")
运行效果如图:
不足之处在于192.168.0.0,在.exe中是直接拼接的”.1″,所以结果是192.168.0.1。