(VB.NET)SHIFT‐JISでエンコードされたバイナリデータファイルを作成するコードについて - tsukimisoba/Blog GitHub Wiki

2025/06/20

SHIFT-JISでエンコードされたバイナリデータファイルを作成するコードについて

Imports System.IO
Imports System.Text

Public Class PersonData
    Public Property Name As String
    Public Property Age As Integer
    
    Public Sub New()
        Name = ""
        Age = 0
    End Sub
    
    Public Sub New(name As String, age As Integer)
        Me.Name = name
        Me.Age = age
    End Sub
End Class

Public Class BinaryFileHandler
    Private Const NAME_SIZE As Integer = 10
    Private Const AGE_SIZE As Integer = 4
    Private Const RECORD_SIZE As Integer = NAME_SIZE + AGE_SIZE
    
    Private Shared ReadOnly shiftJisEncoding As Encoding = Encoding.GetEncoding("shift_jis")
    
    ''' <summary>
    ''' バイナリファイルにデータを書き込む
    ''' </summary>
    ''' <param name="filePath">ファイルパス</param>
    ''' <param name="persons">書き込むPersonDataのリスト</param>
    Public Shared Sub WriteToFile(filePath As String, persons As List(Of PersonData))
        Using fs As New FileStream(filePath, FileMode.Create, FileAccess.Write)
            Using bw As New BinaryWriter(fs)
                For Each person In persons
                    WritePersonData(bw, person)
                Next
            End Using
        End Using
    End Sub
    
    ''' <summary>
    ''' バイナリファイルからデータを読み込む
    ''' </summary>
    ''' <param name="filePath">ファイルパス</param>
    ''' <returns>読み込んだPersonDataのリスト</returns>
    Public Shared Function ReadFromFile(filePath As String) As List(Of PersonData)
        Dim persons As New List(Of PersonData)()
        
        Using fs As New FileStream(filePath, FileMode.Open, FileAccess.Read)
            Using br As New BinaryReader(fs)
                While fs.Position < fs.Length
                    Dim person As PersonData = ReadPersonData(br)
                    persons.Add(person)
                End While
            End Using
        End Using
        
        Return persons
    End Function
    
    ''' <summary>
    ''' 1レコード分のPersonDataを書き込む
    ''' </summary>
    ''' <param name="writer">BinaryWriter</param>
    ''' <param name="person">書き込むPersonData</param>
    Private Shared Sub WritePersonData(writer As BinaryWriter, person As PersonData)
        ' 氏名(10バイト固定)
        Dim nameBytes As Byte() = GetFixedLengthBytes(person.Name, NAME_SIZE)
        writer.Write(nameBytes)
        
        ' 年齢(4バイト Integer)
        writer.Write(person.Age)
    End Sub
    
    ''' <summary>
    ''' 1レコード分のPersonDataを読み込む
    ''' </summary>
    ''' <param name="reader">BinaryReader</param>
    ''' <returns>読み込んだPersonData</returns>
    Private Shared Function ReadPersonData(reader As BinaryReader) As PersonData
        ' 氏名(10バイト)を読み込み
        Dim nameBytes As Byte() = reader.ReadBytes(NAME_SIZE)
        Dim name As String = GetStringFromBytes(nameBytes)
        
        ' 年齢(4バイト)を読み込み
        Dim age As Integer = reader.ReadInt32()
        
        Return New PersonData(name, age)
    End Function
    
    ''' <summary>
    ''' 文字列を指定バイト数のSHIFT-JISバイト配列に変換(固定長)
    ''' </summary>
    ''' <param name="text">変換する文字列</param>
    ''' <param name="fixedLength">固定バイト数</param>
    ''' <returns>固定長のバイト配列</returns>
    Private Shared Function GetFixedLengthBytes(text As String, fixedLength As Integer) As Byte()
        Dim result As Byte() = New Byte(fixedLength - 1) {}
        
        If Not String.IsNullOrEmpty(text) Then
            Dim textBytes As Byte() = shiftJisEncoding.GetBytes(text)
            Dim copyLength As Integer = Math.Min(textBytes.Length, fixedLength)
            Array.Copy(textBytes, result, copyLength)
        End If
        
        ' 残りの部分は0で埋められる(初期化時に0で初期化済み)
        Return result
    End Function
    
    ''' <summary>
    ''' SHIFT-JISバイト配列から文字列に変換
    ''' </summary>
    ''' <param name="bytes">バイト配列</param>
    ''' <returns>変換された文字列</returns>
    Private Shared Function GetStringFromBytes(bytes As Byte()) As String
        ' 末尾の0バイトを除去
        Dim endIndex As Integer = Array.IndexOf(bytes, CByte(0))
        If endIndex = -1 Then
            endIndex = bytes.Length
        End If
        
        If endIndex = 0 Then
            Return String.Empty
        End If
        
        Return shiftJisEncoding.GetString(bytes, 0, endIndex)
    End Function
End Class

' 使用例
Public Class Program
    Public Shared Sub Main()
        ' テストデータ作成
        Dim persons As New List(Of PersonData) From {
            New PersonData("田中太郎", 25),
            New PersonData("佐藤花子", 30),
            New PersonData("山田次郎", 35)
        }
        
        Dim filePath As String = "persons.dat"
        
        Try
            ' ファイルに書き込み
            Console.WriteLine("データをファイルに書き込み中...")
            BinaryFileHandler.WriteToFile(filePath, persons)
            Console.WriteLine("書き込み完了")
            
            ' ファイルから読み込み
            Console.WriteLine("ファイルからデータを読み込み中...")
            Dim readPersons As List(Of PersonData) = BinaryFileHandler.ReadFromFile(filePath)
            Console.WriteLine("読み込み完了")
            
            ' 読み込んだデータを表示
            Console.WriteLine("読み込んだデータ:")
            For Each person In readPersons
                Console.WriteLine($"氏名: {person.Name}, 年齢: {person.Age}")
            Next
            
        Catch ex As Exception
            Console.WriteLine($"エラーが発生しました: {ex.Message}")
        End Try
        
        Console.WriteLine("何かキーを押してください...")
        Console.ReadKey()
    End Sub
End Class
⚠️ **GitHub.com Fallback** ⚠️