Bir String'e OutputStream Alın


580

Çıktıyı bir java.io.OutputStream öğesinden Java'da bir String'e aktarmanın en iyi yolu nedir?

Diyelim ki yöntemim var:

  writeToStream(Object o, OutputStream out)

Bu, belirli verileri nesneden verilen akışa yazar. Ancak, bu çıktıyı mümkün olduğunca kolay bir dize almak istiyorum.

Ben böyle bir sınıf yazmayı düşünüyorum (denenmemiş):

class StringOutputStream extends OutputStream {

  StringBuilder mBuf;

  public void write(int byte) throws IOException {
    mBuf.append((char) byte);
  }

  public String getString() {
    return mBuf.toString();
  }
}

Ama daha iyi bir yol var mı? Sadece bir test yapmak istiyorum!


6
Yalnızca ASCII baytınız var mı? Kod sayfasına ihtiyacınız yok mu?
Horcrux7

Bu durumda, evet. Ancak, iyi bir nokta - bunu düşünmemiştim.
Adrian Mouat

Yanıtlar:


607

Ben a ByteArrayOutputStream. Ve bittiğinde şunları arayabilirsiniz:

new String( baos.toByteArray(), codepage );

ya da daha iyisi:

baos.toString( codepage );

İçin Stringkurucu, codepagebir olabilir Stringya da bir örneğini java.nio.charset.Charset . Olası bir değer java.nio.charset.StandardCharsets.UTF_8'dir .

Yöntem toString()yalnızca a'yı parametre Stringolarak kabul eder codepage(stand Java 8).


8
ByteArrayOutputStream öğesinde toArray () yöntemi yoktur; gerçi toByteArray () var. Cevabı düzeltebilir misiniz? Ayrıca, neden biraz daha basit olan baos.toString (String charsetName) kullanmıyorsunuz?
Jonik

35
Bir bytearray sadece ikili verilerdir. (Unicode) metin birçok farklı şekilde ikili olarak kodlanabildiğinden, ByteArrayOutputStream öğesinin baytları kodlamak için hangi kodlamanın kullanıldığını bilmesi gerekir, böylece baytları bir dizeye tekrar kodunu çözmek için aynı kodlamayı kullanabilir. Sadece bir argüman olmadan toString kullanmak sorunu çözmek yerine sadece görmezden gelmek akıllıca değildir; Java, doğru olabilecek platform kodlamasını kullanır ... ya da kullanmaz. Temelde rastgele. Metni baytlara yazmak ve bu kodlamayı toString'e geçirmek için hangi kodlamanın kullanıldığını bulmanız gerekir.
Stijn de Witt

10
Sadece burada referans verilen kod sayfasında bir açıklama: Java'da Charset.defaultCharset () veya Charset.forName ("belirli karakter kümesi") kullanabilirsiniz; Benim için işe yarayan şuydu: new String (baos.toByteArray (), Charset.defaultCharset ());
Wallace Brown

7
@WallaceBrown kullanarak defaultCharsetkarakter kümesini tamamen görmezden gelmekten daha iyi değildir - kullanmadan önce ne olduğunu bulmanız gerekirtoString
artbristol

4
StandardCharsets.UTF_8bir Charset, değil bir String. Dahası, parametre çağrılır charsetName, değil codepage.
OrangeDog

46

Apache Commons IO kütüphanesini seviyorum. Bir yöntemi de olan ByteArrayOutputStream sürümüne bir göz atın . Commons projesi gibi mevcut ve güvenilir bileşenleri kullanmak, kodunuzun daha küçük olmasını ve genişletilmesi ve yeniden kullanılması daha kolay olmasını sağlar.toString(String enc)toByteArray()


10
Bir yıl boyunca kendinizi kurtarın ve tüm ortak API'ları okuyun, böylece bir sorunla karşılaştığınızda tamamen test edilmiş ve topluluğa ait bir çözüm ortaya çıkarabilirsiniz.
Bob Herrmann

15
Hmm, hevesli bir Apache Commons kullanıcısıyım, ancak bu durumda neden JDK'nın kendi java.io.ByteArrayOutputStream yerine Commons IO'nun ByteArrayOutputStream öğesini kullanmanız gerektiğini göremiyorum. İkincisi ayrıca toString (String charsetName) ve toByteArray () yöntemlerini sağlar. Ayrıntılı düşünmek ister misiniz?
Jonik

1
Evet, orijinal içerik içeriği yayınlamak ve ayıklamak için daha iyi bir yol olduğundan, Commons IO örneğini ekledim, çünkü OutputStream'i doldurmak için tanımlanmamış / şüpheli bir mekanizma için 'write (InputStream)' yöntemi içeriyordu. Ben de JDK ile giderdim.
Joe Liversedge

23

Bu güzel çalıştı

OutputStream output = new OutputStream() {
    private StringBuilder string = new StringBuilder();

    @Override
    public void write(int b) throws IOException {
        this.string.append((char) b );
    }

    //Netbeans IDE automatically overrides this toString()
    public String toString() {
        return this.string.toString();
    }
};

yöntem çağrısı = >> marshaller.marshal( (Object) toWrite , (OutputStream) output);

sonra dize yazdırmak veya sadece "çıktı" akış kendisine başvurmak örnek olarak, dizeyi console = >> yazdırmak için System.out.println(output);

FYI: Benim yöntem çağrım marshaller.marshal(Object,Outputstream)XML ile çalışmak için. Bu konuyla alakasız.

Bu, üretim kullanımı için son derece israf, çok fazla dönüşüm var ve biraz gevşek. Bu, size özel bir OuputStream oluşturmanın ve bir dize çıkarmanın tamamen mümkün olduğunu kanıtlamak için kodlandı. Ama sadece Horcrux7 yoluna gidin ve sadece iki yöntem çağrısı ile her şey iyidir.

Ve dünya başka bir günde yaşıyor ....


9
Sadece bir bayt char için sadece ascii üzerinde çalışacaktır. Horcrux7 gibi
Dave

2
Dave Ray ile aynı fikirde. Baytınızın bir ASCII karakteri olduğunu varsayamazsınız. Baytları bir kodlama kullanarak yorumlamanız gerekir. ByteArrayOutputStream.toString ("UTF-8") veya yeni Dize (byteArrayOutputStream.toByteArray (), "UTF-8") kullanın.
Martin Dow

16

İşte yaptığım şey:

Obj.writeToStream(toWrite, os);
try {
    String out = new String(os.toByteArray(), "UTF-8");
    assertTrue(out.contains("testString"));
} catch (UnsupportedEncondingException e) {
    fail("Caught exception: " + e.getMessage());
}

OS bir olduğunda ByteArrayOutputStream.


2
@JavaJigs Bunu yaklaşık 5 yıl önce cevabımın alt kısmında açıklığa kavuştum :)
Adrian Mouat

19
Değiştirmeyi düşünün "UTF-8"ile StandardCharsets.UTF_8.
james.garriss

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.