如何在Java中以位级精度读写文件
我对文件的读写有点陌生
我想以位级的精度读写文件。i、 e.读取缓冲区中与写入完全相同的位数
以下是我的尝试:
1)写入文件方法
private static final int INT_BYTES = Integer.SIZE / Byte.SIZE;
public void writeToFile(FileChannel fc, BitSet bitSet, int intId ) throws IOException
{
//each bitSet has a intId, first two int bytes written will have intId and bitSet.length() and rest will have content of bitSet
int byteLenOfBitSet=(int)Math.ceil((bitSet.length/8.0));
ByteBuffer bf = ByteBuffer.allocate(byteLenOfBitSet + 2*(INT_BYTES));
bf.putInt(intId); //put the Id
bf.putInt(bitSet.length(); // put the bit length, it would be used during read
bf.put(bitSet) //FIXME this is wrong, need to put bits , bf.put() put bytes
bf.flip();
fc.write(bf);
}
2)从文件读取方法
public Result readFromFile(FileChannel fc) throws IOException
{
long currentPos = fc.position();
ByteBuffer bf = ByteBuffer.allocate(2* INT_BYTES);
if(fc.read(bf) < 0)return null;
bf.rewind();
int intId=bf.getInt(); //read first int as intId
int bitLen = bf.getInt(); //read second int as bitLen to read further from file
int byteLen=(int)Math.ceil((bitLen/8.0)); //FIXME not so sure
//move fc read position ahead by 2 INT_BYTES to read bitSet
fc.position((currentPos + INT_BYTES * 2));
bf = ByteBuffer.allocate(byteLen);//FIXME, this is wrong, we need to somehow get bit not in bytelen , don't want unnecessarily read entire byte if there is less than 8 bit of info to read
if(fc.read(bf) < 0)return null;
bf.rewind();
BitSet readBitSet = new BitSet();
//TODO, then read each bit from bf to a readBitSet
// and return result with intId+readBitSet
}
在另一组方法中,我只能读写整数(字节级),我使用类似于上面的逻辑使它工作良好。但是,我被困在了一个水平
如果需要更多澄清,请告诉我
它可能类似于Read and write file bit by bit 但这个答案是针对Perl的,我正在寻找Java实现
编辑
我的担忧:
因为数据是这样写入文件的
2 INT_BYTES then bitSet example: 5 3 101
2 INT_BYTES then bitSet example: 2 10 1010111101
我担心在尝试读取第一个bitSet
时可能会读取第二个2 INT_BYTES
,因此我的第一个结果位集可能是错误的。所以,想知道如何确保位级边界得到维护。i、 e.我只想在读取第一个位集时读取到第一个位集的长度
# 1 楼答案
This answer包括一个具有
toByteArray
方法的位集子类。要编写,可以从该方法获取byte[]
数组,并使用ByteBuffer.put(byte[])
(ByteBuffer docs)。要读取,可以使用get()
,然后在byte[]
上循环并重建位集(供参考:FileChannel docs)
编辑回答你的question below
我认为你可以摆脱
fc.position
,因为fc.read
和bf.getInt
都提升了他们目前的地位根据this answer,
allocate
的参数应该是您希望通过调用fc.read
读取的字节数。所以2*INT_BYTES
对于第一个allocate
调用看起来是正确的。第二个allocate
看起来也不错;不要打电话给fc.position
对于
byteLen
,请尝试byteLen=(bitLen >> 3) + ((bitLen&0x07)?1:0)
bitLen>>3
除以8(2^3)并截断。所以1。。7位为零,8。。15.有一个。如果位的数量不是8的倍数,则需要再增加一个字节((bitLen&0x07)?1:0)
在这种情况下为1,否则为0请记住,如果没有8的倍数,那么位将在末尾填充。例如,读取12位将占用流中的两个完整字节