Got a functional version of BDF 3

This commit is contained in:
josua 2020-07-27 11:11:01 +10:00
parent 31e6b9b637
commit f73eb0454f
9 changed files with 180 additions and 149 deletions

View File

@ -1,10 +1,12 @@
package bdf.file; package bdf.file;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream; import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import bdf.data.BdfDatabase; import bdf.data.BdfDatabase;
import bdf.types.BdfObject; import bdf.types.BdfObject;
@ -65,7 +67,7 @@ public class BdfFileManager extends BdfReader
OutputStream out = new FileOutputStream(path); OutputStream out = new FileOutputStream(path);
if(compressed) { if(compressed) {
out = new DeflaterOutputStream(out); out = new GZIPOutputStream(out);
} }
// Write the database to the file // Write the database to the file

View File

@ -41,25 +41,13 @@ public class BdfArray implements IBdfType, Iterable<BdfObject>
} }
} }
public BdfObject createObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
return new BdfArray(lookupTable);
}
@Override @Override
public int serializeSeeker() public int serializeSeeker(int[] locations)
{ {
int size = 0; int size = 0;
for(BdfObject o : elements) { for(BdfObject o : elements) {
size += o.serializeSeeker(); size += o.serializeSeeker(locations);
size += 4; size += 4;
} }
@ -67,13 +55,13 @@ public class BdfArray implements IBdfType, Iterable<BdfObject>
} }
@Override @Override
public int serialize(IBdfDatabase database) public int serialize(IBdfDatabase database, int[] locations)
{ {
int pos = 0; int pos = 0;
for(BdfObject o : elements) for(BdfObject o : elements)
{ {
int size = o.serialize(database.getPointer(pos + 4)); int size = o.serialize(database.getPointer(pos + 4), locations);
database.setBytes(pos, DataHelpers.serializeInt(size)); database.setBytes(pos, DataHelpers.serializeInt(size));
pos += size; pos += size;
@ -191,4 +179,11 @@ public class BdfArray implements IBdfType, Iterable<BdfObject>
}; };
} }
@Override
public void getLocationUses(int[] locations) {
for(BdfObject element : elements) {
element.getLocationUses(locations);
}
}
} }

View File

