-
-
Save EnviableOne/23a8f4d00704a42c4f00dde0ce1ff6c5 to your computer and use it in GitHub Desktop.
Binary searcher
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Find-String { | |
<# | |
.SYNOPSIS | |
Find a matching string from an alphabetically sorted file. | |
.DESCRIPTION | |
Find-String is a specialised binary (half interval) searcher designed to find matches in sorted ASCII encoded text files. | |
.NOTES | |
Change log: | |
11/08/2014 - Chris Dent - First release. | |
#> | |
[CmdletBinding()] | |
[OutputType([String])] | |
param ( | |
# The string to find. The string is treated as a regular expression and must match the beginning of the line. | |
[Parameter(Mandatory = $true)] | |
[String]$String, | |
# The name of the file to search. | |
[Parameter(Mandatory = $true)] | |
[ValidateScript( { Test-Path $_ } )] | |
[String]$FileName | |
) | |
$FileName = $pscmdlet.GetUnresolvedProviderPathFromPSPath($FileName) | |
$FileStream = New-Object IO.FileStream($FileName, [IO.FileMode]::Open) | |
$BinaryReader = New-Object IO.BinaryReader($FileStream) | |
$Length = $BinaryReader.BaseStream.Length | |
$Position = $Length / 2 | |
[Int64]$HalfInterval = $Length / 2 | |
$Position = $Length - $HalfInterval | |
while ($Position -gt 1 -and $Position -lt $Length -and $Position -ne $LastPosition) { | |
$LastPosition = $Position | |
$HalfInterval = $HalfInterval / 2 | |
$BinaryReader.BaseStream.Seek($Position, [IO.SeekOrigin]::Begin) | Out-Null | |
# Track back to the start of the line | |
while ($true) { | |
$Character = $BinaryReader.ReadByte() | |
if ($BinaryReader.BaseStream.Position -eq 1) { | |
$BinaryReader.BaseStream.Seek(-1, [IO.SeekOrigin]::Current) | Out-Null | |
break | |
} elseif ($Character -eq [Byte][Char]"`n") { | |
break | |
} else { | |
$BinaryReader.BaseStream.Seek(-2, [IO.SeekOrigin]::Current) | Out-Null | |
} | |
} | |
# Read the line | |
$Characters = @() | |
if ($BinaryReader.BaseStream.Position -lt $BinaryReader.BaseStream.Length) { | |
do { | |
$Characters += [Char][Int]$BinaryReader.ReadByte() | |
} until ($Characters[-1] -eq [Char]"`n" -or $BinaryReader.BaseStream.Position -eq $BinaryReader.BaseStream.Length) | |
$Line = (New-Object String (,[Char[]]$Characters)).Trim() | |
} else { | |
# End of file | |
$FileStream.Close() | |
return $null | |
} | |
if ($Line -match "^$String") { | |
# Close the file stream and return the match immediately | |
$FileStream.Close() | |
return $Line | |
} elseif ($Line -lt $String) { | |
$Position = $Position + $HalfInterval | |
} elseif ($Line -gt $String) { | |
$Position = $Position - $HalfInterval | |
} | |
} | |
# Close the file stream if no matches are found. | |
$FileStream.Close() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Used in passwordTest Script for searching textbased list of hashes