1

I am using below code to creating a copy of mdb file in memory but its giving null pointer exception on DatabaseBuilder constructor that no file exist, what i want is to create a copy of this manipulate it and return the copy to outputstream.

File tmp = new File("test.mdb");

FileChannel channel = MemFileChannel.newChannel(tmp,DatabaseImpl.RW_CHANNEL_MODE);

FileUtils.copyFile(file , tmp);

Database db = new DatabaseBuilder(tmp).setChannel(channel).open();

Haider
  • 615
  • 1
  • 16
  • 38
  • 1
    if you specify test.mdb in this way, you have to place the file correctly. E.g. if you run it from command line, the file must be in the current working directory. If you are trying to run it from eclipse or maven the directory where it searches it is the java project directory. – m4gic Aug 31 '18 at 15:35
  • @m4gic i want to create test.mdb in memory the object file is the physical file present in the resource folder which is loading correctly – Haider Aug 31 '18 at 18:57
  • `DatabaseBuilder` also has a constructor with no arguments. Have you tried `new DatabaseBuilder().setChannel ...` ...? – Gord Thompson Sep 10 '18 at 13:42
  • @GordThompson then its says empty database file , if i remove the cahnnel creation code and write new DatabaseBuilder(tmp).open() than all is ok which is what i am using now – Haider Sep 10 '18 at 13:46
  • When you say "the physical file present in the resource folder" do you intend to distribute the database as part of an executable jar file and want to open an in-memory copy of the database when you run your app? – Gord Thompson Sep 10 '18 at 14:19
  • @GordThompson what i want was to create a copy of mdb in memory and perform the insertion on that file and return the file to the server output stream without creating physical file – Haider Sep 10 '18 at 14:25
  • Try using `Class#getResourceAsStream` to open the reference file as an InputStream, then use something like `Database db = new DatabaseBuilder().setChannel(MemFileChannel.newChannel(dbResourceStream)).open())` -- that works for me. – Gord Thompson Sep 10 '18 at 15:04
  • @GordThompson will try that , and any any how to copy the channel to servletoutputstream because db.getFile() is null because we are not using physical file i think – Haider Sep 10 '18 at 17:13
  • After making the changes to the in-memory database, try using [MemFileChannel#transferTo](http://jackcess.sourceforge.net/apidocs/com/healthmarketscience/jackcess/util/MemFileChannel.html#transferTo(java.io.OutputStream)) to copy the channel to an OutputStream. – Gord Thompson Sep 10 '18 at 18:05
  • @GordThompson great can you please post it as an answer so i can accept it – Haider Sep 10 '18 at 18:11

1 Answers1

2

So you have a pre-made Access database file as a resource in your project. You can open an in-memory copy of that database with Jackcess by first using Class#getResourceAsStream to open the resource ...

final String dbResourcePath = "/embedded.accdb";
@SuppressWarnings("rawtypes")
Class thisClass = JackcessTestMain.class;  // my "main" class
InputStream dbResourceStream = null;
// for running from executable jar 
dbResourceStream = thisClass.getResourceAsStream("/resources" + dbResourcePath);
if (dbResourceStream == null) {
    // for running inside the Eclipse IDE
    dbResourceStream = thisClass.getResourceAsStream(dbResourcePath);
}

... pass that InputStream to a Jackcess MemFileChannel ...

MemFileChannel mfc = MemFileChannel.newChannel(dbResourceStream);

... and then use DatabaseBuilder to open the Database from the channel:

Database db = new DatabaseBuilder().setChannel(mfc).open()

When finished making changes to the in-memory copy of the database you can send the contents of the channel to an OutputStream. For example,

db.close();
FileOutputStream fos = new FileOutputStream("C:/Users/Public/zzz.accdb");
mfc.transferTo(fos);
fos.close();
Gord Thompson
  • 116,920
  • 32
  • 215
  • 418