2012-09-24 4 views
6

In einem Servlet baue ich eine sehr große Menge an HTML-Inhalt in einem StringBuilder, die am Ende in den PrintWriter der Antwort geschrieben werden muss. Um einen PrintWriter zu verwenden, muss zuerst die toString() - Methode von StringBuilder aufgerufen werden, um den Inhalt als String abzurufen. Dies verdoppelt den Inhalt unnötig. Gibt es eine Möglichkeit, direkt aus dem StringBuilder zu schreiben, da er den Inhalt bereits enthält?Schreiben Sie einen StringBuilder in einen Writer ohne toString()

PrintWriter kann eine CharSequence akzeptieren, aber die Dokumentation besagt, dass es die toString() der CharSequence aufruft, also hilft es nicht wirklich.

Die einzige klare Möglichkeit, die ich sehen kann, ist die charAt (i) -Methode von StringBuilder, um ein Zeichen zu einem Zeitpunkt zu erhalten und zu schreiben, aber wäre dies eine Verbesserung?

+2

Verbesserung ist relativ. Wenn Ihr Ziel ist, den Speicherverbrauch zu reduzieren, dann wäre es ja eine Verbesserung. Sie sollten testen, ob es langsamer ist. Ich wäre nicht überrascht, wenn die Performance-Strafe aufgrund der Pufferung des Ausgabestroms gar nicht so groß wäre. –

Antwort

7

Als Alternative könnten Sie den StringBuilder löschen und eine StringWriter und eine PrintWriter verwenden.

+0

Ich muss den HTML-Inhalt nehmen und ihn in den PrintWriter des Servlets schreiben, der durch Aufruf der Methode getWriter() von HttpServletResponse erhalten wird. Ich sehe keine Möglichkeit, dies mit einem StringWriter zu kombinieren. – worpet

2

Sie könnten nur auf die Printwriter an erster Stelle schreiben und nicht auf das String ...

charAt verwenden würde auf jeden Fall nicht helfen. Es würde sehr schlechte Leistung erbringen, um es so zu machen. Wenn Sie wirklich wollen in dieser Richtung gehen Sie könnte verwenden Sie die StringBuilder.subString(start,end) Methode. Mit dieser Methode können Sie beispielsweise jeweils 1000 Zeichen gleichzeitig lesen und sie an den PrintWriter senden.

+0

'StringBuildersubstring()' wird bei jedem Aufruf einen neuen String zuweisen. Obwohl die Gesamtmenge des zugewiesenen Speichers kleiner ist, verursacht dies viel Overhead. Ich würde tatsächlich denken, dass die Verwendung von charAt() nicht so schlecht sein wird, weil der PrintWriter des Servlets wahrscheinlich sowieso gepuffert ist. –

2

Die Klasse StringBuilder speichert die Zeichenfolge in einem internen char-Array. Das Problem ist, dass auf dieses char-Array nicht zugegriffen werden kann.

Vorgeschlagene Lösungen:

1) Sie können eine neue Klasse erweitern ObjectOutputStream, in dem Sie die writeObjectOverride(Object obj) Methode überschreiben erstellen. Dann serialisieren Sie einfach die StringBuilder Instanz, in der Sie Ihr HTML-Dokument erstellt haben. Ihre überschriebene writeObjectOverride(Object obj) Methode wird mit dem internen Char-Array des Stringbuilder aufgerufen, das Teil des Serialisierungsprozesses ist, und voila: Sie haben den Verweis auf das interne char-Array des String-Builders, es gehört Ihnen, es in den PrintWriter des Servlets zu schreiben Ausgabe ... Hinweis: Ihre writeObjectOverride() Methode wird mehrmals aufgerufen werden, natürlich können Sie diejenigen ignorieren, die Ihnen etwas anderes als die gewünschte Char-Array übergeben.

2) Sie könnten die CharBuffer Klasse anstelle von StringBuilder verwenden, die Methode hat, die das interne Array zurückgibt. CharBuffer hat nicht so viele append (oder Put) Operationen als StringBuilder, so würde es erfordern diejenigen ein wenig (je nachdem, was Sie brauchen, genau) ...

3) Sie schreiben Sie Ihre eigenen Implementierung könnte zu verlängern StringBuilder, oder vielmehr, was Sie daraus verwenden. Auf diese Weise hätten Sie Zugriff auf das Objekt (beispielsweise ein Char-Array), in dem Sie den zusammengesetzten Text speichern ...

+0

Ich bin nicht sicher, Lösung 1 würde funktionieren, weil Sie WriteObjectOverride verwenden müssen Sie die meisten der Serialisierungslogik neu schreiben, weil der ObjectOutputStream-Konstruktor mit einem Parameter den Aufruf von WriteObjectOverride deaktiviert. d. h. es ist nicht dafür ausgelegt, auf diese Weise verwendet zu werden. Außerdem gibt es keine anderen Methoden, die Sie in writeObjectOverride aufrufen könnten, um den Normalfall zu behandeln. Sie könnten zwar eine Reflexion verwenden, aber der Sicherheitsmanager könnte Sie behindern. – cquezel

Verwandte Themen