Forum: PC-Programmierung Java - Klasse von OutputStream ableiten


von Wühlhase (Gast)


Lesenswert?

Mahlzeit allerseits

Ich möchte eine Klasse "SPIOutputStream" von der Klasse "OutputStream" 
ableiten. (Es geht darum, einen Stream für das yad2xx-Binding zu 
bekommen um Daten in einen FT232H rein- und rausschaufeln zu können.)

Jetzt verlangt die Superklasse OutputStream, daß ich deren abstrakte 
Methode "public void write(int i) throws IOException" überschreibe. In 
den Javadocs steht dazu:

> Writes the specified byte to this output stream. The general contract for
> write is that one byte is written to the output stream. The byte to be
> written is the eight low-order bits of the argument b. The 24 high-order
> bits of b are ignored.

Soweit so gut, jedoch: es wird NUR nach dieser Methode verlangt. Nur, wo 
lese ich aus welche Daten ich raussschieben soll? Einfach nur ein Byte 
(oder ein Bytearray) schreiben wäre kein Problem, aber die Methode hat 
ja nur einen Parameter "wieviele Bytes" geschrieben werden sollen. Aber 
wo liegen die Bytes, aus denen ich mich bedienen kann?

Outputstream stellt noch ein paar Methoden zur Verfügung, die ein 
Bytearray als Parameter enthalten, diese müssen jedoch nicht 
überschrieben werden und daher gehe ich davon aus, das sich die 
Java-Entwickler da etwas bei gedacht haben und die Superklasse bereits 
die Daten irgendwo hält. Aber wo, und wie komme ich da ran? Die 
Superklasse bietet keine Methoden dafür an.

von Der Andere (Gast)


Lesenswert?

Wühlhase schrieb:
> bereits die Daten irgendwo hält

Welche Daten soll die halten.
Wenn du z.B write(byte[] b) aufrufst, wird die von dir überschriebene 
Methode write(int i) benutzt um das Array Byte für Byte rauszuschreiben.
Wenn du Daten cachen willst ist das die Aufgabe deiner abgeleiteten 
Klasse.
Schau dir halt an wie das z.B. BufferedOutputStream macht oder benutze 
diese Klasse direkrt zum Puffern deiner Ausgaben

von Wühlhase (Gast)


Lesenswert?

Ah...also doch mehr Arbeit rein als ich gehofft hab. Dann hab ich es 
doch richtig verstanden, vielen Dank. :)

von Der Andere (Gast)


Lesenswert?

Wühlhase schrieb:
> Ah...also doch mehr Arbeit rein als ich gehofft hab.

Ich glaube du hast es nicht verstanden. Du brauchst nur write(int b) 
implementieren und kannst dann alle Klassen nutzen die einen 
OutputStream bedienen oder auf ihm aufbauen wie z.B. FilterOutputStream, 
BufferedOutputStrema, ...

von Wühlhase (Gast)


Lesenswert?

Doch doch...

"Mehr Arbeit" war vllt nur etwas übertrieben.

von Wühlhase (Gast)


Lesenswert?

Bzw. Quatsch...doch, mein Problem ist noch da.

Ich hab eine Methode "SPI.transactWrite(int bitCount, byte[] data)" die 
ich jetzt mit einem Byte füttern würde. Die Frage war wo ich das Byte 
herbekomme, im Parameter der Methode OutputStream.write() wird es ja 
nicht mitgeliefert.

von Reiner_Gast (Gast)


Lesenswert?

Wühlhase schrieb:
> Ich hab eine Methode "SPI.transactWrite(int bitCount, byte[] data)" die
> ich jetzt mit einem Byte füttern würde. Die Frage war wo ich das Byte
> herbekomme, im Parameter der Methode OutputStream.write() wird es ja
> nicht mitgeliefert.

Jetzt lies dir deinen ersten Post nochmal (aufmerksam) durch (im 
speziellen, was du aus den Docs kopiert hast; ironischerweise enthält 
das schon die Antwort auf deine Frage)...

... dann schau dir nochmal an, wie die Methode Abstrakte Methode 
deklariert ist...

... dann wie sich die Deklaration der Methode SPI.transactWrite(int 
bitCount, byte[] data) davon unterscheidet...

... und schon hast du die Antwort auf deine Frage

von Reiner_Gast (Gast)


Lesenswert?

Reiner_Gast schrieb:
> Methode Abstrakte Methode

Sollte abstrakte Methode "write" heißen :-)

von Wühlhase (Gast)


Lesenswert?

