Запись/чтение строки бинарного файла

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Запись/чтение строки бинарного файла

Сообщение viter.alex » 04.04.2011 (Пн) 0:33

Приношу извинения за „многа букав“
Есть двоичный файл. Его нужно открыть, прочитать четыре байта по заданному смещению и заменить их на другие четыре байта, указанные пользователем. Эти четыре байта представляют собой строку. Для этого я написал такой класс:
Код: Выделить всё
Private Class FourCc
        Private m_Offset As Integer
        Private m_Len As Integer

        Friend Property Offset() As Integer
            Get
                Return m_Offset
            End Get
            Set(ByVal value As Integer)
                m_Offset = value
            End Set
        End Property

        Friend Property Lenght() As Integer
            Get
                Return m_Len
            End Get
            Set(ByVal value As Integer)
                m_Len = value
            End Set
        End Property

        ''' <summary>
        ''' Функция читает значение FourCC из заданного файла
        ''' </summary>
        ''' <param name="FileName">Имя файла</param>
        ''' <returns>Строку, содержащую описание кодека</returns>
        ''' <remarks></remarks>
        Friend Function ReadFourCC(ByVal FileName As String) As String
            Dim retval As String = ""
            Dim binReader As BinaryReader = Nothing
            Try
                binReader = New BinaryReader(File.OpenRead(FileName))
                binReader.BaseStream.Seek(m_Offset, SeekOrigin.Begin)
                retval = CStr(binReader.ReadChars(m_Len))
            Catch ex As ArgumentNullException
                Throw New Exception("Путь к файлу не указан.")
            Catch ex As ArgumentException
                Throw New Exception("Неверный путь.")
            Catch ex As PathTooLongException
                Throw New Exception("Слишком длинный путь к файлу.")
            Catch ex As DirectoryNotFoundException
                Throw New Exception("Каталог не найден.")
            Catch ex As UnauthorizedAccessException
                Throw New Exception("Ошибка прав доступа.")
            Catch ex As FileNotFoundException
                Throw New Exception("Файл не найден.")
            Catch ex As IOException
                Throw New Exception("Ошибка чтения.")
            Catch ex As Exception
                Throw New Exception("Ошибка чтения описания кодека")
            Finally
                binReader.Close()
            End Try
            Return retval
        End Function

        ''' <summary>
        ''' Записывает в файл новое значение FourCC
        ''' </summary>
        ''' <param name="FileName">Путь к файлу</param>
        ''' <param name="NewFourCC">Новое значение</param>
        ''' <remarks></remarks>
        Friend Sub ReplaceFourCc(ByVal FileName As String, ByVal NewFourCC As String)
            Dim binWriter As BinaryWriter = Nothing
            Try
                binWriter = New BinaryWriter(File.OpenWrite(FileName))
                binWriter.BaseStream.Seek(m_Offset, SeekOrigin.Begin)
                binWriter.Write(NewFourCC.ToCharArray, 0, m_Len)
            Catch ex As ArgumentException
                Throw New Exception("Неверный путь.")
            Catch ex As PathTooLongException
                Throw New Exception("Слишком длинный путь к файлу.")
            Catch ex As DirectoryNotFoundException
                Throw New Exception("Каталог не найден.")
            Catch ex As UnauthorizedAccessException
                Throw New Exception("Ошибка прав доступа.")
            Catch ex As FileNotFoundException
                Throw New Exception("Файл не найден.")
            Catch ex As NotSupportedException
                Throw New Exception("Неверный формат пути.")
            Catch ex As Exception
                Throw New Exception("Неизвестная ошибка. " & ex.Message)
            Finally
                binWriter.Close()
            End Try
        End Sub
    End Class

Всё довольно просто. Но! Этот вариант я нашёл после двух часов попыток писать строку или читать строку. Сейчас, как видно, я пишу и читаю массив символов.
А произошло это потому, что при попытке прочитать строку, первый символ обрезался. Я даже уменьшал смещение на 1, чтобы прочитать всё. А при попытке записать строку перед ней писался ещё и пробел. Т.е. я пытаюсь записать 4 байта, а пишется пять и первый из них пустой.
Вот и вопрос: почему так?
Желающим попробовать нужно заменить
Код: Выделить всё
retval = CStr(binReader.ReadChars(m_Len))

на
Код: Выделить всё
retval = binReader.ReadString.SubString(0, m_Len)

в процедуре чтения и
Код: Выделить всё
binWriter.Write(NewFourCC.ToCharArray, 0, m_Len)

на
Код: Выделить всё
binWriter.Write(NewFourCC)

для процедуры записи и результатами полюбоваться в любом hex-редакторе
Лучше день потерять — потом за пять минут долететь!

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Запись/чтение строки бинарного файла

Сообщение FireFenix » 04.04.2011 (Пн) 11:37

viter.alex писал(а):Вот и вопрос: почему так?

Пользуйся отладкой... проходи по шагам и смотри чё да как

Вообще лучше бы ты использовал обычный FileStream, и для работой со строками System.Text.Encoding
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

viter.alex
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 221
Зарегистрирован: 27.07.2008 (Вс) 20:17
Откуда: Montreal

Re: Запись/чтение строки бинарного файла

Сообщение viter.alex » 05.04.2011 (Вт) 23:30

FireFenix писал(а):Пользуйся отладкой... проходи по шагам и смотри чё да как

Вообще лучше бы ты использовал обычный FileStream, и для работой со строками System.Text.Encoding

Пользовался отладкой (как же без неё?). Строка подаётся правильная.
Чем лучше обычный FileStream? И почему он обычный? Это мой первый опыт чтения\записи в двоичный поток, так что могу спрашивать глупости
Зачем System.Text.Encoding? Строка может содержать только латиницу и цифры
Лучше день потерять — потом за пять минут долететь!


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 19

    TopList