使用 Jackcess 和 JCIFS 来操作 SMB 共享上的 Access 数据库
Using Jackcess with JCIFS to manipulate an Access database on an SMB share
我需要使用 Jackcess 在 Java 中处理 MS Access 文件。该文件位于 SMB 共享上,因此我假设我必须使用 JCIFS。
我试过了
String testdirectory = "smb://" + "file location";
SmbFile testsmbdir = null;
try{
testsmbdir = new SmbFile(testdirectory,auth);
}catch(Exception e){
e.printStackTrace();
}
SmbFileInputStream smbFilestream = new SmbFileInputStream(testsmbdir);
db = DatabaseBuilder.open(testsmbdir);
但是,它说 SMBFile 无法转换为
的文件
db = DatabaseBuilder.open(testsmbdir)"
行。另外,如果我尝试使用 "smbFilestream",它会说它也无法将 SmbFileInputStream 转换为 File。
我必须将文件复制到本地机器还是完全不同的东西?如果我该怎么办?
(顺便说一下,我是 windows 用户。我只是将我的应用程序转换为 Mac,如果我的行话不对,很抱歉。)
在回复 Jackcess 论坛 here 上的一个帖子时,James 建议
it should be relatively straightforward to implement a version of FileChannel which works with a SmbRandomAccessFile
我刚刚在 Eclipse 中名为 smb4jackcess
的 Maven 项目中尝试了它,并且无需编写太多代码就可以正常工作。我创建的 class 被命名为 SmbFileChannel
:
// FileChannel using jcifs.smb.SmbRandomAccessFile
package smb4jackcess;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbRandomAccessFile;
public class SmbFileChannel extends FileChannel {
private final SmbRandomAccessFile _file;
private long _length;
public SmbFileChannel(String smbURL) throws SmbException, MalformedURLException, UnknownHostException {
_file = new SmbRandomAccessFile(smbURL, "rw", SmbFile.FILE_NO_SHARE);
_length = _file.length();
}
@Override
public void force(boolean metaData) throws SmbException, MalformedURLException, UnknownHostException {
// do nothing
}
@Override
public FileLock lock(long position, long size, boolean shared) {
throw new UnsupportedOperationException();
}
@Override
public MappedByteBuffer map(MapMode mode, long position, long size) {
throw new UnsupportedOperationException();
}
@Override
public long position() throws SmbException {
return _file.getFilePointer();
}
@Override
public FileChannel position(long newPosition) throws SmbException {
_file.seek(newPosition);
return this;
}
@Override
public int read(ByteBuffer dst) {
throw new UnsupportedOperationException();
}
@Override
public int read(ByteBuffer dst, long position) throws SmbException {
byte[] b = new byte[dst.remaining()];
_file.seek(position);
int bytesRead =_file.read(b);
dst.put(b);
return bytesRead;
}
@Override
public long read(ByteBuffer[] dsts, int offset, int length) {
throw new UnsupportedOperationException();
}
@Override
public long size() throws SmbException {
return _length;
}
@Override
public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException {
ByteBuffer bb = ByteBuffer.allocate((int)count);
int bytesWritten = src.read(bb);
bb.rewind();
bb.limit(bytesWritten);
this.write(bb, position);
return bytesWritten;
}
@Override
public long transferTo(long position, long count, WritableByteChannel target) {
throw new UnsupportedOperationException();
}
@Override
public FileChannel truncate(long newSize) throws SmbException {
if (newSize < 0L) {
throw new IllegalArgumentException("negative size");
}
_file.setLength(newSize);
_length = newSize;
return this;
}
@Override
public FileLock tryLock(long position, long size, boolean shared) {
throw new UnsupportedOperationException();
}
@Override
public int write(ByteBuffer src) throws SmbException {
throw new UnsupportedOperationException();
}
@Override
public int write(ByteBuffer src, long position) throws SmbException {
byte[] b = new byte[src.remaining()];
src.get(b);
_file.seek(position);
_file.write(b);
long endPos = position + b.length;
if(endPos > _length) {
_length = endPos;
}
return b.length;
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length) {
throw new UnsupportedOperationException();
}
@Override
protected void implCloseChannel() throws SmbException {
_file.close();
}
}
我使用的主要class是
package smb4jackcess;
import java.nio.channels.FileChannel;
import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.ColumnBuilder;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Database.FileFormat;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.IndexBuilder;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.TableBuilder;
public class Smb4jackcessMain {
public static void main(String[] args) {
String smbURL = "smb://gord:mypassword@SERVERNAME/sharename/etc/newdb.accdb";
try (SmbFileChannel sfc = new SmbFileChannel(smbURL)) {
// create a brand new database file
Database db = new DatabaseBuilder()
.setChannel(sfc)
.setFileFormat(FileFormat.V2010)
.create();
// add a table to it
Table newTable = new TableBuilder("NewTable")
.addColumn(new ColumnBuilder("ID", DataType.LONG)
.setAutoNumber(true))
.addColumn(new ColumnBuilder("TextField", DataType.TEXT))
.addIndex(new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME)
.addColumns("ID").setPrimaryKey())
.toTable(db);
// insert a row into the table
newTable.addRow(Column.AUTO_NUMBER, "This is a new row.");
db.close();
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
2016-02-04 更新: 代码改进。非常感谢 Dell Boomi 的 James 提供的帮助!
我需要使用 Jackcess 在 Java 中处理 MS Access 文件。该文件位于 SMB 共享上,因此我假设我必须使用 JCIFS。
我试过了
String testdirectory = "smb://" + "file location";
SmbFile testsmbdir = null;
try{
testsmbdir = new SmbFile(testdirectory,auth);
}catch(Exception e){
e.printStackTrace();
}
SmbFileInputStream smbFilestream = new SmbFileInputStream(testsmbdir);
db = DatabaseBuilder.open(testsmbdir);
但是,它说 SMBFile 无法转换为
的文件db = DatabaseBuilder.open(testsmbdir)"
行。另外,如果我尝试使用 "smbFilestream",它会说它也无法将 SmbFileInputStream 转换为 File。
我必须将文件复制到本地机器还是完全不同的东西?如果我该怎么办?
(顺便说一下,我是 windows 用户。我只是将我的应用程序转换为 Mac,如果我的行话不对,很抱歉。)
在回复 Jackcess 论坛 here 上的一个帖子时,James 建议
it should be relatively straightforward to implement a version of FileChannel which works with a SmbRandomAccessFile
我刚刚在 Eclipse 中名为 smb4jackcess
的 Maven 项目中尝试了它,并且无需编写太多代码就可以正常工作。我创建的 class 被命名为 SmbFileChannel
:
// FileChannel using jcifs.smb.SmbRandomAccessFile
package smb4jackcess;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbRandomAccessFile;
public class SmbFileChannel extends FileChannel {
private final SmbRandomAccessFile _file;
private long _length;
public SmbFileChannel(String smbURL) throws SmbException, MalformedURLException, UnknownHostException {
_file = new SmbRandomAccessFile(smbURL, "rw", SmbFile.FILE_NO_SHARE);
_length = _file.length();
}
@Override
public void force(boolean metaData) throws SmbException, MalformedURLException, UnknownHostException {
// do nothing
}
@Override
public FileLock lock(long position, long size, boolean shared) {
throw new UnsupportedOperationException();
}
@Override
public MappedByteBuffer map(MapMode mode, long position, long size) {
throw new UnsupportedOperationException();
}
@Override
public long position() throws SmbException {
return _file.getFilePointer();
}
@Override
public FileChannel position(long newPosition) throws SmbException {
_file.seek(newPosition);
return this;
}
@Override
public int read(ByteBuffer dst) {
throw new UnsupportedOperationException();
}
@Override
public int read(ByteBuffer dst, long position) throws SmbException {
byte[] b = new byte[dst.remaining()];
_file.seek(position);
int bytesRead =_file.read(b);
dst.put(b);
return bytesRead;
}
@Override
public long read(ByteBuffer[] dsts, int offset, int length) {
throw new UnsupportedOperationException();
}
@Override
public long size() throws SmbException {
return _length;
}
@Override
public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException {
ByteBuffer bb = ByteBuffer.allocate((int)count);
int bytesWritten = src.read(bb);
bb.rewind();
bb.limit(bytesWritten);
this.write(bb, position);
return bytesWritten;
}
@Override
public long transferTo(long position, long count, WritableByteChannel target) {
throw new UnsupportedOperationException();
}
@Override
public FileChannel truncate(long newSize) throws SmbException {
if (newSize < 0L) {
throw new IllegalArgumentException("negative size");
}
_file.setLength(newSize);
_length = newSize;
return this;
}
@Override
public FileLock tryLock(long position, long size, boolean shared) {
throw new UnsupportedOperationException();
}
@Override
public int write(ByteBuffer src) throws SmbException {
throw new UnsupportedOperationException();
}
@Override
public int write(ByteBuffer src, long position) throws SmbException {
byte[] b = new byte[src.remaining()];
src.get(b);
_file.seek(position);
_file.write(b);
long endPos = position + b.length;
if(endPos > _length) {
_length = endPos;
}
return b.length;
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length) {
throw new UnsupportedOperationException();
}
@Override
protected void implCloseChannel() throws SmbException {
_file.close();
}
}
我使用的主要class是
package smb4jackcess;
import java.nio.channels.FileChannel;
import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.ColumnBuilder;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Database.FileFormat;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.IndexBuilder;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.TableBuilder;
public class Smb4jackcessMain {
public static void main(String[] args) {
String smbURL = "smb://gord:mypassword@SERVERNAME/sharename/etc/newdb.accdb";
try (SmbFileChannel sfc = new SmbFileChannel(smbURL)) {
// create a brand new database file
Database db = new DatabaseBuilder()
.setChannel(sfc)
.setFileFormat(FileFormat.V2010)
.create();
// add a table to it
Table newTable = new TableBuilder("NewTable")
.addColumn(new ColumnBuilder("ID", DataType.LONG)
.setAutoNumber(true))
.addColumn(new ColumnBuilder("TextField", DataType.TEXT))
.addIndex(new IndexBuilder(IndexBuilder.PRIMARY_KEY_NAME)
.addColumns("ID").setPrimaryKey())
.toTable(db);
// insert a row into the table
newTable.addRow(Column.AUTO_NUMBER, "This is a new row.");
db.close();
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
2016-02-04 更新: 代码改进。非常感谢 Dell Boomi 的 James 提供的帮助!