我如何滥用Java';s MappedByteBuffer
我正在尝试用Java编写一个虚拟文件类。我认为下面的代码片段足够简单,可以看出问题所在。基本上,我必须在奇怪的地方强制我的缓冲区倒带(),这样我的示例才能工作(下面标记为对hugeHack()的调用)。我误解了在底层通道上使用seek和在缓冲区内定位。有人能告诉我我做错了什么吗。我很确定这是一些简单的误解。我希望避免使用hugeHack(),因为我的类是一个随机访问的数据结构,你不知道读写的顺序,我的测试在如何使用它方面是非常可预测和不现实的 以下是我的课堂摘录:我如何滥用Java';s MappedByteBuffer,java,nio,Java,Nio,我正在尝试用Java编写一个虚拟文件类。我认为下面的代码片段足够简单,可以看出问题所在。基本上,我必须在奇怪的地方强制我的缓冲区倒带(),这样我的示例才能工作(下面标记为对hugeHack()的调用)。我误解了在底层通道上使用seek和在缓冲区内定位。有人能告诉我我做错了什么吗。我很确定这是一些简单的误解。我希望避免使用hugeHack(),因为我的类是一个随机访问的数据结构,你不知道读写的顺序,我的测试在如何使用它方面是非常可预测和不现实的 以下是我的课堂摘录: public class Fi
public class FileStorageFloat64<U extends DoubleCoder & Allocatable<U>>
implements IndexedDataSource<U>, Allocatable<FileStorageFloat64<U>>
{
private final long numElements;
private final U type;
private final double[] tmpArray;
private final long byteCount;
private final File file;
private final RandomAccessFile raf;
private final FileChannel channel;
private final MappedByteBuffer buffer;
public FileStorageFloat64(long numElements, U type) {
this.numElements = numElements;
this.type = type.allocate();
this.tmpArray = new double[type.doubleCount()];
this.byteCount = numElements * type.doubleCount() * 8;
try {
this.file = File.createTempFile("Storage", ".storage");
this.file.deleteOnExit();
this.raf = new RandomAccessFile(file, "rw");
this.channel = raf.getChannel();
this.buffer = this.channel.map(MapMode.READ_WRITE, 0, this.byteCount);
for (long i = 0; i < this.byteCount; i++) {
this.buffer.put((byte)0);
}
this.buffer.rewind();
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
@Override
public void set(long index, U value) {
if (index < 0 || index >= numElements)
throw new IllegalArgumentException("storage index out of bounds");
synchronized(this) {
try {
value.toDoubleArray(this.tmpArray, 0);
long pos = index * this.type.doubleCount() * 8;
this.channel.position(pos);
for (int i = 0; i < this.tmpArray.length; i++) {
this.buffer.putDouble(this.tmpArray[i]);
}
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
@Override
public void get(long index, U value) {
if (index < 0 || index >= this.numElements)
throw new IllegalArgumentException("storage index out of bounds");
synchronized(this) {
try {
long pos = index * this.type.doubleCount() * 8;
this.channel.position(pos);
for (int i = 0; i < this.tmpArray.length; i++) {
this.tmpArray[i] = this.buffer.getDouble();
}
value.fromDoubleArray(this.tmpArray, 0);
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
public void hugeHack() {
this.buffer.rewind();
}
公共类文件存储浮动64
实现IndexedDataSource,可分配
{
私人最终长婚礼;
私人最终U型;
私人决赛双[]tmpArray;
私有最终长字节数;
私人最终文件;
私人最终文件raf;
专用最终文件通道;
私有最终MappedByteBuffer缓冲区;
公共文件存储浮动64(长数值,U型){
this.numElements=numElements;
this.type=type.allocate();
this.tmpArray=new double[type.doubleCount()];
this.byteCount=numElements*type.doubleCount()*8;
试一试{
this.file=file.createTempFile(“存储”,“存储”);
this.file.deleteOnExit();
this.raf=新的随机访问文件(文件“rw”);
this.channel=raf.getChannel();
this.buffer=this.channel.map(MapMode.READ\u WRITE,0,this.byteCount);
for(长i=0;i=数值)
抛出新的IllegalArgumentException(“存储索引超出范围”);
已同步(此){
试一试{
值.toDoubleArray(this.tmpArray,0);
long pos=index*this.type.doubleCount()*8;
本通道位置(pos);
for(int i=0;i=此数值)
抛出新的IllegalArgumentException(“存储索引超出范围”);
已同步(此){
试一试{
long pos=index*this.type.doubleCount()*8;
本通道位置(pos);
for(int i=0;i
下面是一个测试方法:
public void run() {
final int SIZE = 40;
ComplexFloat64Member v = new ComplexFloat64Member();
FileStorageFloat64<ComplexFloat64Member> store = new FileStorageFloat64<ComplexFloat64Member>(SIZE, new ComplexFloat64Member());
assertEquals(SIZE, store.size());
for (long i = 0; i < store.size(); i++) {
v.setR(i);
v.setI(i+1);
store.set(i, v);
}
store.hugeHack();
for (long i = 0; i < store.size(); i++) {
store.get(i, v);
assertEquals(i, v.r(), 0);
assertEquals(i+1, v.i(), 0);
}
store.hugeHack();
FileStorageFloat64<ComplexFloat64Member> dup = store.duplicate(); // not shown above
dup.hugeHack();
assertEquals(store.size(), dup.size());
for (long i = 0; i < dup.size(); i++) {
dup.get(i, v);
assertEquals(i, v.r(), 0);
assertEquals(i+1, v.i(), 0);
}
}
public void run(){
最终整数大小=40;
complexfloat64成员v=新的complexfloat64成员();
FileStorageFloat64 store=newfilestoragefloat64(大小,newcomplexfloat64member());
assertEquals(SIZE,store.SIZE());
用于(长i=0;i
好的,所以我昨天花了整整一天时间,找到了一个使用ByteBuffer的解决方案;只是没有映射ByteBuffer。它比我以前的RandomAccessFile方法快10到100倍。我现在可以说这已经足够好了
public class FileStorageFloat64<U extends DoubleCoder & Allocatable<U>>
implements IndexedDataSource<U>, Allocatable<FileStorageFloat64<U>>
{
private final long numElements;
private final U type;
private final double[] tmpArray;
private final int bufSize;
private final File file;
private final RandomAccessFile raf;
private final FileChannel channel;
private final ByteBuffer buffer;
/**
*
* @param numElements
* @param type
*/
public FileStorageFloat64(long numElements, U type) {
this.numElements = numElements;
this.type = type.allocate();
this.tmpArray = new double[type.doubleCount()];
this.bufSize = type.doubleCount() * 8;
try {
this.file = File.createTempFile("Storage", ".storage");
this.file.deleteOnExit();
this.raf = new RandomAccessFile(file, "rw");
this.channel = raf.getChannel();
// make a one element buffer
this.buffer = ByteBuffer.allocate(bufSize);
// fill the buffer with zeroes
for (int i = 0; i < type.doubleCount(); i++) {
buffer.putDouble(0);
}
// write zeroes to the file over and over
channel.position(0);
for (long i = 0; i < numElements; i++) {
channel.write(buffer);
}
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
@Override
public void set(long index, U value) {
if (index < 0 || index >= this.numElements)
throw new IllegalArgumentException("storage index out of bounds");
synchronized(this) {
try {
value.toDoubleArray(this.tmpArray, 0);
for (int i = 0; i < this.tmpArray.length; i++) {
this.buffer.putDouble(i*8, this.tmpArray[i]);
}
this.buffer.rewind();
long pos = index * this.bufSize;
this.channel.position(pos);
this.channel.write(this.buffer);
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
@Override
public void get(long index, U value) {
if (index < 0 || index >= this.numElements)
throw new IllegalArgumentException("storage index out of bounds");
synchronized(this) {
try {
buffer.rewind();
long pos = index * bufSize;
this.channel.position(pos);
this.channel.read(this.buffer);
for (int i = 0; i < this.tmpArray.length; i++) {
this.tmpArray[i] = this.buffer.getDouble(i*8);
}
value.fromDoubleArray(this.tmpArray, 0);
} catch (IOException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
}
公共类文件存储浮动64
实现IndexedDataSource,可分配
{
私人最终长婚礼;
私人最终U型;
私人决赛双[]tmpArray;
私人最终int bufSize;
私人最终文件;
私人最终文件raf;
专用最终文件通道;
专用最终字节缓冲区;
/**
*
*@param numElements
*@param类型
*/
公共文件存储浮动64(长数值,U型){
this.numElements=numElements;
this.type=type.allocate();
this.tmpArray=new double[type.doubleCount()];
this.bufSize=type.doubleCount()*8;
试一试{
this.file=file.createTempFile(“存储”,“存储”);
this.file.deleteOnExit();
this.raf=新的随机访问文件(文件“rw”);
this.channel=raf.getChannel();
//制作一个单元素缓冲区
this.buffer=ByteBuffer.allocate(bufSize);
//用零填充缓冲区
对于(int i=0;i