Ich hab hier mal den Code besagter OutputStream-Klasse. Vielleicht wird 
es dann deutlicher.
1
package yaD2XXutilities;
2
3
import java.io.IOException;
4
import java.io.OutputStream;
5
import java.util.logging.Level;
6
import java.util.logging.Logger;
7
import net.sf.yad2xx.FTDIException;
8
import net.sf.yad2xx.mpsse.Spi;
9
10
11
public class SPIOutputStream extends OutputStream {
12
  private final Spi connectedSPI;
13
  private byte[] writebuffer;      //???
14
15
  public SPIOutputStream(Spi spi) throws FTDIException {
16
    connectedSPI = spi;
17
    connectedSPI.open();
18
  }
19
    
20
  private void unconnectSPI(){
21
    if(connectedSPI != null) {
22
      this.connectedSPI.close();
23
    }
24
  }
25
26
  @Override
27
  public void write(int i) throws IOException {
28
    try {
29
      //Wo krieg ich die Daten her, mit denen ich writebuffer füttern will?
30
      connectedSPI.transactWrite(i, writebuffer);
31
    } catch (FTDIException ex) {
32
      Logger.getLogger(SPIOutputStream.class.getName()).log(Level.SEVERE, null, ex);
33
      throw new IOException("SPI-class has thrown exception: " + ex.getMessage());
34
    }
35
  }
36
    
37
  @Override
38
  public void close() throws IOException {
39
    unconnectSPI();
40
    super.close();
41
  }
42
43
  @Override
44
  protected void finalize() throws Throwable {
45
    unconnectSPI();
46
    super.finalize();
47
  }
48
}

von Wühlhase (Gast)


Lesenswert?

@Reiner:
Ich hab deinen Post gelesen, da war meine Antwort schon draußen. Ich 
meditiere darüber auf dem Heimweg. :)

von Reiner_Gast (Gast)


Lesenswert?

Wühlhase schrieb:
> @Reiner:
> Ich hab deinen Post gelesen, da war meine Antwort schon draußen. Ich
> meditiere darüber auf dem Heimweg. :)

@Wühlhase.... mach das... ich bin auch gleich auf dem Heimweg (und auch 
heute nicht mehr online)...

Hier ein Hinweis (ohne dass ich jetzt Fit wäre in JAVA eher so C/C++, 
die interessante Stellen habe ich mal mit {} umschlossen):

a)
> {Writes the specified byte} to this output stream. The general contract for
> write is that {one byte is written to the output stream}. {The byte to be
> written is the eight low-order bits of the argument b. The 24 high-order
> bits of b are ignored}.

b)
public void write({int} i) throws IOException

c)
SPI.transactWrite(int bitCount, {byte[]} data)

von Achim H. (anymouse)


Lesenswert?

Nochmals das JavaDoc:
1
public abstract void write(int b)
2
                    throws IOException
3
4
Writes the specified byte to this output stream. The general contract for write is that one byte is written to the output stream. The byte to be written is the eight low-order bits of the argument b. The 24 high-order bits of b are ignored.
5
6
Subclasses of OutputStream must provide an implementation for this method.
7
8
Parameters:
9
    b - the byte.

Ich weiß zwar nicht, warum die das Ausgabebyte noch in ein "int" 
verpacken.

Da sind auch schon andere drüber gestolpert:

https://stackoverflow.com/questions/1407893/why-java-outputstream-write-takes-integer-but-writes-bytes

von Wühlhase (Gast)


Lesenswert?

Eigentlich wollte ich ja die Arbeit auf der Arbeit lassen, aber 
Ausnahmen bestätigen die Regel:

Im Javadoc steht dauernd was von "Parameter b"-das ist soweit richtig, 
das hab ich auch noch zusammen gekriegt. Allerdings wird die 
überschriebene Methode als write(int i) deklariert. Ingo, nicht Berta, 
wie in der Javadoc.

Ist sowas normal?

@Achim:
Sosehr ich Java schätze-aber Byte-Kram scheint wirklich Mist zu sein in 
Java.

von Der Andere (Gast)


Lesenswert?

Wühlhase schrieb:
> Im Javadoc steht dauernd was von "Parameter b"-das ist soweit richtig,
> das hab ich auch noch zusammen gekriegt. Allerdings wird die
> überschriebene Methode als write(int i) deklariert.

Das ist jetzt nicht dein Ernst, oder? Ob die Variable i oder b heisst 
ist ja wohl völlig egal.

Wühlhase schrieb:
> Sosehr ich Java schätze-aber Byte-Kram scheint wirklich Mist zu sein in
> Java.

Sorry aber ich glaube eher der Fehler sitzt hier vor der Tastatur. Siehe 
auch dein anderer Beitrag wo du geglaubt hast das der ">" Operator nicht 
funktioniert.

von Wühlhase (Gast)


Lesenswert?

Der Andere schrieb:
> Das ist jetzt nicht dein Ernst, oder? Ob die Variable i oder b heisst
> ist ja wohl völlig egal.
Das schon, allerdings hab ich es als gute Praxis kennengelernt, die 
Parameter in der Doku genauso zu bezeichnen wie in der 
Methodendeklaration. Gleiches gilt für den Datentyp. Zumindest halte ich 
das in meiner Doku so.

Andererseits heißt es auch, daß man lieber aussagekräftige 
Variablen/Parameternamen verwenden sollte, so etwas wie b oder i, nun 
ja...

