Avatar billede velle Nybegynder
13. december 2002 - 16:27 Der er 55 kommentarer og
2 løsninger

Byte- og binær- skrivning til fil

Jeg har udviklet en algoritme til komprimering af tekst, som er en del af min 3. årsopg i matematik. Desværre har jeg slet ikke styr på java IO og det er ikke så let at sætte sig ind i, som jeg lige havde troet.

Jeg har brug for et program:

Det skal kunne læse og skrive bytes (som skal repræsentere de 255 tegn i ascii) fra og til en fil, der udelukkende er en sekvens af bytes.

Det skal kunne læse og skrive bits fra og til en fil, der udelukkende er en sekvens af bits.

Jeg kender ikke så meget til, hvordan det fungerer i Java, men i Pascal skulle det have været noget med File of Byte og File of Boolean. Desværre er jeg ret forvirret over alle de klasser, der vikles ind i hinanden når man skal skrive til en fil i java, og jeg har slet ikke nogen anelse om hvordan jeg afgør hvilken datatype en fil skal/kan bestå af...

Selve algoritmen jeg bruger har jeg styr på, så jeg skal bare vide hvordan jeg kan skrive og læse fra disse to filer. Bytefilen skal omsættes til en sekvens af bits, som så gemmes i den anden fil (hvortil jeg kan skrive bits).

Vær flink at hjælp mig, så jeg slipper på at bruge tid på dette fremfor at skrive opgaven.

VH Velle
Avatar billede arne_v Ekspert
13. december 2002 - 16:34 #1
Det er faktisk ikke så svært.

Små eksempler på brug:

byte[] b;
FileOutputStream fos = new FileOutoutStream("filename.ext");
fos.write(b[0]);
fos.write(b);
fos.write(b,0,10);
fos.close();

byte[] b;
int l;
FileInputStream fis = new FileInputStream("filename.ext");
b[0] = fis.read();
l = fis.read(b);
l = fis.read(b, 0, b.length);
fis.close();
Avatar billede arne_v Ekspert
13. december 2002 - 16:37 #2
FileInputStream og FileOutputStream er beregnet til at læse/skrive
raw bytes.

Du bliver nødt til selv at konvertere bytes-bits, men det formoder jeg
at du har styr på.
Avatar billede disky Nybegynder
13. december 2002 - 17:16 #3
Her er et eksempel som performer langt bedre end ovenstående, fordi der er anvendt buffered input og output stream, hvilket man næsten altid gør klogt i.

Hvis man ikke går bliver der lavet et acces til filen hver eneste gang, hvilket fører til meget dårligt performance.

Du skal samtidigt catche IOException hvis du arbejder med filer, hvilket du også kan se i mit eksempel, som er et helt program som gemmer nogle bytes i en fil, og derefter læser dem ind igen og udskriver dem.

Hvis du leger med eksemplet pas lidt på, jeg har kun reserveret plads til max 10 karakterer ved indlæsning, hvis du gemmer flerer henter den max 10 ind igen.

Man skulle selvfølgelig så f.eks. hente af flere gange osv, men som eksempel er dette fint nok.

Hvis der er problemmer bare spørg.

/*
* Binary.java
*
* Created on 13. december 2002, 17:07
*/

import java.io.*;

/**
*
* @author  Disky
* @version
*/
public class Binary
{
   