@ -11,14 +11,18 @@ import bdf.util.DataHelpers;
class BdfLookupTable implements IBdfType class BdfLookupTable implements IBdfType
{ {
private ArrayList<byte[]> keys; private ArrayList<byte[]> keys;
private BdfReader reader;
BdfLookupTable() { BdfLookupTable(BdfReader reader)
keys = new ArrayList<byte[]>(); {
this.keys = new ArrayList<byte[]>();
this.reader = reader;
} }
BdfLookupTable(IBdfDatabase database) BdfLookupTable(BdfReader reader, IBdfDatabase database)
{ {
keys = new ArrayList<byte[]>(); this.keys = new ArrayList<byte[]>();
this.reader = reader;
for(int i=0;i<database.size();) for(int i=0;i<database.size();)
{ {
@ -49,12 +53,17 @@ class BdfLookupTable implements IBdfType
} }
@Override @Override
public int serialize(IBdfDatabase database) public int serialize(IBdfDatabase database, int[] locations)
{ {
int upto = 0; int upto = 0;
for(int i=0;i<keys.size();i++) for(int i=0;i<keys.size();i++)
{ {
// Skip this key if the location is unset (the key has been culled)
if(locations[i] == -1) {
continue;
}
byte[] key = keys.get(i); byte[] key = keys.get(i);
database.setBytes(upto + 4, key); database.setBytes(upto + 4, key);
@ -68,11 +77,17 @@ class BdfLookupTable implements IBdfType
} }
@Override @Override
public int serializeSeeker() public int serializeSeeker(int[] locations)
{ {
int size = 0; int size = 0;
for(int i=0;i<keys.size();i++) { for(int i=0;i<keys.size();i++)
{
// Skip this key if the location is unset (the key has been culled)
if(locations[i] == -1) {
continue;
}
size += keys.get(i).length; size += keys.get(i).length;
size += 4; size += 4;
} }
@ -80,7 +95,30 @@ class BdfLookupTable implements IBdfType
return size; return size;
} }
public int[] serializeGetLocations()
{
int[] locations = new int[keys.size()];
int next = 0;
reader.bdf.getLocationUses(locations);
for(int i=0;i<locations.length;i++) {
if(locations[i] > 0) {
locations[i] = next;
next += 1;
} else {
locations[i] = -1;
}
}
return locations;
}
@Override @Override
public void serializeHumanReadable(OutputStream stream, BdfIndent indent, int it) { public void serializeHumanReadable(OutputStream stream, BdfIndent indent, int it) {
} }
@Override
public void getLocationUses(int[] locations) {
}
} }

View File

@ -56,17 +56,17 @@ public class BdfNamedList implements IBdfType
} }
@Override @Override
public int serialize(IBdfDatabase database) public int serialize(IBdfDatabase database, int[] locations)
{ {
int pos = 0; int pos = 0;
for(Element o : elements) for(Element o : elements)
{ {
database.setBytes(pos, DataHelpers.serializeInt(o.key)); database.setBytes(pos, DataHelpers.serializeInt(locations[o.key]));
pos += 4; pos += 4;
int size = o.object.serialize(database.getPointer(pos + 4)); int size = o.object.serialize(database.getPointer(pos + 4), locations);
database.setBytes(pos, DataHelpers.serializeInt(size)); database.setBytes(pos, DataHelpers.serializeInt(size));
@ -78,14 +78,14 @@ public class BdfNamedList implements IBdfType
} }
@Override @Override
public int serializeSeeker() public int serializeSeeker(int[] locations)
{ {
int size = 0; int size = 0;
for(Element o : elements) for(Element o : elements)
{ {
size += 8; size += 8;
size += o.object.serializeSeeker(); size += o.object.serializeSeeker(locations);
} }
return size; return size;
@ -181,30 +181,6 @@ public class BdfNamedList implements IBdfType
return null; return null;
} }
public BdfNamedList remove(BdfObject bdf)
{
for(int i=0;i<elements.size();i++) {
if(elements.get(i).object == bdf) {
elements.remove(i);
i -= 1;
}
}
return this;
}
public BdfObject createObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
return new BdfArray(lookupTable);
}
public BdfNamedList set(String key, BdfObject object) public BdfNamedList set(String key, BdfObject object)
{ {
// Convert the key to bytes // Convert the key to bytes
@ -276,4 +252,13 @@ public class BdfNamedList implements IBdfType
public int size() { public int size() {
return elements.size(); return elements.size();
} }
@Override
public void getLocationUses(int[] locations)
{
for(Element e : elements) {
locations[e.key] += 1;
e.object.getLocationUses(locations);
}
}
} }

View File

@ -18,15 +18,13 @@ public class BdfObject implements IBdfType
BdfObject(BdfLookupTable lookupTable) { BdfObject(BdfLookupTable lookupTable) {
this.lookupTable = lookupTable; this.lookupTable = lookupTable;
this.database = new BdfDatabase(0);
} }
BdfObject(BdfLookupTable lookupTable, IBdfDatabase data) BdfObject(BdfLookupTable lookupTable, IBdfDatabase data)
{ {
this.lookupTable = lookupTable; this.lookupTable = lookupTable;
// Is the database length greater than 1
if(data.size() > 1)
{
// Get the type and database values // Get the type and database values
type = data.getByte(0); type = data.getByte(0);
database = data.getPointer(1, data.size() - 1); database = data.getPointer(1, data.size() - 1);
@ -41,15 +39,16 @@ public class BdfObject implements IBdfType
} }
} }
else @Override
public void getLocationUses(int[] locations)
{ {
// Create a new database if(type == BdfTypes.NAMED_LIST || type == BdfTypes.ARRAY) {
database = new BdfDatabase(0); ((IBdfType)object).getLocationUses(locations);
} }
} }
@Override @Override
public int serialize(IBdfDatabase database) public int serialize(IBdfDatabase database, int[] locations)
{ {
int size; int size;
@ -59,11 +58,11 @@ public class BdfObject implements IBdfType
switch(type) switch(type)
{ {
case BdfTypes.ARRAY: case BdfTypes.ARRAY:
size = ((BdfArray)object).serialize(db) + 1; size = ((BdfArray)object).serialize(db, locations) + 1;
break; break;
case BdfTypes.NAMED_LIST: case BdfTypes.NAMED_LIST:
size = ((BdfNamedList)object).serialize(db) + 1; size = ((BdfNamedList)object).serialize(db, locations) + 1;
break; break;
case BdfTypes.STRING: case BdfTypes.STRING:
@ -84,13 +83,13 @@ public class BdfObject implements IBdfType
} }
@Override @Override
public int serializeSeeker() public int serializeSeeker(int[] locations)
{ {
// Objects // Objects
switch(type) switch(type)
{ {
case BdfTypes.ARRAY: return ((BdfArray)object).serializeSeeker() + 1; case BdfTypes.ARRAY: return ((BdfArray)object).serializeSeeker(locations) + 1;
case BdfTypes.NAMED_LIST: return ((BdfNamedList)object).serializeSeeker() + 1; case BdfTypes.NAMED_LIST: return ((BdfNamedList)object).serializeSeeker(locations) + 1;
case BdfTypes.STRING: return ((String)object).getBytes().length + 1; case BdfTypes.STRING: return ((String)object).getBytes().length + 1;
} }
@ -158,7 +157,7 @@ public class BdfObject implements IBdfType
int[] array = this.getIntegerArray(); int[] array = this.getIntegerArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Integer.toString(array[i]) + "I").getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + Integer.toString(array[i]) + "I").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -169,7 +168,7 @@ public class BdfObject implements IBdfType
boolean[] array = this.getBooleanArray(); boolean[] array = this.getBooleanArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + (array[i] ? "true" : "false")).getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + (array[i] ? "true" : "false")).getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -180,7 +179,7 @@ public class BdfObject implements IBdfType
short[] array = this.getShortArray(); short[] array = this.getShortArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Short.toString(array[i]) + "S").getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + Short.toString(array[i]) + "S").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -191,7 +190,7 @@ public class BdfObject implements IBdfType
long[] array = this.getLongArray(); long[] array = this.getLongArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Long.toString(array[i]) + "L").getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + Long.toString(array[i]) + "L").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -202,7 +201,7 @@ public class BdfObject implements IBdfType
byte[] array = this.getByteArray(); byte[] array = this.getByteArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Byte.toString(array[i]) + "B").getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + Byte.toString(array[i]) + "B").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -213,7 +212,7 @@ public class BdfObject implements IBdfType
double[] array = this.getDoubleArray(); double[] array = this.getDoubleArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Double.toString(array[i]) + "D").getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + Double.toString(array[i]) + "D").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -224,7 +223,7 @@ public class BdfObject implements IBdfType
float[] array = this.getFloatArray(); float[] array = this.getFloatArray();
for(int i=0;i<array.length;i++) { for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Float.toString(array[i]) + "F").getBytes()); stream.write((indent.breaker + calcIndent(indent, it) + Float.toString(array[i]) + "F").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes()); if(i != array.length - 1) stream.write(", ".getBytes());
} }
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes()); stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break; break;
@ -448,7 +447,7 @@ public class BdfObject implements IBdfType
public BdfArray getArray() public BdfArray getArray()
{ {
if(this.type != BdfTypes.ARRAY) if(this.type != BdfTypes.ARRAY)
setArray(createArray()); setArray(newArray());
return (BdfArray)object; return (BdfArray)object;
} }
@ -456,7 +455,7 @@ public class BdfObject implements IBdfType
public BdfNamedList getNamedList() public BdfNamedList getNamedList()
{ {
if(this.type != BdfTypes.NAMED_LIST) if(this.type != BdfTypes.NAMED_LIST)
setNamedList(createNamedList()); setNamedList(newNamedList());
return (BdfNamedList)object; return (BdfNamedList)object;
} }
@ -533,15 +532,15 @@ public class BdfObject implements IBdfType
return this; return this;
} }
public BdfObject createObject() { public BdfObject newObject() {
return new BdfObject(lookupTable); return new BdfObject(lookupTable);
} }
public BdfNamedList createNamedList() { public BdfNamedList newNamedList() {
return new BdfNamedList(lookupTable); return new BdfNamedList(lookupTable);
} }
public BdfArray createArray() { public BdfArray newArray() {
return new BdfArray(lookupTable); return new BdfArray(lookupTable);
} }

