2012-06-04 18 views
8

Jak utworzyć klasę, która ma implikację OutputStream i zapisuje do niej treść?Jak napisać łańcuchy do OutputStream?

Na przykład poniższa metoda drukowania jest niepoprawna i nie będzie się kompilować. Jakie są opcje lub lepsze techniki?

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

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

Powinieneś 1) spójrz na OutputStream API i użyj dostępnych metod, i 2) jeśli masz błąd, opublikuj tutaj błąd, abyśmy nie musieli odgadnąć, co jest nie tak. –

+4

Na przykład API pokaże, że nie ma metody OutputStream o nazwie write (...), która pobiera parametr String, a więc nie można go po prostu utworzyć i oczekiwać, że zadziała. Zamiast tego musisz użyć dostępnych metod. –

Odpowiedz

20

rodzajowe OutputStream nie ma możliwości, aby napisać String bezpośrednio do niego. Zamiast tego musisz pobrać byte[] z String, a następnie zapisać je w strumieniu.

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

można znaleźć w dokumentacji OutputStream java Więcej informacji na temat obsługiwanych typów zapisu danych.

Moja sugestia, aby to zrobić lepiej, to upewnić się, że OutputStream, które podasz w konstruktorze, to BufferedOutputStream, ponieważ poprawi to wydajność twojego kodu. Działa poprzez buforowanie niektórych danych w pamięci i zapisywanie ich na dysku w dużych porcjach zamiast wielu mniejszych zapisów.

Oto dokumentacja Java dla BufferedOutputStream

0

pisać ciągi, przyjrzeć klasy PrintStream. Możesz zobaczyć przykład klasy, która robi to, co zamierzasz here.

Ponadto, można otoczyć OutputStream użyciu one of the PrintStream constructors:

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

EDIT: zauważ, że można również użyć klasy PrintWriter w taki sam sposób jak PrintStream powyżej; co jest zwykle lepsze, ponieważ można określić kodowanie do użycia, unikając zależności między platformami.

+2

Należy zauważyć, że 'PrintStream' obsługuje wyjątki inaczej: *" W przeciwieństwie do innych strumieni wyjściowych, 'PrintStream' nigdy nie rzuca' IOException', zamiast tego, wyjątkowe sytuacje jedynie ustawiają wewnętrzną flagę, która może być testowana przez 'checkError () 'metoda." * –

+0

@GregKopff: Tak, teraz jest to odnotowane. Dzięki! –

9

Myślę, że w innych odpowiedziach brakuje ważnego punktu/pytania.

Czy rzeczywiście używasz OutputStream?

Hierarchie klas OutputStream i InputStream służą do zapisywania i odczytywania danych bajtowych. Ale Struny Java nie są zorientowane na bajty. Są zorientowane na znak (do pierwszego przybliżenia), a znaki w języku Java to 16-bitowe jednostki kodowe Unicode.

Podczas wpisywania znaków do strumienia bajtów JVM musi wykonać konwersję na kodującą znaki jako bajty. W rzeczywistości jest wiele sposobów na zrobienie tego. Na przykład kodowanie UTF-8 będzie kodować każdy znak w sekwencji jako jeden lub więcej bajtów, Latin-1 lub ASCII będzie kodować podzbiór znaków jako jeden bajt i zamieniać innych w (prawdopodobnie) znaki zapytania. I tak dalej.

Teraz jest to możliwe, aby napisać coś takiego:

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

ale to ma problem.Problem polega na tym, że metoda getBytes() na String używa domyślnego schematu kodowania znaków JVM do konwersji. A to (domyślny schemat kodowania) zależy od środowiska, w którym uruchomiono maszynę JVM. Tak więc ten kod, robi różne rzeczy w zależności od środowiska. Teraz można naprawić poprzez określenie charset:

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

ale dostaje kłopotliwe jeśli dzwonisz getBytes w wielu miejscach.

Jeśli korzystasz z dużej ilości danych tekstowych, lepszym pomysłem jest użycie interfejsu API Writer zamiast interfejsu API OutputStream. API Writer i jego implementacje zajmują się konwersją pod maską ... i bardziej konsekwentnie i wydajnie.

Ostatnią kwestią jest to, że istnieją inne interfejsy API, które mogą być pomocne w uzyskiwaniu danych tekstowych.

  • BufferedWriter klasy (a także BufferedOutputStream) podtrzymywania wydajnego wyjście poprzez wprowadzenie w pamięci buforowania w procesie produkcji. To oszczędza wywołania systemowe, szczególnie jeśli wykonujesz wiele małych operacji zapisu.
  • Klasa PrintWriter zapewnia wiele wygodnych metod, a także eliminuje konieczność obsługi wyjątków IOExceptions. (Jeśli wystąpi wyjątek IOException, PrintWriter odnotowuje go.Istnieje metoda sprawdzania, czy wystąpił wyjątek.To może być użyteczne lub niebezpieczne, w zależności od tego, co robisz ...)