Aufgabe 10.1

Wie viele Bytes bei euch
Hi.
Wie groß ist dieses Tupel bei euch:
(5,4,‘f’)
3 Byte oder 4 Byte?


3 byte. 2 für die beiden Zahlen (zusammen 16 bit) und 1 für das zeichen.


Sehr fein, so mache ich es auch.
Nur leider scheine ich ein Problem zu haben, wenn ein “ö” kommt.


das prob hatte ich auch mal. Bei mir war es das casten von byte nach int, das ‘ö’ hat ne 1 als msb und dann hatte der int lauter 1 vorne, so dass es beim verschieben probleme gemacht hat. Ich hab dann den int wieder auf 8 bit “gekürzt”, dann gings…


Hm, beim zurückshiften hab ich das schon so gemacht

code = code >> 8;
code = code & 0x00FFFF;

So maskiere ich die ersten zwei Byte aus - egal was da drinen ist.

Edit…
Liwo - jetzt hab ich verstanden was du meinst.

frage zum beispiel
Ich hätte da mal ne kleine Frage zum Beispiel.
Wenn es heisst, dass der Offset im suchfeld vom jüngsten zum ältesten Eintrag gezählt wird, dann müsste ich doch bei der letzten Zeile zuerst das o vor dem b finden, und dann müsste das Tupel doch (5,1,o) heissen… und dann erst finde ich “obar” oder sehe ich da was total falsch?


Ich zitiere aus der Aufgabenstellung: “Während des Packens wird immer versucht, ein möglichst großes Präfix des Vorschaubereichs im Suchbereich zu finden.”


tach zusammen.
meine tupel werden soweit eigtl ganz richtig erstellt. diese sollten doch dann seriell in der datei drinstehen. jetzt ich hab das problem, dass das offset und die länge beim tupel irgendwie ganz seltsam kodiert wird und nur der buchstabe leserlich in der datei steht. irgendwie werden mir zahlen, die ich mit schreibeByte() in die datei schreibe nicht richtig reingeschrieben. warum?
kann mir vielleicht jemand einen kleinen tip geben?


Die Geschichte muss man wohl oder übel auf Bit-Ebene angehen – auch wenn das vermutlich in der Vorlesung nie erwähnt wurde…

schreibeByte() schreibt immer nur ein Byte, also die 8 untersten Bit des übergebenen [m]int[/m]s. Für den Offset brauchtst du allerdings 11, für die Länge 5. Wenn du jetzt das Offset direkt an schreibeByte() übergibst, schneidet er dir einen Teil ab…

Helfen sollten diese Operatoren:
[m]<<, >>>, &, |[/m]


ahhhhh. ich glaub ich hab verstanden was du meinst. ich probiers gleich mal. DANKE!


Ich habe gestern ein kleines Testprogramm für [m]Einpacker[/m] und [m]Auspacker[/m] mit ein paar Testdateien geschrieben. Das Programm versucht die mitgelieferten Testdateien zu komprimieren und wieder zu dekomprimieren und vergleicht dann jeweils die dekomprimierte Datei mit der ursprünglichen Datei. Vielleicht hilft das dem einen oder anderen von euch beim Beheben von Bugs.
http://airhardt.eckental-brand.de/algo/10.html


wäre vielleicht jemand so nett und könnte den inhalt der datei eines gepacktes foobarfoobarfoobar posten - ich würde es gerne einfach als referenz haben, ob der einpacker richtig funktioniert bevor ich den auspacker schreibe.
vielen dank, simple


Ich sitze grade schon wieder ne Ewigkeit vor dem Zeug weil ich nach dem 2byte-packen ums Verrecken nicht mehr an mein Offset komme :rolleyes:

Eigentlich sollte das Offset dadurch wiederhergestellt werden, dass ich das erste Byte (enthält die 8MSBs des Offsets) um 3 nach links shifte und das Ganze dann mit einem um 5 nach rechts geshifteten Byte2 verodere (Byte2 enthält in den 3 MSBs die 3LSBs des Offsets gefolgt von den 5Bit der Länge).

Leider funktioniert das nicht, demnach muss da entweder ein böser Denkfehler drin sein oder ich hab irgendwas verrafft… :vogel:

Wäre super wenn mir jemand auf die Sprünge helfen könnte!
Danke
Marko


