รับ OutputStream เป็นสตริง


580

วิธีที่ดีที่สุดในการไพพ์เอาต์พุตจาก java.io.OutputStream ไปยัง String ใน Java คืออะไร

พูดว่าฉันมีวิธีการ:

  writeToStream(Object o, OutputStream out)

ซึ่งเขียนข้อมูลบางอย่างจากวัตถุไปยังกระแสที่กำหนด อย่างไรก็ตามฉันต้องการเอาท์พุทนี้เข้าไปใน String ได้อย่างง่ายดายที่สุด

ฉันกำลังพิจารณาเขียนชั้นเรียนเช่นนี้ (ยังไม่ทดลอง):

class StringOutputStream extends OutputStream {

  StringBuilder mBuf;

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

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

แต่จะมีวิธีที่ดีกว่า ฉันต้องการทดสอบเท่านั้น!


6
คุณมีเพียง ASCII ไบต์หรือไม่ คุณไม่ต้องการเพจรหัสหรือไม่?
Horcrux7

ในกรณีนี้ใช่ อย่างไรก็ตามจุดที่ดี - ฉันไม่ได้คิดเกี่ยวกับมัน
Adrian Mouat

คำตอบ:


607

ByteArrayOutputStreamฉันจะใช้ และเมื่อเสร็จแล้วคุณสามารถโทร:

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

หรือดีกว่า:

baos.toString( codepage );

สำหรับStringคอนสตรัคที่codepageอาจจะเป็นStringหรือเป็นตัวอย่างของjava.nio.charset.Charset ค่าที่เป็นไปได้คือjava.nio.charset.StandardCharsets.UTF_8 java.nio.charset.StandardCharsets.UTF_8

วิธีการtoString()ยอมรับเฉพาะStringเป็นcodepageพารามิเตอร์ (ยืนจาวา 8)


8
ByteArrayOutputStream ไม่มีเมธอด toArray () มันต้อง toByteArray () แม้ว่า คุณสามารถแก้ไขคำตอบได้ไหม? นอกจากนี้ทำไมไม่ใช้ baos.toString (String charsetName) ซึ่งจะง่ายกว่าเล็กน้อย
Jonik

35
bytearray เป็นเพียงข้อมูลไบนารี เนื่องจากข้อความ (unicode) สามารถเข้ารหัสแบบไบนารีได้หลายวิธี ByteArrayOutputStream จำเป็นต้องรู้ว่าการเข้ารหัสใดที่ใช้ในการเข้ารหัสไบต์ดังนั้นจึงสามารถใช้การเข้ารหัสเดียวกันเพื่อถอดรหัสไบต์เป็นสตริงอีกครั้ง การใช้ toString เพียงอย่างเดียวโดยไม่มีการโต้เถียงนั้นไม่ฉลาดเท่าที่คุณจะเพิกเฉยต่อปัญหาแทนการแก้ปัญหา Java จะใช้การเข้ารหัสแพลตฟอร์มซึ่งอาจถูกต้อง ... หรือไม่ มันเป็นการสุ่มโดยทั่วไป คุณจำเป็นต้องค้นหาว่าการเข้ารหัสใดที่ใช้ในการเขียนข้อความไปยังไบต์และส่งการเข้ารหัสนั้นไปที่ toString
Stijn de Witt

10
เพียงคำอธิบายเกี่ยวกับ codepage ที่อ้างถึงที่นี่: ใน Java คุณสามารถใช้ Charset.defaultCharset () หรือ Charset.forName ("charset เฉพาะ"); สิ่งที่ใช้ได้ผลสำหรับฉันคือ: String ใหม่ (baos.toByteArray (), Charset.defaultCharset ());
Wallace Brown

7
@ WallaceBrown ใช้defaultCharsetไม่ดีไปกว่าชุดอักขระทั้งหมด - คุณจำเป็นต้องค้นหาว่ามันคืออะไรก่อนที่คุณจะใช้toString
artbristol

4
StandardCharsets.UTF_8เป็นไม่ได้Charset Stringนอกจากนี้พารามิเตอร์ที่เรียกว่าไม่charsetName codepage
OrangeDog

46

ฉันชอบห้องสมุด Apache Commons IO ลองดูที่รุ่นของByteArrayOutputStreamซึ่งมีวิธีการเช่นเดียวกับtoString(String enc) toByteArray()การใช้ส่วนประกอบที่มีอยู่และเชื่อถือได้เช่นโครงการคอมมอนส์ช่วยให้โค้ดของคุณเล็กลงและง่ายต่อการขยายและจัดวางใหม่


10
ช่วยชีวิตตัวเองหนึ่งปีและอ่านผ่าน APIs ทั่วไปทั้งหมดดังนั้นเมื่อคุณพบปัญหาคุณสามารถปลดปล่อยโซลูชันที่ผ่านการทดสอบอย่างสมบูรณ์และเป็นเจ้าของชุมชน
Bob Herrmann

15
อืมฉันเป็นผู้ใช้ Apache Commons ตัวยง แต่ในกรณีนี้ฉันล้มเหลวที่จะดูว่าทำไมคุณควรใช้ ByteArrayOutputStream ของ Commons IO แทน java.io.ByteArrayOutrayStream ของ JDK หลังยังมีเมธอด toString (String charsetName) และ toByteArray () สนใจที่จะทำอย่างละเอียด?
Jonik

1
ใช่เนื่องจากบริบทดั้งเดิมเป็นวิธีที่ดีกว่าในการสตรีมและแยกเนื้อหาฉันจึงรวมตัวอย่าง Commons IO เนื่องจากรวมวิธีการ 'write (InputStream)' สำหรับกลไกที่ไม่ได้กำหนด / มีข้อสงสัยสำหรับการบรรจุ OutputStream ฉันจะไปกับ JDK ด้วย
Joe Liversedge

23

มันใช้งานได้ดี

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();
    }
};

