Solved

Binary Replace in VB.NET

Posted on 2007-03-22
9
1,341 Views
Last Modified: 2012-08-13
OK I searched and have yet to find a suitable solution. Most of what I've found used a BinaryReader and was WAY too slow.

I'm trying to do a simple byte replace on a large binary file and not getting the speed I want.

In VB, I was able to use the following, so I'm wondering if it can be modified for .NET:

Open File For Binary As #ff
    FileString = String$(LOF(ff), Chr$(0))
    Get #ff, 1, FileString
    If FileString = "" Then Exit Function
    ReDim FileStringArray(1 To Len(FileString)) As Byte
    Call CopyMemory(FileStringArray(1), ByVal FileString, Len(FileString))
    For temp = 1 To Len(FileString)
        If FileStringArray(temp) = Asc(Chr(174)) Then 'replace through numeric Value
            FileStringArray(temp) = 13
        End If
        Next temp
    Call CopyMemory(ByVal FileString, FileStringArray(1), Len(FileString))
    ff1 = FreeFile
    Open tempfn$ For Binary As #ff1
    Put #ff1, 1, FileString
Close #ff

Any ideas?

Thanks.

Carp

0
Comment
Question by:carpbyte
  • 4
  • 4
9 Comments
 
LVL 11

Expert Comment

by:Babycorn-Starfish
ID: 18775996
Hi,

what type of solutions have you come across using the BinaryReader/Writers? just so i don't offer something you've already rejected.

Cheers

JW
0
 
LVL 34

Expert Comment

by:Sancler
ID: 18776175
Try this

    Private Sub doReplace()
        Dim sr As New StreamReader("<yourInputFile>")
        Dim sInput As String = sr.ReadToEnd
        sr.Close()
        Dim sOutput As String = sInput.Replace(Chr(174), Chr(13))
        Dim sw As New StreamWriter("<yourOutputFile>")
        sw.Write(sOutput)
        sw.Flush()
        sw.Close()
    End Sub

You'll need

Imports System.IO

at the top of the file.

It's based on the thought that a binary file and a text file are essentially the same internally: it's just what reads and displays them that makes the difference.  So it reads the file as a String and uses [String].Replace with character codes.

The assumption "that a binary file and a text file are essentially the same internally" will not always be true for all practical purposes: e.g. Byte Order Markers and/or encoding can interfere with direct equivalence.  And I am not sure that I've got the replacement - 13 for 174 right.  But, if it works OK, I doubt you'll get it much faster.

Roger
0
 

Author Comment

by:carpbyte
ID: 18776208
The string reader doesn't appear to "read" non ascii characters - that's the problem.

For example the binary file I'm using has a Hex FE (254) as the first byte,  but if you read the first byte in the string it isn't that.

???
0
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

 

Author Comment

by:carpbyte
ID: 18776219
Everything I saw that does a loop through an array was very slow...
0
 
LVL 34

Expert Comment

by:Sancler
ID: 18776288
Try this

Imports System.io
Public Class Form1

    Private Sub writefile()
        Dim sw As New StreamWriter("C:\Test\testfile.bin")
        Dim s As String = 0
        For i As Integer = 0 To 255
            s &= Chr(i)
        Next
        sw.Write(s)
        sw.Flush()
        sw.Close()
    End Sub

    Private Sub readfile()
        Dim sr As New StreamReader("C:\Test\testfile.bin")
        Dim s As String = sr.ReadToEnd
        sr.Close()
        For i As Integer = 0 To s.Length - 1
            Debug.WriteLine(Asc(s.Substring(i, 1)))
        Next
    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        writefile()
        readfile()
    End Sub
End Class

What the streamreader can read and what any display mechanism will actually show are not necessarily the same.  The output for me from the above has an extra 48 at the start, but every other number from 0 to 255 shows OK.

Roger
0
 
LVL 34

Expert Comment

by:Sancler
ID: 18778213
And I see now (in the cold light of morning) that ther reason for the "extra 48 at the start" is because I inadvertantly put

       Dim s As String = 0

instead of

       Dim s As String = ""

Roger
0
 

Author Comment

by:carpbyte
ID: 18781711
Nope.

Here's the problem I'm encountering - the binary file has the following characters I need to replace:

174  change to 13
254  change to 34
20    change to 124

ALL of these bytes exist in the file, however when loaded as a string neither the 174 or 254 are recognized. In fact, it appears they get stripped out completely, case in pont the very first char in the file is hex FE (254) but doing a debug on what SHOULD be the first char is actually returning the second.

I assume that by definition, using a string variable expects ONLY string and control bytes, thus they vanish.

I thnk the soultion involves creating a byte array, but looping through it is infinitely too slow.

???

Bizarre.

Thanks.
0
 
LVL 34

Accepted Solution

by:
Sancler earned 125 total points
ID: 18783745
As I said in my first post, "encoding can interfere with direct equivalence".  But I think we can get over that.  Here's a revised demo.  It creates the testfile with a binary writer.  It then reads it in with a binary reader.  But it then - successfully, at least in this demo - overcomes the encoding problems by a specific conversion from byte to string, does the replacements in the string, and then does a specific conversion back from string to byte.

Imports System.io
Public Class Form1

    Private Sub writefile()

        Dim ba(99) As Byte
        For i As Integer = 0 To 24
            ba(i * 4) = 96
            ba((i * 4) + 1) = 174
            ba((i * 4) + 2) = 20
            ba((i * 4) + 3) = 254
        Next

        Dim fs As New FileStream("C:\Test\testfile.bin", FileMode.Create)
        Dim w As New BinaryWriter(fs)
        w.Write(ba)
        w.Close()
        fs.Close()

    End Sub

    Private Sub readfile()

        Dim ba() As Byte
        Dim fs As New FileStream("C:\Test\testfile.bin", FileMode.Open, FileAccess.Read)
        Dim r As New BinaryReader(fs)
        ba = r.ReadBytes(100)
        r.Close()
        fs.Close()

        'convert byte array to string
        Dim s As String = System.Text.Encoding.Default.GetString(ba)
        'use string replace
        Dim t As String = s.Replace(Chr(254), Chr(34))
        t = t.Replace(Chr(174), Chr(13))
        t = t.Replace(Chr(20), Chr(124))
        'convert string back to byte array
        Dim bb() As Byte = System.Text.Encoding.Default.GetBytes(t)

        'test
        For i As Integer = 0 To s.Length - 1
            Debug.Write("Byte was " & ba(i) & ": ")
            Debug.WriteLine("byte is " & bb(i))
        Next

    End Sub

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        writefile()
        readfile()
    End Sub
End Class

It seems to be working OK for me.

Roger
0
 

Author Comment

by:carpbyte
ID: 18783858
That did the trick.

Thanks.

Carp
0

Featured Post

Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question