    /** Creates new Binary */
    public Binary()
    {
        try
        {
        byte out[]={1,2,3,4,99};
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("c:/test.txt"));
        bos.write(out);
        bos.write(117);
        bos.close();
       
        byte ind[]=new byte[10]; //reserver plads nok
        int længde=0;
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("c:/test.txt"));
        længde=bis.read(ind,0,ind.length); //læs max det antal pladser som der er i ind arrayet.
        //du kan også bruge bis.read(byte) eller bis.read(b[])
        for(int x=0;x<længde;x++)
        {
            System.out.println(""+ind[x]);
        }
        bis.close();
       
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }
   
    /**
    * @param args the command line arguments
    */
    public static void main(String args[])
    {
        new Binary();
    }
   
}
Avatar billede velle Nybegynder
13. december 2002 - 17:17 #4
Kan man ikke lave et eller andet med en buffer, så jeg kan skrive bits til denne buffer og den automatisk samler disse i bytes og skriver dem til filen.
Avatar billede disky Nybegynder
13. december 2002 - 17:23 #5
Det letteste ville være at loade og save hele filen i et hug.

Ellers skal du til at rode med at hente og gemme dele af bytes af gangen, og det kræver enten at du kun kan gemme i grupper af 8 bit, eller bruger random access filer.
Avatar billede disky Nybegynder
13. december 2002 - 17:26 #6
Der er en udemærket artikel om hvordan du laver din egent BitInputStream og BitOutStream klasse her:
http://archive.devx.com/java/free/articles/gt052002/gt052002-1.asp
Avatar billede disky Nybegynder
13. december 2002 - 17:28 #7
Sourcekoden er her:
// $Id$
 
  import java.io.*;
 
  public class BitInputStream
  {
    private InputStream in;
    private int buffer;
    private int nextBit = 8;
 
    public BitInputStream( InputStream in ) {
      this.in = in;
    }
 
    synchronized public int readBit() throws IOException {
      if (in == null)
        throw new IOException( "Already closed" );
 
      if (nextBit==8) {
        buffer = in.read();
 
        if (buffer==-1)
          throw new EOFException();
 
        nextBit = 0;
      }
 
      int bit = buffer & (1<<nextBit);
      nextBit++;
 
      bit = bit == 0 ? 0 : 1;
 
      return bit;
    }
 
    public void close() throws IOException {
      in.close();
      in = null;
    }
  }


og

// $Id$
 
  import java.io.*;
 
  public class BitOutputStream
  {
    private OutputStream out;
    private int buffer;
    private int bitCount;
 
    public BitOutputStream( OutputStream out ) {
      this.out = out;
    }
 
    synchronized public void writeBit( int bit ) throws IOException {
      if (out==null)
        throw new IOException( "Already closed" );
 
      if (bit != 0 && bit != 1) {
        throw new IOException( bit+" is not a bit" );
      }
 
      buffer |= bit<<bitCount;
      bitCount++;
 
      if (bitCount==8) {
        flush();
      }
    }
 
    private void flush() throws IOException {
      if (bitCount>0) {
        out.write( (byte)buffer );
        bitCount=0;
        buffer=0;
      }
    }
 
    public void close() throws IOException {
      flush();
      out.close();
      out = null;
    }
  }
Avatar billede velle Nybegynder
13. december 2002 - 17:35 #8
jeg kigger lige på det
Avatar billede disky Nybegynder
13. december 2002 - 17:36 #9
Her er et eksempel der skriver og læser 10 bit til en fil:
/*
* Binary.java
*
* Created on 13. december 2002, 17:07
*/

import java.io.*;

/**
*
* @author  Disky
* @version
*/
public class Binary
{
    Binary()
    {
        try
        {
            BitOutputStream bos=new BitOutputStream(new BufferedOutputStream(new FileOutputStream("c:/test.txt")));
           
            bos.writeBit(0);
            bos.writeBit(1);
            bos.writeBit(1);
            bos.writeBit(0);
            bos.writeBit(1);
            bos.writeBit(1);
            bos.writeBit(0);
            bos.writeBit(0);
            bos.writeBit(1);
            bos.writeBit(0);
           
            bos.close();
           
            BitInputStream bis=new BitInputStream(new BufferedInputStream(new FileInputStream("c:/test.txt")));

            int bit;
           
            for(int x=0;x<10;x++)
            {
                bit=bis.readBit();
                System.out.println(""+bit);
            }
            bis.close();
        }
        catch(FileNotFoundException e)
        {
        }
        catch(IOException e)
        {
        }
    }
   
