web-dev-qa-db-ja.com

文字列をOutputStreamに書き込む方法

豊富なOutputStreamを使用してコンテンツを書き込むクラスを作成するにはどうすればよいですか?

たとえば、次の印刷方法は間違っており、コンパイルされません。オプションまたはより良いテクニックは何ですか?

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

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

ジェネリックOutputStreamには、Stringを直接書き込む機能はありません。代わりに、Stringbyte[]を取得して、ストリームに書き込む必要があります。

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

サポートされている書き込みデータ型の詳細については、 OutputStream Javaのドキュメントを参照してください。

これを改善するための私の提案は、コンストラクタで提供するOutputStreamBufferedOutputStreamであることを確認することです。これにより、コードのパフォーマンスが向上します。これは、データの一部をメモリにバッファリングし、多数の小さな書き込みではなく大きなチャンクでディスクに書き込むことによって機能します。

Java BufferedOutputStream)のドキュメント

23
wattostudios

他の回答は重要な点・質問が欠けていると思います。

本当にOutputStreamを使用する必要がありますか?

OutputStreamおよびInputStreamクラス階層は、バイト指向データの書き込みおよび読み取り用です。ただし、Java文字列はバイト指向ではありません。文字列(最初の概算では)であり、Javaの文字は16ビットUnicodeコード単位です。

文字をバイトストリームに書き込む場合、JVMは文字をバイトとしてencodeに変換する必要があります。実際、これを行うには多くの可能な方法があります。たとえば、UTF-8はシーケンス内の各文字を1つとしてエンコードしますまたはそれ以上バイト、Latin-1またはASCIIはサブセット)をエンコードします文字を1バイトとして、他の文字を(おそらく)疑問符に変換します。

今、このようなものを書くことが可能です:

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

しかし、問題があります。問題は、StringgetBytes()メソッドがJVMのデフォルトの文字エンコード方式を使用して変換を行うことです。そして、これ(デフォルトのコード化スキーム)は、JVMが起動された環境に依存します。したがって、そのコードは、環境に応じて異なる処理を行います。これで、文字セットを指定して修正できます。

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

しかし、多くの場所でgetBytesを呼び出すと、面倒になります。

多くのテキストベースの出力を行う場合は、Writer AP​​Iの代わりにOutputStream AP​​Iを使用することをお勧めします。 Writer AP​​Iとその実装は、内部での変換を処理します...より一貫して効率的に。

最後のポイントは、テキストベースの出力を行うのに役立つ他のAPIがあることです。

  • BufferedWriterクラス(およびBufferedOutputStream)は、出力プロセスにメモリ内バッファリングを導入することにより、効率的な出力をサポートします。これにより、特に小さな書き込み操作を多数実行している場合に、システムコールを節約できます。
  • PrintWriterクラスは、多くの便利なメソッドを提供し、IOExceptionsを処理する必要もなくなります。 (IOExceptionが発生した場合、PrintWriterはそれを記録します。例外が発生したかどうかをテストする方法があります。これは、何をしているのかによって、有用または危険になる場合があります...)
9
Stephen C

文字列を書き出すには、 PrintStream クラスを見てください。意図したことを行うクラスの例 here を見ることができます。

また、 OutputStreamコンストラクターの1つ を使用してPrintStreamをラップできます。

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

[〜#〜] edit [〜#〜]PrintWriter も使用できることに注意してください上記のPrintStreamと同じ方法でクラスを作成します。これは通常、使用するエンコーディングを指定して、プラットフォームの依存関係を回避できるため、より優れています。

1
Jordão