2013-08-29 31 views
6

Tôi muốn viết một CharSequence để OutputStream bằng cách sử dụng một CharSet được chỉ định. Về cơ bản những gì một Writer được khởi tạo với cùng CharSet sẽ làm, khi viết (String) được gọi.Làm thế nào để mã hóa một CharSequence bằng cách sử dụng một CharSet (không chuyển đổi thành String)

Bắt là, có nhiều CharSequences được viết và một số là khá lớn. Để làm phức tạp hơn, mọi thứ có thể được ghi vào nhiều OutputStream. Tôi có thể dễ dàng thực hiện điều đó bằng cách sử dụng (thực sự tôi hiện đã thực hiện nó theo cách đó):

byte[] rawBytes = CharSequence.toString().getBytes(CharSet) 
for (OutputStream out : outputTargets) { 
    out.write(rawBytes); 
} 

Nhưng rõ ràng là String là một đối tượng rác hoàn toàn không mong muốn ở đây, như là mảng byte []. Tôi đang tìm một phương pháp cho phép tôi thực hiện mã hóa trực tiếp mà không cần các đối tượng trung gian. Đáng ngạc nhiên điều này dường như là không thể - ở khắp mọi nơi tôi nhìn vào JRE, nơi một CharSequence được chấp nhận nó được nhanh chóng chuyển đổi thành một String trước khi bất kỳ công việc được thực hiện.

Hầu hết (tất cả?) Của công việc chuyển đổi cho CharSet dường như được thực hiện trong các lớp ngoài công lập, vì vậy tôi không tìm thấy cách nào để truy cập vào bất kỳ cách nào một cách minh bạch và hợp pháp.

Làm thế nào để có thể tránh được rác/các cơ sở mã hóa Charlet của JRE được sử dụng trực tiếp?

+0

xem CharsetEncoder – ZhongYu

Trả lời

6

Lặp lại các ký tự của chuỗi và ghi chúng vào một người viết.

OutputStream outputStream = .... 
CharSequence charSequence = .... 
Charset charset = .... 

Writer writer = new OutputStreamWriter(outputStream, charset); 

for (int i = 0; i < charSequence.length(); i++) { 
    writer.write(charSequence.charAt(i)); 
} 
+0

Tôi không muốn làm điều này (vì nó đòi hỏi tôi phải thực hiện một số thay đổi thiết kế), nhưng sau một số người nghĩ rằng đây có vẻ là phương pháp đơn giản nhất nhưng hiệu quả cộng hưởng (nếu ai quan tâm đến OutputStreams) được đệm). – Durandal

5

Bạn có thể sử dụng Charset để mã hóa một CharSequence đến một mảng byte:

private static byte[] encodeUtf8(CharSequence cs) { 
    ByteBuffer bb = Charset.forName("UTF-8").encode(CharBuffer.wrap(cs)); 
    byte[] result = new byte[bb.remaining()]; 
    bb.get(result); 
    return result; 
} 

Nếu, thay vì OutputStream, bạn đang sử dụng một thể hiện của WritableByteChannel, phương pháp write nó mất ByteBuffer trực tiếp, vì vậy bạn thậm chí không cần sao chép bộ đệm byte vào mảng byte trước tiên.

+1

Tôi tin rằng OP muốn tránh tạo một mảng byte trong bộ nhớ cho toàn bộ chuỗi. Hãy tưởng tượng rằng CharSequence lớn gấp 10 lần RAM có sẵn. Trong trường hợp đó, phương pháp này sẽ không hoạt động, phải không? – Keith

+1

Đó là điểm công bằng và trường hợp sử dụng tốt cho giải pháp của bạn (+1). –

+0

CharSequences của tôi thường không phải là tất cả những gì lớn (một vài K, nhưng chúng thường xuyên và nó tạo ra rất nhiều rác dư thừa). Ngoài ra còn có mũ cứng do phương thức length() trả về một int, ngăn không cho nó đại diện cho một textfile lớn như CharSequence. Ý tưởng với CharBuffer.wrap(), trong khi tôi sẽ không sử dụng nó cho vấn đề cụ thể này có thể hữu ích trong các tình huống khác. – Durandal

Các vấn đề liên quan