    /**
    * @param args the command line arguments
    */
    public static void main(String args[])
    {
        new Binary();
   
    }
   
}


p.s. Error handlingen i hans klasser er ikke super, men de giver et glimrende grundlag at arbejde videre på
Avatar billede velle Nybegynder
13. december 2002 - 17:39 #10
Hvis FileInputStream læser bytes, hvordan kan det så være at read() giver en integer værdi?
Avatar billede carstenknudsen Nybegynder
13. december 2002 - 17:43 #11
Det er for at den kan signalere at noget gik galt
ved at returnere -1.
Avatar billede velle Nybegynder
13. december 2002 - 17:57 #12
der er noget helt galt :-) det lader til at den tømmer filerne, når den åbner dem... hvordan undgår jeg det?
Avatar billede arne_v Ekspert
13. december 2002 - 17:59 #13
Tømmer filerne ? Mener du sletter indholdet ? Det bør de ikke !
Hverken FileINputStream, BufferedInputStream eller BitInputStream !
Avatar billede disky Nybegynder
13. december 2002 - 18:47 #14
int værdien er enten 0 eller 1

og kan ikke være andet ud fra: bit = bit == 0 ? 0 : 1;

Hvis der går noget galt throw'er han en exception.

Prøv at post din kode der læser fra filen, så vi kan se hvad du laver ?
Hvis du skriver til filen slettes det gamle indhold.
Avatar billede velle Nybegynder
13. december 2002 - 18:50 #15
jeg ved ikke hvordan jeg fik den til at tømme filerne før, men anyway så har jeg et nyt spørgsmål:

import java.io.*;
public class tom {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("hej.dat");
        byte[] inp = new byte[1000];
        int i = 0;
        boolean stop = false;
        while (true) {
            try {
                inp[i++] = (byte)fis.read();
            }
            catch(EOFException e) {
                break;
            }
        }
    }
}

Jeg troede jeg kunne få den til at afbryde loopet på denne måde, når filen er læst til ende, men det virker ikke. Hvad skal jeg så gøre?
Avatar billede arne_v Ekspert
13. december 2002 - 18:52 #16
Test på fis.read() - hvis den returnerer < 0, så
er den gal.

[og du skal naturligvis vente med at typecaste til efter testet]
Avatar billede disky Nybegynder
13. december 2002 - 18:53 #17
noget i retningen af:

import java.io.*;
public class tom {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("hej.dat");
        byte[] inp = new byte[1000];
        int i = 0;
int data;
        boolean stop = false;
        while ((data=fis.read())!=-1) {
            try {
                inp[i++] = (byte)data;
            }
            catch(EOFException e) {
            }
        }
    }
}
Avatar billede arne_v Ekspert
13. december 2002 - 18:54 #18
read

public int read()
        throws IOException

    Reads a byte of data from this input stream. This method blocks if no input is yet available.

    Specified by:
    read in class InputStream

    Returns:
    the next byte of data, or -1 if the end of the file is reached. Throws:
    IOException - if an I/O error occurs.


-1 => end of file
IOException => fejl f.eks. kaput harddisk og den slags
Avatar billede disky Nybegynder
13. december 2002 - 18:54 #19
Eller endnu bedre:
import java.io.*;
public class tom {
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("hej.dat");
        byte[] inp = new byte[1000];
        int i = 0;
        boolean stop = false;
try
{
        while (true) {
              inp[i++] = (byte)fis.read();
            }
        }
            catch(EOFException e) {
                break;
            }
    }
}
Avatar billede arne_v Ekspert
13. december 2002 - 18:56 #20
PS: og når du læser en enkelt byte af gangen, så kan du overvejer
    BufferedInputStream.
