Avatar billede tjacob Juniormester
07. november 2007 - 11:57 Der er 9 kommentarer og
2 løsninger

Bit/Byte transformationer

Jeg har et program der bruger en række filer (flere hundrede) som input. I Hver fil er der poster (grupper af karakterer) der er 100 til 30.000 karakterer (bytes) lange. Disse poster indeholder kun 8 forskellige karakterer (det kunne være bogstaverne a-h) i tilfældig orden/antal.
Filerne kan indeholde op til 1000 sådanne poster, så de kan blive temmelig store.

Jeg ville gerne komprimere disse filer lidt.
8 forskellige karakterer kan udtrykkes i 3 bits (000 til 111), så jeg tænkte at jeg kunne lave alle karakterer om til bits, og derefter 'hakke' dem op i 8 bit stykker, der kunne konverteres til bytes.
Så ville filerne blive ca. 2½ gang mindre. Der skal så være en header med længden.

Jeg har været ved at kigge på BitConverter og BitArray klasserne. Mit problem er ikke i selve transformationerne, men at få konstrueret et loop der udfører selve opgaven med de 3 og 8 bits. Det skal helst være en rimelig hurtig funktion, da det godt kan tage lidt tid med 30.000 karakterer.

Nogen der har et bud på en sådan funktion der tager en String (eller Byte Array) som input, og som outputter en String (eller et Byte Array)?

Eller måske en helt anden måde at komprimere filerne på?
Avatar billede nielle Nybegynder
07. november 2007 - 12:49 #1
Et alternativ kunne være at kigge på klasserne i System.IO.Compression, f.eks. GZipStream:

http://msdn2.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx
Avatar billede tjacob Juniormester
07. november 2007 - 13:31 #2
Nielle>>

Det ser ud til at det er noget der dur!!
Jeg har testet den, og den er rimelig hurtig, og komprimerer disse filer til ca 1/4 størrelse!!

Filerne er, pga de mange gentagne tegn, velegnede til komprimering.
Jeg har filerne gemt som Rijndael krypterede, og da jeg først kørte komprimeringen, så blev den komprimerede fil større end originalen!!
Men komprimeringen skal naturligvis laves FØR kryptering, og så giver den førnævnte 1/4 størrelse.

Så det er vist løsningen....

Jeg lader dog lige spm. stå, da jeg sådan set stadigvæk er interesseret i ovennævnte funktion med 3-8 bit konverteringen. Der er 60 points ekstra til den der kan komme med den....
Avatar billede arne_v Ekspert
07. november 2007 - 18:47 #3
Avatar billede tjacob Juniormester
08. november 2007 - 11:38 #4
Arne>>

Den er også interessant. I/O af alle bitstørrelser 1 til 64, -Det er noget jeg kan bruge.

Jeg har et lille hobbyprojekt med en Sudoku solver/generator, og der er der virkelig gang i bit-operationerne, så den skal nok blive nyttig....

Desværre (for mig) er den i C#.
Jeg er dog i gang med selvstudium, og forventer at gå over til C# i løbet af nogle måneder (år? ;), men indtil videre skal jeg have oversat funktionerne før jeg kan bruge dem.
Avatar billede arne_v Ekspert
08. november 2007 - 19:40 #5
Du kan godt compile en C# klasse til en DLL og saa bruge klassen/klasserne fra VB.NET !
Avatar billede arne_v Ekspert
08. november 2007 - 19:41 #6
Hvordan bruger du GzipStream ?

Det kan godt have lidt indflydelse paa komprimerings graden.
Avatar billede tjacob Juniormester
09. november 2007 - 09:25 #7
Ok, jeg vil prøve, om ikke jeg kan få den compilet.
MHT GzipStream: Helt simpelt uden errorhandling ser det sådan ud:

    Public Sub SaveCompressed(ByVal sFileName As String, ByVal sText As String)

        Dim fStream As FileStream = File.Open(sFileName, FileMode.OpenOrCreate)
        Dim gzStream As New GZipStream(fStream, CompressionMode.Compress)
        Dim sWriter As New StreamWriter(gzStream)
        sWriter.Write(sText)
        sWriter.Close()
        gzStream.Close()
        fStream.Close()

    End Sub
Avatar billede tjacob Juniormester
09. november 2007 - 11:31 #8
Så fik jeg den compilet til en dll (første gang jeg prøver det!) -Det var faktisk forbavsende simpelt.

Den fungerer fint med VB.NET, og den er (såvidt jeg kan se) lynende hurtig.

Og løsningen med min 3-8 bit er simpel nu:

Jeg har lavet en funktion der laver en Streng (med bogstaver a-h) om til et boolean array der er tre gange så lang som strengen, hvor hvert element repræsenterer en bit.

Nu laver jeg en bStream as New BKSystem.IO.BitStream()
skriver bits til streamen: bStream.Write(mit bool array)
-og laver det om til en streng igen:
Dim bArray() as Byte = bStream.ToByteArray
Dim sOutString As String = System.Text.Encoding.UTF8.GetString(bArray)

-Der skal så laves noget header med længden for at tage hånd om padding m.m., men det er detaljer.
Avatar billede tjacob Juniormester
09. november 2007 - 11:36 #9
Tak for hjælpen til jer begge.

Lægger i nogle svar?
Avatar billede nielle Nybegynder
09. november 2007 - 18:40 #10
Svar :^)
Avatar billede arne_v Ekspert
09. november 2007 - 18:46 #11
.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester