将压缩的 FlatBuffer 写入文件并从文件中读回的问题
Issues with writing compressed FlatBuffer to file and reading back from file
我已经成功地将 FlatBuffer 数据写入文件,并且可以从文件中读回。但是现在我试图在写入文件之前压缩 Flatbuffer 数据。当我尝试从文件中读回压缩数据并解压缩时,它不起作用。
任何帮助将不胜感激,因为我是平面缓冲区和 java 压缩的新手。
** FlatBuffer 架构**
table employees {
persons:[Person];
}
table Person {
fname:string;
mname:string;
lname:string;
age:short;
}
MainActivity.java
package com.irteqa.flatbufferdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.google.flatbuffers.FlatBufferBuilder;
import fb.Person;
import fb.employees;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "FlatBufferDemo";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createBinaryData();
}
public void createBinaryData() {
List<PersonEntity> personEntityList = new ArrayList<>();
for (int i = 0; i < 1; i++) {
PersonEntity personEntity = new PersonEntity("Stephen" + (i + 1), "Wardell", "Curry", (short) (i + 1));
personEntityList.add(personEntity);
}
writeBinaryData(personEntityList);
// ************************************************************************
// Reading Data
// ************************************************************************
String filepath = getFilesDir() + "/person.dat";
ByteBuffer buffer = null;
// ByteBuffer buffer = readByteBufferfromFile(filepath);
try {
byte[] bytesComp = readBytesFromFile(filepath);
buffer = CompressionUtil.decompress(bytesComp);
} catch (IOException e) {
e.printStackTrace();
}
// Get access to the root:
employees all_employees = employees.getRootAsemployees(buffer);
// Note: We did not set the `mana` field explicitly, so we get back the default value.
Log.d(TAG, "reading ByteBuffer: ");
for (int i = 0; i < all_employees.personsVector().length(); i++) {
Person person = all_employees.persons(i);
Log.d(TAG, person.fname() + " " + person.mname() + " " + person.lname() + " " + person.age());
}
}
private ByteBuffer readByteBufferfromFile(String filepath) {
ByteBuffer buffer = null;
try (RandomAccessFile aFile = new RandomAccessFile(filepath, "r");
FileChannel inChannel = aFile.getChannel();) {
long fileSize = inChannel.size();
//Create buffer of the file size
buffer = ByteBuffer.allocate((int) fileSize);
inChannel.read(buffer);
buffer.flip();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
private void writeBinaryData(List<PersonEntity> personEntityList) {
Log.d(TAG, "Writing ByteBuffer: ");
FlatBufferBuilder builder = new FlatBufferBuilder(0);
int[] persons = new int[personEntityList.size()];
for (int i = 0; i < personEntityList.size(); i++) {
PersonEntity ent = personEntityList.get(i);
int fnameOffset = builder.createString(ent.fname);
int mnameOffset = builder.createString(ent.mname);
int lnameOffset = builder.createString(ent.lname);
short age = ent.age;
persons[i] = Person.createPerson(builder
, fnameOffset
, mnameOffset
, lnameOffset
, age);
}
int personsVector = employees.createPersonsVector(builder, persons);
employees.startemployees(builder);
employees.addPersons(builder, personsVector);
int orc = employees.endemployees(builder);
builder.finish(orc);
ByteBuffer buf = builder.dataBuffer();
String filepath = getFilesDir() + "/person.dat";
// writeByteBuffertoFile(buf, filepath); // writing ByteBuffer wihtout compression
// compress and write to file
try {
byte[] bytesCompressed = CompressionUtil.compress(buf);
writeBytestoFile(bytesCompressed, filepath);
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeBytestoFile(byte[] bytesCompressed, String outputFile) {
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
outputStream.write(bytesCompressed);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeByteBuffertoFile(ByteBuffer buf, String filepath) {
FileChannel fc = null;
try {
File file = new File(filepath);
fc = new FileOutputStream(file).getChannel();
fc.write(buf);
fc.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] readBytesFromFile(String file) throws IOException {
File f = new File(file);
// work only for 2GB file, because array index can only upto Integer.MAX
byte[] buffer = new byte[(int) f.length()];
FileInputStream is = new FileInputStream(file);
is.read(buffer);
is.close();
return buffer;
}
}
** CompressionUtil **
package com.irteqa.flatbufferdemo;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class CompressionUtil {
public static byte[] compress(ByteBuffer buffer) throws IOException {
byte[] bytes = buffer.array();
ByteArrayOutputStream os = new ByteArrayOutputStream(bytes.length);
GZIPOutputStream gos = new GZIPOutputStream(os);
gos.write(bytes);
gos.close();
byte[] compressed = os.toByteArray();
os.close();
return compressed;
}
public static ByteBuffer decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 1024;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
byte[] data = new byte[BUFFER_SIZE];
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE*2);
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
buffer.put(data, 0 , bytesRead);
}
gis.close();
is.close();
return buffer;
}
}
我收到以下错误:
2022-05-24 10:24:56.238 4231-4231/com.irteqa.flatbufferdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.irteqa.flatbufferdemo, PID: 4231
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.irteqa.flatbufferdemo/com.irteqa.flatbufferdemo.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int fb.Person$Vector.length()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int fb.Person$Vector.length()' on a null object reference
at com.irteqa.flatbufferdemo.MainActivity.createBinaryData(MainActivity.java:68)
at com.irteqa.flatbufferdemo.MainActivity.onCreate(MainActivity.java:35)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
2022-05-24 10:29:56.401 4231-4231/com.irteqa.flatbufferdemo I/Process: Sending signal. PID: 4231 SIG: 9
看起来你正在将 ByteBuffer
压缩到平面缓冲区,而不是从 0 开始。最好序列化你从 builder.sizedByteArray()
.
我已经成功地将 FlatBuffer 数据写入文件,并且可以从文件中读回。但是现在我试图在写入文件之前压缩 Flatbuffer 数据。当我尝试从文件中读回压缩数据并解压缩时,它不起作用。
任何帮助将不胜感激,因为我是平面缓冲区和 java 压缩的新手。
** FlatBuffer 架构**
table employees {
persons:[Person];
}
table Person {
fname:string;
mname:string;
lname:string;
age:short;
}
MainActivity.java
package com.irteqa.flatbufferdemo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.google.flatbuffers.FlatBufferBuilder;
import fb.Person;
import fb.employees;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "FlatBufferDemo";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
createBinaryData();
}
public void createBinaryData() {
List<PersonEntity> personEntityList = new ArrayList<>();
for (int i = 0; i < 1; i++) {
PersonEntity personEntity = new PersonEntity("Stephen" + (i + 1), "Wardell", "Curry", (short) (i + 1));
personEntityList.add(personEntity);
}
writeBinaryData(personEntityList);
// ************************************************************************
// Reading Data
// ************************************************************************
String filepath = getFilesDir() + "/person.dat";
ByteBuffer buffer = null;
// ByteBuffer buffer = readByteBufferfromFile(filepath);
try {
byte[] bytesComp = readBytesFromFile(filepath);
buffer = CompressionUtil.decompress(bytesComp);
} catch (IOException e) {
e.printStackTrace();
}
// Get access to the root:
employees all_employees = employees.getRootAsemployees(buffer);
// Note: We did not set the `mana` field explicitly, so we get back the default value.
Log.d(TAG, "reading ByteBuffer: ");
for (int i = 0; i < all_employees.personsVector().length(); i++) {
Person person = all_employees.persons(i);
Log.d(TAG, person.fname() + " " + person.mname() + " " + person.lname() + " " + person.age());
}
}
private ByteBuffer readByteBufferfromFile(String filepath) {
ByteBuffer buffer = null;
try (RandomAccessFile aFile = new RandomAccessFile(filepath, "r");
FileChannel inChannel = aFile.getChannel();) {
long fileSize = inChannel.size();
//Create buffer of the file size
buffer = ByteBuffer.allocate((int) fileSize);
inChannel.read(buffer);
buffer.flip();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
private void writeBinaryData(List<PersonEntity> personEntityList) {
Log.d(TAG, "Writing ByteBuffer: ");
FlatBufferBuilder builder = new FlatBufferBuilder(0);
int[] persons = new int[personEntityList.size()];
for (int i = 0; i < personEntityList.size(); i++) {
PersonEntity ent = personEntityList.get(i);
int fnameOffset = builder.createString(ent.fname);
int mnameOffset = builder.createString(ent.mname);
int lnameOffset = builder.createString(ent.lname);
short age = ent.age;
persons[i] = Person.createPerson(builder
, fnameOffset
, mnameOffset
, lnameOffset
, age);
}
int personsVector = employees.createPersonsVector(builder, persons);
employees.startemployees(builder);
employees.addPersons(builder, personsVector);
int orc = employees.endemployees(builder);
builder.finish(orc);
ByteBuffer buf = builder.dataBuffer();
String filepath = getFilesDir() + "/person.dat";
// writeByteBuffertoFile(buf, filepath); // writing ByteBuffer wihtout compression
// compress and write to file
try {
byte[] bytesCompressed = CompressionUtil.compress(buf);
writeBytestoFile(bytesCompressed, filepath);
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeBytestoFile(byte[] bytesCompressed, String outputFile) {
try (FileOutputStream outputStream = new FileOutputStream(outputFile)) {
outputStream.write(bytesCompressed);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeByteBuffertoFile(ByteBuffer buf, String filepath) {
FileChannel fc = null;
try {
File file = new File(filepath);
fc = new FileOutputStream(file).getChannel();
fc.write(buf);
fc.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static byte[] readBytesFromFile(String file) throws IOException {
File f = new File(file);
// work only for 2GB file, because array index can only upto Integer.MAX
byte[] buffer = new byte[(int) f.length()];
FileInputStream is = new FileInputStream(file);
is.read(buffer);
is.close();
return buffer;
}
}
** CompressionUtil **
package com.irteqa.flatbufferdemo;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class CompressionUtil {
public static byte[] compress(ByteBuffer buffer) throws IOException {
byte[] bytes = buffer.array();
ByteArrayOutputStream os = new ByteArrayOutputStream(bytes.length);
GZIPOutputStream gos = new GZIPOutputStream(os);
gos.write(bytes);
gos.close();
byte[] compressed = os.toByteArray();
os.close();
return compressed;
}
public static ByteBuffer decompress(byte[] compressed) throws IOException {
final int BUFFER_SIZE = 1024;
ByteArrayInputStream is = new ByteArrayInputStream(compressed);
GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
byte[] data = new byte[BUFFER_SIZE];
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE*2);
int bytesRead;
while ((bytesRead = gis.read(data)) != -1) {
buffer.put(data, 0 , bytesRead);
}
gis.close();
is.close();
return buffer;
}
}
我收到以下错误:
2022-05-24 10:24:56.238 4231-4231/com.irteqa.flatbufferdemo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.irteqa.flatbufferdemo, PID: 4231
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.irteqa.flatbufferdemo/com.irteqa.flatbufferdemo.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int fb.Person$Vector.length()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int fb.Person$Vector.length()' on a null object reference
at com.irteqa.flatbufferdemo.MainActivity.createBinaryData(MainActivity.java:68)
at com.irteqa.flatbufferdemo.MainActivity.onCreate(MainActivity.java:35)
at android.app.Activity.performCreate(Activity.java:6237)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
2022-05-24 10:29:56.401 4231-4231/com.irteqa.flatbufferdemo I/Process: Sending signal. PID: 4231 SIG: 9
看起来你正在将 ByteBuffer
压缩到平面缓冲区,而不是从 0 开始。最好序列化你从 builder.sizedByteArray()
.