Avatar billede velle Nybegynder
13. december 2002 - 19:32 #21
Tak for det hele, jeg har overhovedet ikke forladt computeren siden jeg skrev indlægget, men det tager lidt tid for mig at teste det, fordi jeg slet ikke er vant til at skrive java. Anyway: Når den læser et æ så bliver værdien -26!!! Den skal kunne tage alle tegn, så man kan sætte den til at løbe et hvilket som helst txt-dokument igennem. Er det svært at få ordnet?
Avatar billede arne_v Ekspert
13. december 2002 - 19:34 #22
-26 er (formoder jeg) korrekt !

byte er signed d.v.s. har værdier -128..127

og alle 8 bit tegn bliver negative !

[det var derfor du skulle teste på retur værdien
inden typecast til byte !]
Avatar billede arne_v Ekspert
13. december 2002 - 19:37 #23
Jeg har lige checket -26 = E6 = æ !

(og ja - jeg har også tit bandet og svovlet over at Java
ikke har unsigned datatyper, men det har Jav altså ikke)
Avatar billede velle Nybegynder
13. december 2002 - 19:40 #24
jeg tog som udgangspunkt at byte er signed 0-255 (vant til fra Pascal), og hvis du ser længere oppe i carsten knudsens indlæg (hvis det da er sandt) så giver det jo netop mening hvis byte ikke er signed for 0.
Avatar billede arne_v Ekspert
13. december 2002 - 19:42 #25
read returnerer en int:
  0..255 som data
  -1 for fejl

når du typecaster den int til en byte får du:
  -128..127

Carstens svar er korrekt, fordi han snakke rom int'en.

Pointen som jeg allerede har nævnt flere gange er at man
skal teste for -1 inden man typecaster fordi ellers vil
valide data blive betragtet som fejl.
Avatar billede arne_v Ekspert
13. december 2002 - 19:43 #26
int i = 255;
byte b = (byte)i;
System.out.println(b);

udskriver -1 !
Avatar billede arne_v Ekspert
13. december 2002 - 19:46 #27
Hvad næste værre er (men dog meget logisk):

int i = 255;
byte b = (byte)i;
int j = b;
System.out.println(j);

udskriver også -1.

Man skal bruge:

int i = 255;
byte b = (byte)i;
int j = 0xFF & (int)b;
System.out.println(j);

for at få 255 igen.
Avatar billede velle Nybegynder
13. december 2002 - 19:49 #28
yes yes. Jeg har ikke før prøvet at nogen har været så gode og hurtige til at svare, er det pga. pointene eller pga. interesse? :-)
Avatar billede arne_v Ekspert
13. december 2002 - 19:52 #29
Lad os sige 67% interesse for Java + 33% interesse for point
kombineret med at have brugt hundredevis af timer gennem de
sidste par år på at skrive Java kode der læser og skriver
records med unsigned 8/16/32 bits integers i.
Avatar billede velle Nybegynder
13. december 2002 - 20:09 #30
Nu er jeg stødt på noget, som jeg slet ikke havde tænkt igennem før. Den skal tælle hvor mange gange, de forskellige tegn forekommer, og det kan jeg sagtens lave. Men efterfølgende skal den generere en liste med tegnene arrangeret efter hyppighed. Kan det ikke ordnes på anden måde end brug af array. Jeg kunne godt tænke mig en løsning hvor objekterne rent faktisk skifter plads afhængigt af deres hyppighed. ?
Avatar billede arne_v Ekspert
13. december 2002 - 20:39 #31
Du kan enten gemme i et array og sortere normalt.

Eller så kan du lave din egen klasse or gemme
i en ArrayList som kan sorteres.

Ønsker du løbende sortering - aætså at for hver gang
du har fundet et tegn skal du opdatere hyypigheden
og sortere ?

I så fald skal du nok have et træ (a la det man normalt
bruger til at implementere dynamisk Huffmann encoding).

Apropos - hvilken form for komprimering bruger du
Huffman, Aritmetisk, LZ78/LZW, LZ77, BW ?
Avatar billede disky Nybegynder
13. december 2002 - 20:43 #32
Smid data i en dynamisk ArrayList, når du har talt alle forekomster, lav et array ud af det og kald sort() metoden som java har på dit array.

Hvad angår årsag til at hjælpe, er det for mit tilfælde

100% fordi jeg kan lide at hjælpe andre, point bruger jeg ikke til andet end at bibeholde men #1 plads i java og jsp og #8 på hele sitets top 10 :-)

Det har dog også krævet en del arbejde at opnå :)

Men jeg synes da helt klart også det er sjovt at finde metoder, løsninger og lignende, man lærer jo selv nye ting hele tiden.
Avatar billede magoo20000 Nybegynder
13. december 2002 - 21:01 #33
Nu er jeg lidt nysgerrig!
arne + disky -> Hvad laver i til dagligt? Konsulenter?
Avatar billede arne_v Ekspert
13. december 2002 - 21:07 #34
Senior Software Engineer i et amerikansk firma
Avatar billede disky Nybegynder
13. december 2002 - 21:15 #35
Jeg er java konsulent for et firma i nærheden af København, og har i næsten et år været hos et stort mobil telefon firma, hvor jeg arbejder med Java og C udvikling til mobiltelefoner.
Avatar billede velle Nybegynder
13. december 2002 - 21:26 #36
Nu skal i lige se, hvad jeg har lavet !!! jeg er ikke helt dum, selvom det er nærliggende at tro :-) Men det kunne jo sikker have været lavet smartere? (btw. så skal jeg senere have det udvidet til at tælle forekomster af strenge på to tegn).

import java.io.*;
public class tom {
    static Tegn[] fk1 = new Tegn[256];
    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("hej.dat");
        for (int i = 0 ; i < 256 ; i++)
            fk1[i] = new Tegn(i);
        byte a = 0;
        int count = -1;
        int buffer;
        while (true) {
            buffer = fis.read();
            if (buffer == -1)
                break;
            a = (byte)buffer;
            System.out.println(a);
            fk1[a].inc();
        }
       
        for (int i = 0; i < 256 ; i++) {
            fk1[i].hyppighed = (int)(Math.random()*10);
        }

        skriv();
        Tegn tmp;
        int min,max;
        for ( int l=0,r=255 ; l<r ; l++, r--) {
            min = r;
            max = l;
            for (int i=l+1 ; i<r-1 ; i++) {
                if ( fk1[i].getH() < fk1[min].getH() )
                    min = i;
                else if ( fk1[i].getH() > fk1[max].getH() )
                    max = i;
                tmp = fk1[max];
                fk1[max] = fk1[l];
                fk1[l] = tmp;
                tmp = fk1[min];
                fk1[min] = fk1[r];
                fk1[r] = tmp;
            }
        }
        skriv();
    }
   
    public static void skriv() {
        for (int i = 0 ; i<256 ; i++)
            System.out.print(fk1[i].værdi + ": " + fk1[i].getH() + " ");
        System.out.println("h2j");
    }
}

class Tegn {
    byte værdi;
    int hyppighed; //antal registrering
    Tegn(int nr) {
        værdi = (byte)nr;
        hyppighed = 0;
    }
    public void inc() {
        hyppighed++;
    }
    public int getH() {
        return hyppighed;
    }
}
Avatar billede magoo20000 Nybegynder
13. december 2002 - 21:30 #37
OK tak! Er bare nysgerrig anlagt ;-)
Avatar billede disky Nybegynder
13. december 2002 - 21:31 #38
hmmm du henter en fil tælle data i den, for derefter at overskrive det talte med dit random kald, øh hvorfor ?
Istedet for at lave din egen sortering kan du med fordel bruge den Java har :)
Avatar billede velle Nybegynder
13. december 2002 - 21:37 #39
Angående komprimering, så er det et system jeg fandt på tidligere idag. Det eneste jeg har af materiale til min opg som vedrører komprimering er en artikel fra 93 i politiken om huffman, men den omtaler slet ikke, hvordan man får computeren til at holde styr på, hvornår en ny datasekvens begynder. Men så tænkte jeg:

xxxk xxxk xxxk xxxk xxxk .... .... osv.

hvor k hele tiden afgør om den følgende sekvens skal kobles på. Et ofteforekommende tegn f.eks. skulle f.eks. optræde som

yyy0

hvor koden for "e" er yyy. Mens et sjældent forekommende tegn f.eks. § skal repræsenteres af

yyy1yyy1yyy0

hvor yyyyyyyyy er den binære værdi for §

Disse repræsentationer bliver selvfølgeligt mine egne afhængigt af tegnenes frekvenser. De overflødige pladser kan bruges til ofte forekommende strenge af 2 eller 3 tegn.

Jeg ved endnu ikke om jeg vil opdele det netop med xxxk xxxk osv. Det kunne jo også være xxx k xxxxxk hvorved netop asciialfabetet repræsenteres.
Avatar billede disky Nybegynder
13. december 2002 - 21:41 #40
Jeg har lige pillet lidt i koden, der var lidt problemmer med at byte er signed, så et tal som 128 blev til -128 og det gav ArrayOutOfBoundException.

Gem værdierne som int intil de skal bruges som byte's.
Eller typecast dem til en int og derefter and'e med 0xff får at fjerne fortegnsfejlen:


import java.io.*;

public class tom
{
    static Tegn[] fk1 = new Tegn[256];
   
    public static void main(String[] args) throws Exception
    {
        FileInputStream fis = new FileInputStream("c:/DbHandler.java");
        for (int i = 0 ; i < 256 ; i++)
            fk1[i] = new Tegn(i);
        int count = -1;
        int buffer;
        while ( (buffer=fis.read())!=-1)
        {
            buffer=buffer&0xff;  //ellers balade da byte er signed
            System.out.println(buffer);
            fk1[buffer].inc();
        }
/*
        for (int i = 0; i < 256 ; i++)
        {
            fk1[i].hyppighed = (int)(Math.random()*10);
        }
*/       
        skriv();
        Tegn tmp;
        int min,max;
        for ( int l=0,r=255 ; l<r ; l++, r--)
        {
            min = r;
            max = l;
            for (int i=l+1 ; i<r-1 ; i++)
            {
                if ( fk1[i].getH() < fk1[min].getH() )
                    min = i;
                else if ( fk1[i].getH() > fk1[max].getH() )
                    max = i;
                tmp = fk1[max];
                fk1[max] = fk1[l];
                fk1[l] = tmp;
                tmp = fk1[min];
                fk1[min] = fk1[r];
                fk1[r] = tmp;
            }
        }
        skriv();
    }
   
    public static void skriv()
    {
        for (int i = 0 ; i<fk1.length ; i++)
        {
            System.out.print(fk1[i].værdi + ": " + fk1[i].getH() + "  ");
            if(i%16==0) System.out.println(""); //få det til at se lidt pænere ud
        }
       
        System.out.println("h2j");
    }
}

class Tegn
{
    int værdi;
    int hyppighed; //antal registrering
    Tegn(int nr)
    {
        værdi = nr;
        hyppighed = 0;
    }
    public void inc()
    {
        hyppighed++;
    }
    public int getH()
    {
        return hyppighed;
    }
}
Avatar billede velle Nybegynder
13. december 2002 - 21:42 #41
Pis, for det første skulle random have være udkommenteret, men nu har jeg fundet ud af at den nogen gange kludrer i det, selvom jeg troede jeg havde testet det ordentligt... Nå anyway, hvordan bruger jeg Javas sortering? :-)
Avatar billede disky Nybegynder
13. december 2002 - 21:51 #42
Her er en der bruger Sort()

En lidt speciel del er denne her:
        Comparator comp=new Comparator()
        {
            public int compare(Object o1, Object o2)
            {
                int s1=((Tegn)o1).værdi;
                int s2=((Tegn)o2).værdi;
                return s1-s2;
            }
        };

Her definerer man en comparator, som finder ud af hvilken af to Tegn der er størst. Man modtager to objekter, dem caster jeg til Tegn, hvorefter jeg henter 'værdi' fra dem.
Hvis den første værdi er mindst skal retur værdien være negativ, nul hvis de er ens, og positiv hvis nummer 2 er mindst.



import java.io.*;
import java.util.*;

public class tom
{
    Tegn[] fk1 = new Tegn[256];
   
    public static void main(String[] args) throws Exception
    {
        new tom();
    }
   
    tom() throws Exception
    {
        FileInputStream fis = new FileInputStream("c:/DbHandler.java");
        for (int i = 0 ; i < 256 ; i++)
            fk1[i] = new Tegn(i);
        int count = -1;
        int buffer;
        while ( (buffer=fis.read())!=-1)
        {
            buffer=buffer&0xff;  //ellers balade da byte er signed
            System.out.println(buffer);
            fk1[buffer].inc();
        }
/*
        for (int i = 0; i < 256 ; i++)
        {
            fk1[i].hyppighed = (int)(Math.random()*10);
        }
*/
        skriv();
        Tegn tmp;
       
        Comparator comp=new Comparator()
        {
            public int compare(Object o1, Object o2)
            {
                int s1=((Tegn)o1).værdi;
                int s2=((Tegn)o2).værdi;
                return s1-s2;
            }
        };
       
        java.util.Arrays.sort(fk1,comp);
       
        skriv();
    }
   
    public void skriv()
    {
        for (int i = 0 ; i<fk1.length ; i++)
        {
            System.out.print(fk1[i].værdi + ": " + fk1[i].getH() + "  ");
            if(i%16==0) System.out.println(""); //få det til at se lidt pænere ud
        }
       
        System.out.println("h2j");
    }
}

class Tegn
{
    int værdi;
    int hyppighed; //antal registrering
    Tegn(int nr)
    {
        værdi = nr;
        hyppighed = 0;
    }
    public void inc()
    {
        hyppighed++;
    }
    public int getH()
    {
        return hyppighed;
    }
}
Avatar billede arne_v Ekspert
13. december 2002 - 22:00 #43
Jeg ville lave det som:

package test;

import java.io.*;
import java.util.*;

public class Tom {
    static ArrayList fk1 = new ArrayList();
    public static void main(String[] args) throws Exception {
        BufferedInputStream bis =
            new BufferedInputStream(new FileInputStream("hej.dat"));
        for (int i = 0; i < 256; i++) {
            fk1.add(new Tegn(i));
        }
        int buffer;
        while ((buffer = bis.read()) > 0) {
            System.out.println(buffer);
            Tegn t = (Tegn) fk1.get(buffer);
            t.inc();
        }
        for (int i = 0; i < 256; i++) {
            Tegn t = (Tegn) fk1.get(i);
            t.inc((int) (Math.random() * 10));
        }
        skriv();
        Collections.sort(fk1);
        skriv();
    }

    public static void skriv() {
        for (int i = 0; i < 256; i++) {
            Tegn t = (Tegn) fk1.get(i);
            System.out.print(t.getV() + ": " + t.getH() + " ");
        }
        System.out.println("h2j");
    }
}

class Tegn implements Comparable {
    byte værdi;
    int hyppighed;
    Tegn(int nr) {
        værdi = (byte) nr;
        hyppighed = 0;
    }
    public void inc() {
        hyppighed++;
    }
    public void inc(int n) {
        hyppighed += n;
    }
    public int getV() {
        return værdi;
    }
    public int getH() {
        return hyppighed;
    }
    public int compareTo(Object o) {
        return værdi - ((Tegn) o).værdi;
    }
}
Avatar billede velle Nybegynder
13. december 2002 - 22:00 #44
Kanon. Svar mig på dette spørgsmål, og så skal du nok få dine point :-)

Hvad er en arraylist, og ville det have været smartere at bruge den løsning til dette her?
Avatar billede velle Nybegynder
13. december 2002 - 22:01 #45
Hvis jeg markerer jeg begge to, får I så 100p hver?
Avatar billede arne_v Ekspert
13. december 2002 - 22:02 #46
Nej diskys array se faktisk smartede ud en min ArrayList.
Avatar billede velle Nybegynder
13. december 2002 - 22:02 #47
btw Min forrige msg ("Kanon ....") blev sendt inden jeg havde set dit indlæg ArneV.
Avatar billede arne_v Ekspert
13. december 2002 - 22:02 #48
Det er ihvertfald muligt at dele point.
Avatar billede disky Nybegynder
13. december 2002 - 22:03 #49
Nej en af ovenstående løsninger er hel fin :)

Du skal vælge avanceret point givning, og så indtaste det antal point du ønsker at give de enkelte personer.

Så er det helt op til dig hvem der har hjulpet dig hvormeget :)
Avatar billede disky Nybegynder
13. december 2002 - 22:04 #50
Jeg siger mange tak, og du spørger bare hvis du har brug for hjælp igen :)
Avatar billede velle Nybegynder
13. december 2002 - 22:04 #51
Jeg markerede begge og trykkede accepter, jeg håber I fik 100 hver. Tak for det hele. Men jeg kommer jo nok med endnu en tråd, når jeg er strandet igen :-) VH Velle
Avatar billede arne_v Ekspert
13. december 2002 - 22:05 #52
Du bør iøvrigt læse lidt mere om compression teori.

En model med tegn som 4,8 eller 12 bits er dårligere end
Huffmann.

Og Huffmann er ikke engang særligt optimalt.

Arithmetisk er bedre.

Og hvis man opgiver et krav om at komprimere bytes enkeltvist, så
er LZ77, LZ78/LZW og BW alle bedre.

PS: Det er et helvede at kode det træ til dynamisk huffmann encoding.
Avatar billede arne_v Ekspert
13. december 2002 - 22:08 #53
Huffman Encoding: Journal of Algorithms 6, pp 163-180
(den er skervet af Knuth hvilket garanter at indholdet
er pinligt korrekt - og at den er svær at læse).

Arithmetisk: CACM june 1987 Volume 30 Number 6 (og den er
mere menneskelig at læse).
Avatar billede disky Nybegynder
13. december 2002 - 22:08 #54
Avatar billede velle Nybegynder
13. december 2002 - 22:12 #55
I er sq gode at kende :-) I svarer på mine spørgsmål inden jeg får dem stillet.
Avatar billede disky Nybegynder
13. december 2002 - 22:24 #56
hehe
Avatar billede arne_v Ekspert
14. december 2002 - 11:36 #57
To yderligere noter:

1)  Hvis du skal have noget matematik ind, så er pointen
    den at:
      for enkelt byte compression algoritmer kræver optimail
      compression at alle bogstaver encodes med et antal
      bit svarende til 2-tals-logaritmen af deres andel
    Aritmetisk rammer lige præcis, Huffman rammer nærmeste
    heltal. Din algoritme (som beskrevet) vil ramme nærmste 4/8/12.

2)  Både aritmetisk og Huffman opererer med 257 tegn (256 værdier
    + en EOF marker). Det er nødvendigt, fordi eller kan der komme
    ekstra tegn ind under dekryptering til sidst. Din algoritme
    (som beskrevet) skulle ikke have det behov, men hvis du forbedrer
    den, så vil du også få brug for det.
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