i'm trying to create a RLE compression & decompression tool, problem is that i don't know how to count each consecutive items in an array, that share the same value.
suppose a file with this byte string:
00 00 00 FF 99 88 88 77 22 00 00 00 00 00 00 00 00 00 00
how'd i receive something like 3 00 1 FF 1 99 2 88 1 77 1 22 10 00
?
and how would i split the count like 255 0 5 0
instead of 260 0
?
here is my compressRLE() function right now:
Public Sub compressRLE(org As String, cmp As String)
Dim inputFile = IO.File.Open(org, IO.FileMode.Open)
Dim bytes = New Byte(2147483647 - 1) {}
Dim bytearray = bytes.ToArray()
Dim nbytes As Array = {}
While inputFile.Read(bytes, 0, 2147483647) > 0
My.Computer.FileSystem.WriteAllBytes(2147483647, bytes, True)
End While
For i = 0 To bytearray.Length
If bytearray(i) = bytearray(i 1) Then
End If
Next i
inputFile.Close()
End Sub
CodePudding user response:
You will need to do several things:
- Split the byte array string
- Loop over the items returned from the split
- Keep track of the current "consecutive" item
- If the currently looped item matches the current consecutive item, then increase it's total
- Otherwise, start a new total and set the new current consecutive item
Here is an example:
Private Function ConsecutiveItemCount(delimitter As String, input As String) As IEnumerable(Of KeyValuePair(Of String, Integer))
If (String.IsNullOrEmpty(delimitter)) Then
Throw New ArgumentNullException(NameOf(delimitter))
End If
If (String.IsNullOrWhiteSpace(input)) Then
Throw New ArgumentNullException(NameOf(input))
End If
Dim everyItem = input.Split({ delimitter }, StringSplitOptions.RemoveEmptyEntries)
Dim consecutiveItems = New List(Of KeyValuePair(Of String, Integer))()
For index As Integer = 0 To everyItem.Length - 1
Dim currentlyIteratedItem = everyItem(index)
If (consecutiveItems.Count = 0) Then
consecutiveItems.Add(New KeyValuePair(Of String, Integer)(currentlyIteratedItem, 1))
Continue For
End If
Dim currentlyIncrementingItem = consecutiveItems.Last()
If (currentlyIncrementingItem.Key() = currentlyIteratedItem) Then
Dim newConsecutiveTotal = currentlyIncrementingItem.Value 1
consecutiveItems.Item(consecutiveItems.Count - 1) = New KeyValuePair(Of String, Integer)(currentlyIteratedItem, newConsecutiveTotal)
Else
consecutiveItems.Add(New KeyValuePair(Of String, Integer)(currentlyIteratedItem, 1))
End If
Next
Return consecutiveItems
End Function
Live Demo: https://dotnetfiddle.net/BCSe3N
CodePudding user response:
Something like this,
Public Function DoCountsEx(byts() As Byte) As List(Of Counts)
Dim cts As New List(Of Counts)
If byts.Length > 0 Then
Dim aCT As New Counts(byts(0), 0)
Dim idx As Integer = 1
Do While idx < byts.Length
If byts(idx) = aCT.bytVal Then
aCT.count = 1
Else
cts.Add(aCT)
aCT = New Counts(byts(idx), idx)
End If
idx = 1
Loop
cts.Add(aCT)
End If
Return cts
End Function
Public Class Counts
Public bytVal As Byte
Public count As Integer
Public bytLoc As Integer 'location start in buffer
Public Sub New(val As Byte, loc As Integer)
Me.bytVal = val
Me.bytLoc = loc
Me.count = 1
End Sub
End Class
Test
' byts() = 00 00 00 FF 99 88 88 77 22 00 00 00 00 00 00 00 00 00 00
Dim cts As List(Of Counts) = DoCountsEx(byts)
'check
Debug.WriteLine("")
For Each c As Counts In cts
Dim hex As String = Convert.ToString(c.bytVal, 16).PadLeft(2, "0"c)
Debug.WriteLine("Value:{0} Count:{1} Location:{2}", hex, c.count, c.bytLoc)
Next
Debug Output
Value:00 Count:3 Location:0
Value:ff Count:1 Location:3
Value:99 Count:1 Location:4
Value:88 Count:2 Location:5
Value:77 Count:1 Location:7
Value:22 Count:1 Location:8
Value:00 Count:10 Location:9