2010-02-01 2 views
2

Каков наилучший способ записи размера определенных объектов по мере их сериализации? Например, если объекты типа A, B, C сериализованы, запишите размер их сериализованных байтов. Мы можем получить размер всего графа объектов через getBytes, но мы хотели бы разбить его на то, что является самым большим вкладом в общий размер сериализованного размера.Записывать размер объектов по мере их сериализации?

ObjectOutputStream предлагает writeObjectOverride, но мы не хотим переписывать процесс сериализации. В упрощенных терминах нам нужно знать, когда мы сталкиваемся с определенным объектом до сериализации, записываем общее количество байтов текущего байта, а затем после его сериализации учитываем разницу в байтах. Похоже, что использование writeSerialData будет работать, но метод является закрытым.

Идеи?

Спасибо.

--- UPDATE ---

ответы/предложения ниже проницательные. Ниже я до сих пор. Дайте мне знать, что вы думаете. Благодарю.

// extend to get a handle on outputstream  
MyObjectOutputStream extends ObjectOutputStream { 
    private OutputStream out; 

    public MyObjectOutputStream(out) { 
     super(out); 
     this.out = out; 
    }  

    public OutputStream getOut() { 
     return this.out; 
    } 
} 


// counter 
public static class CounterOutputStream extends FilterOutputStream { 
    private int bytesWritten = 0; 
    ...  
    public int getBytesWritten() { 
     return this.bytesWritten; 
    } 

    public void resetCounter() { 
     bytesWritten = 0; 
    } 

    private void update(int len) { 
     bytesWritten += len; 
    } 
} 

// go serialize  
ByteArrayOutputStream out = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new MyObjectOutputStream(new CounterOutputStream(out, 1024)); 


// record serialized size of this class; do this for every interested class 
public class MyInterestingObject { 
... 
    private void writeObject(ObjectOutputStream out) throws IOException { 
     CounterOutputStream counter = null; 
     if (out instanceof MyObjectOutputStream) { 
      counter = (CounterOutputStream)((MyObjectOutputStream)out).getOut(); 
      counter.resetCounter(); 
     } 

     // continue w/ standard serialization of this object 
     out.defaultWriteObject(); 

     if (counter != null) { 
      logger.info(this.getClass() + " bytes written: " + counter.getBytesWritten());  
     // TODO: store in context or somewhere to be aggregated post-serialization 
     } 
    } 
} 
+0

Укажите, к какому языку программирования вы говорите, и отметьте соответствующим образом. – unwind

+0

Предположительно это Java, поскольку он сказал 'writeSerialData',' ObjectOutputStream', 'getBytes' и' writeObjectOverride'. Я помечаю это сейчас. –

+0

К сожалению, извинения. Да, Java. – cwall

ответ

2

Самым простым решением было бы обернуть OutputStream вы используете с реализацией, которая будет рассчитывать записанных байтов.

import java.io.IOException; 
import java.io.OutputStream; 

public class CountingOutputStream extends OutputStream { 
    private int count; 
    private OutputStream out; 

    public CountingOutputStream(OutputStream out) { 
     this.out = out; 
    } 

    public void write(byte[] b) throws IOException { 
     out.write(b); 
     count += b.length; 
    } 

    public void write(byte[] b, int off, int len) throws IOException { 
     out.write(b, off, len); 
     count += len; 
    } 

    public void flush() throws IOException { 
     out.flush();  
    } 

    public void close() throws IOException { 
     out.close(); 
    } 

    public void write(int b) throws IOException { 
     out.write(b); 
     count++; 
    } 

    public int getBytesWritten() { 
     return count; 
    } 
} 

Тогда вы бы просто использовать, что

CountingOutputStream s = new CountingOutputStream(out); 
ObjectOutputStream o = new ObjectOutputStream(s); 
o.write(new Object()); 
o.close(); 
// s.getBytesWritten() 
+1

Подсчет байтов довольно прямолинейный, но мне не хватает того, как это определяет, какой объект мы пишем. – cwall

+0

Эта оболочка может где-то регистрироваться: ссылка и класс объекта с частичным размером. Если он использует структуру, подобную дереву, она может записывать «этот объект пишет от X до Y байтов». Это накопленный размер объекта. Если вы вычтите размер внутренних объектов (объекты, сериализованные между X и Y, это объекты между writeObject начинаются и заканчиваются), вы имеете размер сети объекта. :) Надеюсь, поможет! – helios

+0

Конечно, вам нужно использовать унаследованный объект ObjectOutputStream. Потому что он использует свой собственный writeObject для сериализации под-объектов. – helios

0

Вы могли бы реализовать Externalizable, а не Сериализуемый на любых объектах, которые необходимо захватить такие данные. Затем вы можете реализовать подсчет байтов по каждому полю в методе writeExternal, возможно, передав его в класс утилиты. Что-то вроде

public void writeExternal(ObjectOutput out) throws IOException 
{ 
    super.writeExternal(out); 
    out.writeUTF(this.myString == null ? "" : this.myString); 
    ByteCounter.getInstance().log("MyClass", "myString", this.myString); 
} 

Другого хакома пути будет придерживаться Сериализуемым, но использовать readResolve или writeReplace крючки, чтобы захватить все данные, что вам нужно, например,

public class Test implements Serializable 
{ 
    private String s; 

    public Test(String s) 
    { 
     this.s = s; 
    } 

    private Object readResolve() 
    { 
     System.err.format("%s,%s,%s,%d\n", "readResolve", "Test", "s", s.length()); 
     return this; 
    } 

    private Object writeReplace() 
    { 
     System.err.format("%s,%s,%s,%d\n", "writeReplace", "Test", "s", s.length()); 
     return this; 
    } 

    public static void main(String[] args) throws Exception 
    { 
     File tmp = File.createTempFile("foo", "tmp"); 
     ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(tmp)); 
     Test test = new Test("hello world"); 
     out.writeObject(test); 
     out.close(); 
     ObjectInputStream in = new ObjectInputStream(new FileInputStream(tmp)); 
     test = (Test)in.readObject(); 
     in.close(); 
    } 
} 
+0

Интересная идея. Благодарю. Я посмотрю. По общему признанию, я удивлен, что нет встроенного механизма, например callbacks с ограничительными привилегиями, для мониторинга сериализации по умолчанию. Externalizable - это вариант, но требует осуществления тяжелой атлетики, что является более чем необходимо для этого варианта использования. – cwall

Смежные вопросы