ファイルの読み/書き

Binary-RW.ps1

ファイルの読み/書き

Binary-RW.ps1

# 戻り値
#     書き込み時は戻り値なし
#     読み込み時は読み込んだデータを格納するバイト配列
# -target
#     書き込み/読み込み対象のファイル・パス
#     書き込み時では、ファイルが存在しない場合は作成する
# -offset
#     書き込み/読み込み位置。0 以上
# -size
#     読み込み用。読み込みサイズ。1 以上
# -data
#     省略すると読み込み
#     指定すると書き込み
#     指定できるのはバイト配列、または 16 進数で構成する文字列
Param( [string] $target, [int] $offset, [int] $size, $data )


    trap
    {
        break
    }


# エラー・メッセージ出力
Function ErrorMsg( [string] $s )
{
    Write-Host $s
}

# メッセージ出力
Function OutputMsg( $s )
{
    $s | Write-Host
}

# ファイル・オープン。
#     読み込み時は、ファイルが存在していなければならない
#     書き込み時は、存在しなければ作成する
# -path
#     ファイル・パス
# -write
#     指定すると書き込み、省略すると読み込み
Function Open-File( $path, [Switch] $write )
{
    try
    {
        $pathCurrent = [System.IO.Directory]::GetCurrentDirectory()

        [System.IO.Directory]::SetCurrentDirectory( (Get-Location) );

        if( $write.IsPresent )
        {
            $FileMode = [System.IO.FileMode]::OpenOrCreate
            $FileAccess = [System.IO.FileAccess]::Write
        }
        else
        {
            $FileMode = [System.IO.FileMode]::Open
            $FileAccess = [System.IO.FileAccess]::Read
        }

        $fSrc = [System.IO.File]::Open( $path, $FileMode, $FileAccess )

        if( $write.IsPresent )
        {
            [System.IO.BinaryWriter]::new( $fSrc )
        }
        else
        {
            [System.IO.BinaryReader]::new( $fSrc )
        }
    }
    catch [System.Exception]
    {
        if( $fSrc -ne $Null )
        {
            $fSrc.Dispose()
        }

        $Null
    }
    finally
    {
        [System.IO.Directory]::SetCurrentDirectory( $pathCurrent )
    }
}

# フィルター。
# バイト配列を 16 進数の文字列に変換する
Function BytesToHEX
{
    Begin
    {
        $bufferTxt = ''
    }

    Process
    {
        $bufferTxt += $_.ToString( 'X2' )
    }

    End
    {
        $bufferTxt
    }
}

# フィルター。
# バイト配列を 16 進数の文字列に変換する
# -s
#     16 進数を表す文字列
Function CheckHEX( [string] $s )
{
    if( $s -match "^([0-9A-Fa-f]{2})+$" )
    {
        $True
    }
    else
    {
        $False
    }
}

# 文字列(16 進数を表す)をバイト配列にする
# -s
#     16 進数を表す文字列
Function HEXToBytes( [string] $s )
{
    $buffer = New-Object "byte[]" ($s.Length -shl 1)

    $y = 0

    for( $x = 0; $x -lt $s.Length; $x += 2 )
    {
        $buffer[ $y ] = [byte]::Parse( $s.Substring($x, 2), [System.Globalization.NumberStyles]::HexNumber )

        $y ++
    }

    $buffer
}


# $data が有効なものか確認する
# バイト配列、16 進数を表す文字列の場合、有効となる
#
# 戻り値
#     $Null の場合は $data が不正
#     バイト配列の場合は正。$data をバイト配列に変換したもの
# -data
#     任意の値
Function CheckData( $data )
{
    if( $data.GetType() -eq [byte[]] )
    {
        return $data
    }

    if( $data.GetType() -eq [string] )
    {
        $r = CheckHEX $data

        if( $r -eq $False )
        {
            return $Null
        }

        return HEXToBytes $data
    }

    $Null
}


    # ターゲット・ファイルの存在を確認する

    if( $target.Length -eq 0 )
    {
        OutputMsg "書式", "Binary-RW [-target] ファイル [-offset] <オフセット> [-size <サイズ>] [-data <value>]"

        return
    }


    if( $size -lt 0 )
    {
        ErrorMsg "-size の指定は不正です"
        return
    }

    if( $offset -lt 0 )
    {
        ErrorMsg "-offset の指定は不正です"
        return
    }


    # コマンドレットへの引数を確認する

    if( $data -eq $Null )
    {
        # 読み込み時

        # 処理なし
    }
    else
    {
        # 書き込み時

        $bufferHex = CheckData $data

        if( $bufferHex -eq $Null )
        {
            ErrorMsg "-data の指定が不正です"
            return
        }
    }


    # メイン

    if( $data -eq $Null )
    {
        # 読み込み時

        [System.IO.BinaryReader] $fr = Open-File $target
        if( $fr -eq $Null )
        {
            ErrorMsg "読み込みオープンできません"
            return
        }

        if( $fr.BaseStream.Length -lt ($offset + $size) )
        {
            $fr.Dispose()

            ErrorMsg "-offset / -size の指定が不正です"
            return
        }

        [byte[]] $bufferHex = New-Object "byte[]" $size

        $fr.BaseStream.Position = $offset

        [void] $fr.Read( [byte[]] $bufferHex, 0, $bufferHex.Length )

        $fr.Dispose()

        $bufferHex
    }
    else
    {
        # 書き込み時

        [System.IO.BinaryWriter] $fw = Open-File $target -write
        if( $fw -eq $Null )
        {
            ErrorMsg "書き込みオープンできません"
            return
        }

        $fw.BaseStream.Position = $offset

        $fw.Write( [byte[]] $bufferHex, 0, $bufferHex.Length )

        $fw.Dispose()
    }

使用サンプル

# 使用例(書き込み、文字列指定)
Binary-RW State01.bin 32 -data:"ff01020304050607"


# 使用例(読み込み。byte[] でキャストすることが大事!)
[byte[]] $m = Binary-RW State01.bin 16 -size:8


# 使用例(書き込み、バイト配列指定)
Binary-RW State01.bin 48 -data:$m