Douglas
não registrado
|
|
ENUNCIADA !
|
|
|
Postada em 11/01/2012 11:35 hs
Caros Colegas, já estou a 2 dias tentando fazer uma rotina funcionar baseado no Algortimo de Huffman, criado pelo Frederick conforme no link abaixo, que tem o exemplo.
Funciona perfeitamente caregando um arquivo de texto, no entanto não consigo fazer o mesmo passando uma variavel string diretamente para a função: Public Function EncodeString(Text As String) As String
Por favor peço que alguém me ajude a desvendar este algortimo e porque fuciona lendo os bytes de arquivo de texto, mas não funciona com uma string, mesmo já tento a função pronta para esta finalidade?
O que eu preciso é informar a a string.
Dim strTEXT As String
Me.Text1 = Huffman.EncodeString(strTEXT)
Deveria me retornar na caixa de texto Text1, da mesma forma que gera o arquivo de texto.
http://www.visualbasiccode.net/vb/scripts/ShowCode.asp?txtCodeId=11000&lngWId=-1
|
|
|
|
Treze
|
SÃO VICENTE SP - BRASIL
|
|
ENUNCIADA !
|
|
|
Postada em 11/01/2012 12:04 hs
mas vc não vai conseguir mesmo o algoritimo foi desenvolvido para compactar arquivos, e não uma sequencia de texto, não sei nem porque compactar uma string.
|
|
|
|
Postada em 11/01/2012 12:19 hs
Treze, não creio que seja isto, pois a intenção do Algoritimo é justamente compactar a string e não arquivos. o algoritmo faz uma varredura na string para buscar as probabilidades de repetições, assim a string vai ficando menor. Eu preciso de encurtar o tamanho de uma string e por isso existe N formas como Aritmeticas, RLE, Huffman e etc...
No exemplo acima funciona exatamente assim, você tem uma string de menor comprimento no final. Apenas não consigo adaptar para uma string, mesmo carregando o Array de bytes.
|
|
|
|
Postada em 18/01/2012 12:51 hs
Exato, se você abrir o binário de um arquivo vai encontrar várias strings lá.
Quanto a seu problema, não li a codificação que você postou, mas acredito que ele esteja tentando ler o arquivo como binary, por isso você não consegue utilizar a string.
É diferente passar uma parâmetro binary de um parâmetro string. Acredito que no exemplo que você postou o programador tenha como objetivo utilizar o Huffman em arquivos, enquanto você tem como objetivo utilizar em String's. Nesse caso, será necessário realizar modificações no aplicativo para atender a suas necessidades.
|
|
|
Douglas
não registrado
|
|
ENUNCIADA !
|
|
|
Postada em 19/01/2012 08:19 hs
Obrigado pelo Retorno!
Na verdade o algoritmo não usa binário. Ele guarda em um array de Bytes e depois armazena no CopyMem. Eu até já consegui pegando o valor do byte no CopyMem e montei a string se usar o arquivo. Mas agora quando tento reverter o processo, da o erro de Out of memory. Nâo sei como que ele o cálculo inverso, mas as string parece que entrou um um loop continuo e de 1120 caracteres foi para 50 milhões.
Vou postar aqui o parte do Codigo: Veja que ByteArray já foi armazenado todos os bytes de uma string.
dessa forma: Dim ByteArray() As Byte
'Convert the string to a byte array ByteArray() = StrConv(Text, vbFromUnicode) 'Compress the data ' Call EncodeByte(ByteArray(), UBound(ByteArray) + 1)
'Compress the byte array Call EncodeByte(ByteArray, Len(Text))
Aqui a funnção que vai decodificar as string e o erro aconteçe no ResultLen que fica com valor monstruoso. Fazendo a leitura em um arquivo de texto isso não acontece.
Public Sub DecodeByte(ByteArray() As Byte, ByteLen As Long) 'On Error Resume Next Dim i As Long Dim j As Long Dim Pos As Long Dim Char As Byte Dim CurrPos As Long Dim Count As Integer Dim CheckSum As Byte Dim Result() As Byte Dim BitPos As Integer Dim NodeIndex As Long Dim ByteValue As Byte Dim ResultLen As Long Dim NodesCount As Long Dim lResultLen As Long Dim NewProgress As Integer Dim CurrProgress As Integer Dim BitValue(0 To 7) As Byte Dim Nodes(0 To 511) As HUFFMANTREE Dim CharValue(0 To 255) As ByteArray If (ByteArray(0) <> 72) Or (ByteArray(1) <> 69) Or (ByteArray(3) <> 13) Then 'The source did not contain the identification 'string "HE?" & vbCr where ? is undefined at 'the moment (does not matter) ElseIf (ByteArray(2) = 48) Then 'The text is uncompressed, return the substring 'Decode = Mid$(Text, 5) Call CopyMem(ByteArray(0), ByteArray(4), ByteLen - 4) ReDim Preserve ByteArray(0 To ByteLen - 5) Exit Sub ElseIf (ByteArray(2) <> 51) Then 'This is not a Huffman encoded string Err.Raise vbObjectError, "HuffmanDecode()", "The data either was not compressed with HE3 or is corrupt (identification string not found)" Exit Sub End If CurrPos = 5 'Extract the checksum CheckSum = ByteArray(CurrPos - 1) CurrPos = CurrPos + 1 'Extract the length of the original string Call CopyMem(ResultLen, ByteArray(CurrPos - 1), 4) CurrPos = CurrPos + 4 lResultLen = ResultLen 'If the compressed string is empty we can 'skip the function right here If (ResultLen = 0) Then Exit Sub 'MsgBox ResultLen, vbInformation, ByteArray()
'Create the result array ReDim Result(0 To ResultLen - 1) 'Get the number of characters used Call CopyMem(Count, ByteArray(CurrPos - 1), 2) CurrPos = CurrPos + 2 'Get the used characters and their 'respective bit sequence lengths For i = 1 To Count With CharValue(ByteArray(CurrPos - 1)) CurrPos = CurrPos + 1 .Count = ByteArray(CurrPos - 1) CurrPos = CurrPos + 1 ReDim .Data(0 To .Count - 1) End With Next 'Create a small array to hold the bit values, 'this is (still) faster than calculating on-fly For i = 0 To 7 BitValue(i) = 2 ^ i Next 'Extract the Huffman Tree, converting the 'byte sequence to bit sequences ByteValue = ByteArray(CurrPos - 1) CurrPos = CurrPos + 1 BitPos = 0 For i = 0 To 255 With CharValue(i) If (.Count > 0) Then For j = 0 To (.Count - 1) If (ByteValue And BitValue(BitPos)) Then .Data(j) = 1 BitPos = BitPos + 1 If (BitPos = 8) Then ByteValue = ByteArray(CurrPos - 1) CurrPos = CurrPos + 1 BitPos = 0 End If Next End If End With Next If (BitPos = 0) Then CurrPos = CurrPos - 1 'Create the Huffman Tree NodesCount = 1 Nodes(0).LeftNode = -1 Nodes(0).RightNode = -1 Nodes(0).ParentNode = -1 Nodes(0).Value = -1 For i = 0 To 255 Call CreateTree(Nodes(), NodesCount, i, CharValue(i)) Next 'Decode the actual data ResultLen = 0 For CurrPos = CurrPos To ByteLen ByteValue = ByteArray(CurrPos - 1) For BitPos = 0 To 7 If (ByteValue And BitValue(BitPos)) Then NodeIndex = Nodes(NodeIndex).RightNode Else NodeIndex = Nodes(NodeIndex).LeftNode End If If (Nodes(NodeIndex).Value > -1) Then Result(ResultLen) = Nodes(NodeIndex).Value ResultLen = ResultLen + 1 If (ResultLen = lResultLen) Then GoTo DecodeFinished NodeIndex = 0 End If Next If (CurrPos Mod 10000 = 0) Then NewProgress = CurrPos / ByteLen * PROGRESS_DECODING If (NewProgress <> CurrProgress) Then CurrProgress = NewProgress RaiseEvent Progress(CurrProgress) End If End If Next DecodeFinished:
'Verify data to check for corruption. Char = 0 For i = 0 To (ResultLen - 1) Char = Char Xor Result(i) If (i Mod 10000 = 0) Then NewProgress = i / ResultLen * PROGRESS_CHECKCRC + PROGRESS_DECODING If (NewProgress <> CurrProgress) Then CurrProgress = NewProgress RaiseEvent Progress(CurrProgress) End If End If Next If (Char <> CheckSum) Then Err.Raise vbObjectError, "clsHuffman.Decode()", "The data might be corrupted (checksum did not match expected value)" End If
'Return the uncompressed string ReDim ByteArray(0 To ResultLen - 1) Call CopyMem(ByteArray(0), Result(0), ResultLen) 'Make sure we get a "100%" progress message If (CurrProgress <> 100) Then RaiseEvent Progress(100) End If End Sub
|
|
|
|
Postada em 20/01/2012 13:45 hs
Parece que desta vez me deparei um grande problema. Dificil ainda achar um bom programador que entenda bem de algoritmos no Brasil. Pesquisando na NET, Codificação Aritmética, Huffaman, RLE, Gzip entre tantos outros algortimos de compressão de strings tem origens estrangeiras, ninguém no Brasil e nenhum site aqui fala deste assunto.
Caso alguém tenha algum endereço ou algum algoritmo, ou mesmo esteja ainda estudando na faculdade, pergunte ao seu professor e quem sabe mesmo sendo de outra linguagem eu consiga fazer a tradução para o VB6. No .NET isso já vem pronto usando o Gzip.
|
|
|
|