View File

@ -13,69 +13,69 @@ public class BdfReader
protected BdfLookupTable lookupTable; protected BdfLookupTable lookupTable;
protected BdfObject bdf; protected BdfObject bdf;
public BdfReader() { private void initNew() {
lookupTable = new BdfLookupTable(); lookupTable = new BdfLookupTable(this);
bdf = new BdfObject(lookupTable); bdf = new BdfObject(lookupTable);
} }
public BdfReader() {
initNew();
}
public BdfReader(byte[] database) { public BdfReader(byte[] database) {
this(new BdfDatabase(database)); this(new BdfDatabase(database));
} }
public BdfReader(IBdfDatabase database) public BdfReader(IBdfDatabase database)
{ {
// Check the version of the BDF file if(database.size() < 4) {
if(!"BDF3".contentEquals(new String(database.getBytes(0, 4)))) { initNew();
lookupTable = new BdfLookupTable();
bdf = new BdfObject(lookupTable);
return; return;
} }
// Get the lookup table // Get the lookup table
int lookupTable_size = DataHelpers.getByteBuffer(database.getPointer(4, 4)).getInt(); int lookupTable_size = DataHelpers.getByteBuffer(database.getPointer(0, 4)).getInt();
lookupTable = new BdfLookupTable(database.getPointer(8, lookupTable_size)); lookupTable = new BdfLookupTable(this, database.getPointer(4, lookupTable_size));
// Get the rest of the data // Get the rest of the data
int upto = lookupTable_size + 8; int upto = lookupTable_size + 4;
int bdf_size = DataHelpers.getByteBuffer(database.getPointer(upto, 4)).getInt(); int bdf_size = DataHelpers.getByteBuffer(database.getPointer(upto, 4)).getInt();
bdf = new BdfObject(lookupTable, database.getPointer(upto + 4, bdf_size)); bdf = new BdfObject(lookupTable, database.getPointer(upto + 4, bdf_size));
} }
public BdfDatabase serialize() public BdfDatabase serialize()
{ {
int bdf_size = bdf.serializeSeeker(); int[] locations = lookupTable.serializeGetLocations();
int lookupTable_size = lookupTable.serializeSeeker();
int database_size = bdf_size + lookupTable_size + 12; int bdf_size = bdf.serializeSeeker(locations);
int lookupTable_size = lookupTable.serializeSeeker(locations);
int database_size = bdf_size + lookupTable_size + 8;
BdfDatabase database = new BdfDatabase(database_size); BdfDatabase database = new BdfDatabase(database_size);
database.setBytes(0, "BDF3".getBytes()); database.setBytes(0, DataHelpers.serializeInt(lookupTable_size));
database.setBytes(4, DataHelpers.serializeInt(lookupTable_size)); database.setBytes(4 + lookupTable_size, DataHelpers.serializeInt(bdf_size));
database.setBytes(8 + lookupTable_size, DataHelpers.serializeInt(bdf_size));
lookupTable.serialize(database.getPointer(8, lookupTable_size)); lookupTable.serialize(database.getPointer(4, lookupTable_size), locations);
bdf.serialize(database.getPointer(12 + lookupTable_size, database_size)); bdf.serialize(database.getPointer(8 + lookupTable_size, database_size), locations);
return database; return database;
} }
public BdfObject getBDF() { public BdfObject getObject() {
return bdf; return bdf;
} }
public String serializeHumanReadable(BdfIndent indent) { public BdfObject resetObject() {
return serializeHumanReadable(indent, 0); bdf = new BdfObject(lookupTable);
return bdf;
} }
public String serializeHumanReadable() { public String serializeHumanReadable(BdfIndent indent)
return serializeHumanReadable(new BdfIndent("", ""), 0);
}
public String serializeHumanReadable(BdfIndent indent, int it)
{ {
ByteArrayOutputStream stream = new ByteArrayOutputStream(); ByteArrayOutputStream stream = new ByteArrayOutputStream();
try { try {
bdf.serializeHumanReadable(stream, indent, it); bdf.serializeHumanReadable(stream, indent, 0);
return stream.toString(); return stream.toString();
} }
@ -84,23 +84,19 @@ public class BdfReader
} }
} }
public void serializeHumanReadable(OutputStream stream, BdfIndent indent) throws IOException { public String serializeHumanReadable() {
return serializeHumanReadable(new BdfIndent("", ""));
}
public void serializeHumanReadable(OutputStream stream, BdfIndent indent) throws IOException
{
bdf.serializeHumanReadable(stream, indent, 0); bdf.serializeHumanReadable(stream, indent, 0);
stream.write('\n');
stream.flush();
} }
public void serializeHumanReadable(OutputStream stream) throws IOException { public void serializeHumanReadable(OutputStream stream) throws IOException {
bdf.serializeHumanReadable(stream, new BdfIndent("", ""), 0); serializeHumanReadable(stream, new BdfIndent("", ""));
}
public BdfObject createObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
return new BdfArray(lookupTable);
} }
} }