Den Inhalt siehste ja in der Aufgabenstellung. Das sind genau die Tuppel.
Es hängt wirklich davon ab, wie du deine Tupel schreibst.
Da kann jeder sein eigenes Format haben.

public void schreibeTupel(int offset, int laenge, int folgebyte) {
  int code = offset << 5;
  code += laenge;
  
  schreibeByte(code >>> 8);
  schreibeByte(code);
  schreibeByte(folgebyte);
  // in der Datei stehen jetzt 11 Bit Offset, 5 Bit Länge und 8 Bit Folgebyte.
}

public int leseByte() {
  int read = in.read();
  if(read == -1)
    return -1;
  read  = read << 8;
  read += in.read();
  read  = read << 8;
  read += in.read();
  // in der read stehen jetzt 8 Bit fürn Arsch, 11 Bit Offset,
  // 5 Bit Länge und 8 Bit Folgebyte.
  return read;
}

public void decode(int code) {
  int folgebyte = code & 0xFF;
  code == code >>> 8;
  int laenge = code & 0x1F;
  code = code -laenge;
  code = code >>> 5;
  int offset = code;

 // so in Etwa
}

Attachment:
foobarfoobarfoobar.zl77: https://fsi.cs.fau.de/unb-attachments/post_30872/foobarfoobarfoobar.zl77


@hehejo: perfekt. danke. ja das war mir schon klar, dass sowas wie die tupel in der datei stehen sollten :-p - das hab ich auch so gemacht. ich war mir blos unsicher, weil wenn man die datei mal anguckt, dann stehen ja z.B. die “0”-en nicht mit drin.
jut - mein packer funktioniert also genauso. jetzt werd ich mich ans auspacken machen :open_mouth:


dieses >>> bedeutet übrigens, dass vorne 0er eingefügt werden.

würde vorne mit 1ern auffüllen, falls die Zahl negativ ist (also vorne eine 1 hat).


Hm, okay ist soweit auch alles nachvollziehbar, allerdings versteh ich nicht warum sowas hier nicht funktioniert:

int offset = 1234;
int laenge = 22;

// PACK
byte b1 = (byte)(offset >>> 3);
byte b2 = (byte)((offset << 5) | laenge);

// UNPACK
int u_laenge = b2 & 0x1f;
int u_offset = (b1 << 3) | (b2 >>> 5);

Für Länge funktionierts, aber für das Offset kommen seltsame Sachen raus (oft auch negatives)…


Das Verhalten von Java, was die Vorzeichen von Bitoperatoren betrifft, ist – freundlich ausgedrückt – etwas seltsam…

So sollte es funktionieren:
[m]int u_offset = ((b1 & 0xFF) << 3) | ((b2 & 0xFF) >>> 5);[/m]

([m]b1[/m],[m]b2[/m] werden (hier durch [m]&[/m], sonst durch [m]<<[/m]) automatisch nach [m]int[/m] gecastet, dabei bleibt das negative Vorzeichen ([m]byte[/m] ist signed!) erhalten)

Edit:
Hm, verständlicher wär’s vielleicht so:
[m]int u_offset = (((int)b1 & 0xFF) << 3) | (((int)b2 & 0xFF) >>> 5);[/m]


Was für ein Käse…

Aber big thx für den Hinweis, da wär ich jetzt nichtmehr draufgekommen :slight_smile:


frage zur funktionsweise: wenn ich einen treffer aus dem vorschaubereich im suchbereich finde, soll ich diesen dann gleich “dynamisch” reinnehmen, dann den suchbereich entsprechend vergrößern (bzw. hinten abschneiden) und dann weiter aus dem vorschaubereich lesen oder soll man einfach den ganzen vorschaubereich durchgehen, nach treffern suchen diese dann geballt rüberschaufeln, und anschließend so viel nach"laden" wie frei geworden ist?

beispiel: suchbereich 9 und vorschaubereich der größe 7.
jetzt kann es theoretisch sein, dass ich alle 7 zeichen aus der vorschau im suchbereich finde. d.h. ich würde anschließend 7 zeichen rüberschaufeln. aber das heißt doch auch, dass ich immer nur maximal 7 zeichen zusammenfassen könnte (wenn ich nicht entsprechend nachlade, sobald ich mind. 1 treffer gelandet habe)