วิธีการโทร = >> marshaller.marshal( (Object) toWrite , (OutputStream) output);

จากนั้นเพื่อพิมพ์สตริงหรือรับมันเพียงแค่อ้างอิงกระแส "เอาท์พุท" ตัวเองเป็นตัวอย่างในการพิมพ์สตริงออกไป console = >> System.out.println(output);

FYI: การเรียกใช้เมธอดของฉันmarshaller.marshal(Object,Outputstream)สำหรับการทำงานกับ XML มันไม่เกี่ยวข้องกับหัวข้อนี้

นี่เป็นเรื่องสิ้นเปลืองอย่างมากสำหรับการใช้งานอย่างมีประสิทธิภาพมีวิธีการแปลงมากเกินไปและหลวมไปหน่อย นี่เป็นรหัสที่พิสูจน์ให้คุณเห็นว่าเป็นไปได้โดยสิ้นเชิงที่จะสร้าง OuputStream ที่กำหนดเองและส่งออกสตริง แต่ไปทาง Horcrux7 และทุกอย่างก็ดีมีเพียงสองวิธี

และโลกมีชีวิตอยู่ในวันอื่น ....


9
เพียงแค่เลือกไบต์เพื่อถ่านจะทำงานบน ascii เท่านั้น ใช้ ByteArrayOutputStream เหมือน Horcrux7
Dave Ray

2
ตกลงกับเดฟเรย์ คุณไม่สามารถสรุปได้ว่าไบต์ของคุณเป็นอักขระ ASCII คุณต้องตีความไบต์โดยใช้การเข้ารหัส ใช้ byteArrayOutputStream.toString ("UTF-8") หรือสตริงใหม่ (byteArrayOutputStream.toByteArray (), "UTF-8")
Martin Dow

16

นี่คือสิ่งที่ฉันทำ:

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());
}

ByteArrayOutputStreamในกรณีที่ระบบปฏิบัติการเป็น


2
@JavaJigs ฉันชี้แจงสิ่งนี้ที่ด้านล่างของคำตอบของฉันเกือบ 5 ปีที่แล้ว :)
Adrian Mouat

19
พิจารณาเปลี่ยนด้วย"UTF-8" StandardCharsets.UTF_8
james.garriss

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.