12 Stimmen

Wie man Zeichenfolgen in einen OutputStream schreibt

Wie kann ich eine Klasse erstellen, die eine Implementierung von OutputStream annimmt und den Inhalt darauf schreibt?

Zum Beispiel wird die folgende Print-Methode falsch sein und nicht kompilieren. Was sind die Optionen oder bessere Techniken?

public class FooBarPrinter{
    private OutputStream o;
    public FooBarPrinter(OutputStream o){
        this.o=o;
    }

    public void print(String s){        
        o.write(s);
    }
}

23voto

wattostudios Punkte 8606

Ein generischer OutputStream hat nicht die Fähigkeit, einen String direkt in ihn zu schreiben. Stattdessen müssen Sie das byte[] des String erhalten und sie dann in den Stream schreiben.

public void print(String s){ 
    o.write(s.getBytes());
}

Weitere Informationen zu den unterstützten Datentypen für das Schreiben finden Sie in der java Dokumentation für OutputStream.

Mein Vorschlag zur Verbesserung besteht darin, sicherzustellen, dass der OutputStream, den Sie im Konstruktor bereitstellen, ein BufferedOutputStream ist, da dies die Leistung Ihres Codes verbessern wird. Es funktioniert, indem es einige der Daten im Speicher puffert und sie in großen Blöcken auf die Festplatte schreibt, anstatt viele kleine Schreibvorgänge durchzuführen.

Hier ist die java Dokumentation für BufferedOutputStream

9voto

Stephen C Punkte 665668

Ich denke, dass die anderen Antworten einen wichtigen Punkt / eine wichtige Frage vermissen.

Sollten Sie wirklich einen OutputStream verwenden?

Die Klassenhierarchien OutputStream und InputStream sind zum Schreiben und Lesen von byte-orientierten Daten gedacht. Aber Java Strings sind nicht byte-orientiert. Sie sind zeichenorientiert (zum ersten Annäherung), und Zeichen in Java sind 16-Bit-Unicode-Codeeinheiten.

Wenn Sie Zeichen in einen Byte-Stream schreiben, muss die JVM eine Konvertierung durchführen, um die Zeichen als Bytes zu kodieren. Tatsächlich gibt es viele mögliche Wege, dies zu tun. Zum Beispiel wird UTF-8 jedes Zeichen in der Sequenz als ein oder mehrere Bytes kodieren, Latin-1 oder ASCII werden eine Untermenge von Zeichen als einzelne Bytes kodieren und andere in (wahrscheinlich) Fragezeichen umwandeln. Und so weiter.

Es ist jedoch möglich, etwas wie dies zu schreiben:

  public void print(String s){ 
      o.write(s.getBytes());
  }

aber es hat ein Problem. Das Problem ist, dass die getBytes()-Methode auf einem String das Standardzeichencodierungsschema der JVM verwendet, um die Konvertierung durchzuführen. Und dies (das Standardzeichencodierungsschema) hängt von der Umgebung ab, in der die JVM gestartet wurde. Dieser Code macht also je nach Umgebung unterschiedliche Dinge. Sie könnten das beheben, indem Sie den Charset angeben:

  public void print(String s){ 
      o.write(s.getBytes("UTF-8"));
  }

aber das wird umständlich, wenn Sie getBytes an vielen Stellen aufrufen.

Wenn Sie viele textbasierte Ausgaben machen, ist es eine bessere Idee, das Writer-API anstelle des OutputStream-API zu verwenden. Das Writer-API und dessen Implementierungen behandeln die Konvertierung intern ... und konsistenter und effizienter.

Der letzte Punkt ist, dass es andere APIs gibt, die hilfreich sein können, um textbasierte Ausgaben zu erstellen.

  • Die Klasse BufferedWriter (und auch BufferedOutputStream) unterstützen effiziente Ausgabe, indem sie ein In-Memory-Buffering in den Ausgabeprozess einführen. Dies spart Systemaufrufe, insbesondere wenn Sie viele kleine Schreiboperationen durchführen.
  • Die Klasse PrintWriter bietet eine Vielzahl von Komfortmethoden und entfernt auch die Notwendigkeit, IOExceptions zu behandeln. (Wenn eine IOException auftritt, macht der PrintWriter eine Notiz davon. Es gibt eine Methode zum Testen, ob eine Ausnahme aufgetreten ist. Dies kann nützlich oder gefährlich sein, je nachdem, was Sie tun ...)

2voto

Jordão Punkte 53117

Zum Schreiben von Zeichenfolgen werfen Sie einen Blick auf die PrintStream-Klasse. Sie können ein Beispiel für eine Klasse sehen, die das tut, was Sie beabsichtigen, hier.

Sie können auch ein OutputStream mit einem der PrintStream-Konstruktoren umschließen:

public class FooBarPrinter{
  private PrintStream p;
  public FooBarPrinter(OutputStream o){
    p = new PrintStream(o);
  }
  public void print(String s){      
    p.print(s);
  }
}

BEARBEITEN: Beachten Sie, dass Sie auch die PrintWriter-Klasse auf die gleiche Weise wie PrintStream oben verwenden können; was in der Regel besser ist, weil Sie die Codierung angeben können, um Plattformabhängigkeiten zu vermeiden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X