2012-11-20 16 views
2

我正在實現一個需要使用GZIP對日誌消息進行編碼並通過UDP將其發送出去的日誌記錄系統。GZIP和UDP的最快捷方式Java中的大量字符串

到目前爲止,我已經得到了什麼是:

初始化:

DatagramSocket sock = new DatagramSocket(); 
baos = new ByteArrayOutputStream(); 
printStream = new PrintStream(new GZIPOutputStream(baos)); 

然後這爲PrintStream穿出記錄儀 - 消息將通過它

那麼每次消息到達到達:

byte[] d = baos.toByteArray(); 
DatagramPacket dp = new DatagramPacket(d,d.length,host,port); 
sock.send(dp); 

目前困擾我的是我無法找到從ByteArrayOutputStream(toByteArray()只需要一個副本)中刪除數據的方式,我擔心每次重新創建所有三個流對象都會效率低下。

有什麼方法可以從流中刪除發送的數據?或者我應該完全朝另一個方向看?

+1

注意:如果字符串很短,如果GZIPed它們會更大。 –

回答

0

給出的答案與我的問題等方面有幫助,但對於實際的問題 - 有一種方法從一個ByteArrayOutputStream清除數據。它有一個reset()方法。它實際上並不清除緩衝區,但它將count屬性重置爲0,導致它忽略已存在於緩衝區中的任何數據。

注意:重新底層ByteArrayOutputStream後寫入GZIPOutputStream會產生錯誤,所以我還沒有找到一種方法來重用的一切。

1

您必須爲每條消息創建一個新的流;否則,每次撥打toByteArray()都會再次發送之前的所有消息。

一個更好的方法可能是包裝一個TCP套接字的OutputStreamGZIPOutputStream

printStream = new PrintStream(new GZIPOutputStream(sock.getOutputStream())); 

也不要忘記刷新每個消息或什麼也不會發生後PrintStream

如果速度真的很重要,你應該考慮使用DatagramChannel,而不是舊(慢)蒸汽API。這應該讓你開始:

ByteBuffer buffer = ByteBuffer.allocate(1000); 
ByteBufferOutputStream bufferOutput = new ByteBufferOutputStream(buffer); 
GZIPOutputStream output = new GZIPOutputStream(bufferOutput); 
OutputStreamWriter writer = new OutputStreamWriter(output, "UTF-8"); 
writer.write("log message\n"); 
writer.close(); 

sock.getChannel().open(); // do this once 
sock.getChannel().write(buffer); // Send compressed data 

注意:您可以通過它倒帶重用buffer但所有的流必須按照消息創建一次。

1

如果速度很重要,那麼使用GZIP將會有所幫助。 (這會增加一些延遲)

public static void main(String... args) throws IOException { 
    test("Hello World"); 
    test("Nov 20, 2012 4:55:11 PM Main main\n" + 
      "INFO: Hello World log message"); 
} 

private static void test(String s) throws IOException { 
    byte[] bytes = s.getBytes("UTF-8"); 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    GZIPOutputStream outputStream = new GZIPOutputStream(baos); 
    outputStream.write(bytes); 
    outputStream.close(); 
    byte[] bytes2 = baos.toByteArray(); 
    System.out.println("'" + s + "' raw.length=" + bytes.length + " gzip.length=" + bytes2.length); 
} 

打印

'Hello World' raw.length=11 gzip.length=31 
'Nov 20, 2012 4:55:11 PM Main main 
INFO: Hello World log message' raw.length=63 gzip.length=80 
+0

GZIP在這裏不是我的決定。我將日誌消息發送給Graylog,這會強制GZIP和UDP。 –

+0

GZIP兼容性合理。如果你能找到一種方法,日誌條目分批將dramtaically提高效率結合起來。 BTW DeflatorOutputStream具有小得多的頁眉/頁腳,如果這是對未來的選擇。 –

相關問題