Der Andere schrieb:
> Sorry aber ich glaube eher der Fehler sitzt hier vor der Tastatur. Siehe
> auch dein anderer Beitrag wo du geglaubt hast das der ">" Operator nicht
> funktioniert.
Das will ich mir nicht anmaßen auszuschließen, allerdings beruht diese 
Einschätzung auf Erfahrungsberichten aus dem Link von Achim. Ich hab mit 
Bytes in Java bisher nur wenig tun gehabt. Was sich gerade ändert. :)

An dieser Stelle nochmal vielen Dank für den Link-wer weiß vor was der 
mich in Zukunft noch bewahrt hat.

von Jim M. (turboj)


Lesenswert?

Wühlhase schrieb:
> Ich hab mit
> Bytes in Java bisher nur wenig tun gehabt. Was sich gerade ändert. :)

Mach Dich auf Schmerzen gefasst.

Java kennt keine unsigned Typen, das fällt einem als C oder PASCAL 
gewöhnten Programmierer dann öfters auf die Füße.

Wühlhase schrieb:
> Allerdings wird die
> überschriebene Methode als write(int i) deklariert. Ingo, nicht Berta,
> wie in der Javadoc.
>
> Ist sowas normal?

Selbsverständich, denn IMO generiert Dir die IDE den Code nur aus dem 
Typ des Parameters - den Namen muss er für den Aufruf gar nicht 
kennen.

Ergo "i" für "int". Kann man eventuell sogar irgendwo einstellen.

von foo (Gast)


Lesenswert?

Jim M. schrieb:
> Java kennt keine unsigned Typen, das fällt einem als C oder PASCAL
> gewöhnten Programmierer dann öfters auf die Füße.

Richtig. Aber seit Java 8 gibt es ein paar Methoden in den Integer- und 
Long-Klassen, die sehr hilfreich sein können:
http://www.informit.com/articles/article.aspx?p=2216988&seqNum=2

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Wühlhase schrieb im Beitrag ^#5417232:
> Bzw. Quatsch...doch, mein Problem ist noch da.
>
> Ich hab eine Methode "SPI.transactWrite(int bitCount, byte[] data)" die
> ich jetzt mit einem Byte füttern würde. Die Frage war wo ich das Byte
> herbekomme, im Parameter der Methode OutputStream.write() wird es ja
> nicht mitgeliefert.

Oh Herr, lass Hirn vom Himmel fallen -(

Wenn du SPI.transactWrite(int bitCount, byte[] data) bedienen möchtest, 
dann überschreibe public void write(byte[] b, int off, int len)
1
public void write(byte[] b, int off, int len) {
2
    spi.transactWrite(len * 8, Arrays.copyOffRange(b, off, off + len));
3
    // TODO Exception handling
4
}

Die write(int b) Methode macht man sich dann passend:
1
public void write(int b) {
2
    write(new byte[]{(byte)(b & 0x00ff)}, 0, 1);
3
}

Da muss man sich nicht über Integer-Datentypen, "Schmerzen" oder anderen 
eingebildeten Kinderkram aufregen. Da muss man nicht zwei Tage wie ein 
wilder Hühnerhaufen rumlaufen. Einfach mal NACHDENKEN, in die 
Dokumentation sehen, zur Not in den Code von OutputStream (ja, den gibt 
es von Oracle und kann in jede anständige IDE eingebunden werden) und 
die sieben Zeilen Code schreiben. Oh ja, und ein bisschen Programmieren 
muss man auch können.

: Bearbeitet durch User
von dfa (Gast)


Lesenswert?

Am Beispiel dieses Threads zeigt sich, dass auch die beste Dokumentation 
versagen kann... im vom OP geposteten Absatz aus der Doku stand der 
Schlüsselsatz und die Beantwortung für seine Frage ("Wo kommen die Daten 
her?") eigentlich schon drinnen ("The byte to be written is the eight 
low-order bits of the argument b.").

von Wühlhase (Gast)


Lesenswert?

Hannes J. schrieb:
> Oh Herr, lass Hirn vom Himmel fallen -(
Frust auf der Arbeit? Etwas Seelentherapie gefällig?
https://www.youtube.com/watch?v=p32OC97aNqc

Ansonsten war das Thema eigentlich schon vorgestern erledigt (Danke an 
Rainer und Der Andere). Wie gesagt-entweder eine Deklaration write(int 
b) oder ein "int i" in der Doku hätten mir schon gereicht. Weil...

Jim M. schrieb:
> Selbsverständich, denn IMO generiert Dir die IDE den Code nur aus dem
> Typ des Parameters - den Namen muss er für den Aufruf gar nicht
> kennen.
>
> Ergo "i" für "int". Kann man eventuell sogar irgendwo einstellen.
...das eben nicht so ist. Netbeans zeigt einem auch die Parameternamen, 
mit der eine Methode deklariert wurde.

Wie gesagt-das Thema ist durch.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.