View File

@ -7,8 +7,9 @@ import bdf.data.IBdfDatabase;
interface IBdfType interface IBdfType
{ {
int serialize(IBdfDatabase database); void getLocationUses(int[] locations);
int serializeSeeker(); int serialize(IBdfDatabase database, int[] locations);
int serializeSeeker(int[] locations);
void serializeHumanReadable(OutputStream stream, BdfIndent indent, int it) throws IOException; void serializeHumanReadable(OutputStream stream, BdfIndent indent, int it) throws IOException;
} }

View File

@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream; import java.util.zip.InflaterInputStream;
public class FileHelpers public class FileHelpers
@ -50,7 +51,7 @@ public class FileHelpers
public static byte[] readAllCompressed(String path) throws IOException public static byte[] readAllCompressed(String path) throws IOException
{ {
// Create the file input stream // Create the file input stream
InflaterInputStream in = new InflaterInputStream(new FileInputStream(path)); GZIPInputStream in = new GZIPInputStream(new FileInputStream(path));
// Load all of its data // Load all of its data
byte[] data = readAll(in); byte[] data = readAll(in);

View File

@ -8,21 +8,10 @@ import bdf.types.BdfNamedList;
import bdf.types.BdfObject; import bdf.types.BdfObject;
import bdf.types.BdfReader; import bdf.types.BdfReader;
public class Tests { public class Tests
{
public static void main(String[] args) throws InterruptedException, IOException static void displayHex(IBdfDatabase db)
{ {
BdfReader reader = new BdfReader();
BdfObject bdf = reader.getBDF();
BdfNamedList nl = bdf.getNamedList();
nl.set("hello", nl.createObject().setInteger(69));
nl.set("world", nl.createObject().setString("👋"));
nl.set("👋", nl.createObject().setArray(nl.createArray()));
reader.serializeHumanReadable(System.out);
System.out.println();
IBdfDatabase db = reader.serialize();
char[] hex_chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; char[] hex_chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
for(int i=0;i<db.size();i++) for(int i=0;i<db.size();i++)
@ -36,10 +25,35 @@ public class Tests {
} }
System.out.println(); System.out.println();
}
public static void main(String[] args) throws InterruptedException, IOException
{
BdfReader reader = new BdfReader();
BdfObject bdf = reader.getObject();
BdfNamedList nl = bdf.newNamedList();
bdf.setNamedList(nl);
nl.set("Hello, ", bdf.newObject().setInteger(69));
nl.set("world!", bdf.newObject().setInteger(420));
nl.remove("Hello, ");
reader.serializeHumanReadable(System.out);
IBdfDatabase db = reader.serialize();
displayHex(db);
reader = new BdfReader(db); reader = new BdfReader(db);
reader.serializeHumanReadable(System.out);
reader.getObject().setArray(bdf.newArray());
db = reader.serialize();
displayHex(db);
reader.serializeHumanReadable(System.out); reader.serializeHumanReadable(System.out);
System.out.println();
} }
} }