1

我对 Javolution 有以下实现:

public class RunScan extends Struct
{
    public final Signed32 numOfClusters = new Signed32();
    public final ClusterData[] clusters;
    public final Signed32 numOfRecons = new Signed32();
    public final ReconData[] recons ;

    public RunScan (int numOfClusters, int numOfRecons)
    {
        this.numOfClusters.set(numOfClusters);
        this.numOfRecons.set(numOfRecons);
        clusters = array(new ClusterData[numOfClusters]);
        recons = array(new ReconData[numOfRecons]);      
    }
}

public class ClusterData extends Struct
{
    public final UTF8String scanType = new UTF8String(CommInterfaceFieldConstants.SCAN_TYPE_SIZE);
    public final UTF8String patientId = new UTF8String(CommInterfaceFieldConstants.PATIENT_ID_SIZE);
.
.
.
}

public class ReconData extends Struct
{
    public final UTF8String patientId = new UTF8String(CommInterfaceFieldConstants.PATIENT_ID_SIZE);
    public final UTF8String scanSeriesId = new UTF8String(CommInterfaceFieldConstants.SCAN_SERIES_ID_SIZE);
.
.
.
}

在我们的通信类中,在将数据放入套接字之前,我们需要获取 RunScan 对象的 bytes[],但我们在“//<<<<<<<”行中获取了 BufferUnderflowException:

private byte[] getCmdBytes(Struct scCmd)
    {
        ByteBuffer cmdBuffer = scCmd.getByteBuffer();
        int cmdSize = scCmd.size();

        byte[] cmdBytes = new byte[cmdSize];
        if (cmdBuffer.hasArray()) 
        {
            int offset = cmdBuffer.arrayOffset() + scCmd.getByteBufferPosition();
            System.arraycopy(cmdBuffer.array(), offset, cmdBytes, 0, cmdSize);            
        } 
        else 
        {
            String msg = "\n\ncmdBufferRemaining=" + cmdBuffer.remaining() + ", cmdBytesSize=" + cmdBytes.length + "\n\n";
            System.out.println(msg);
            cmdBuffer.position(scCmd.getByteBufferPosition());
            cmdBuffer.get(cmdBytes); //<<<<<<<<<< underFlowException         
        }

        return cmdBytes;
    }

此方法适用于其他情况。发生异常是因为这一行,

ByteBuffer cmdBuffer = scCmd.getByteBuffer();

我认为只返回 RunScan 对象的 8 个字节(来自剩余()方法)ByteBuffer,它们是这两个 Signed32 字段。但是这条线,

int cmdSize = scCmd.size();

返回包含这两个数组大小的 RunScan 对象的正确长度。

如果我在使用硬编码长度声明它们(而不是在构造函数中“新建”它们)时创建这两个数组,那么它可以正常工作,没有任何例外。

任何人都可以帮我弄清楚我们的实施有什么问题吗?

4

3 回答 3

2

我的代码遇到了类似的情况。通常,对于当前的 Struct 对象,您不能在与包含数组中元素数量的成员相同的结构中定义可变长度数组。

尝试这样的事情:

public class RunScanHeader extends Struct
{
    public final Signed32 numOfClusters = new Signed32();
    public final Signed32 numOfRecons = new Signed32();
}

public class RunScanBody extends Struct
{
    public final ClusterData[] clusters;
    public final ReconData[] recons ;

    public RunScan (int numOfClusters, int numOfRecons)
    {
        clusters = array(new ClusterData[numOfClusters]);
        recons = array(new ReconData[numOfRecons]);      
    }
}

然后,您将需要一个两阶段的方法来读取和写入,首先读取/写入标头数据,然后读取/写入正文数据。

抱歉,我目前没有更多详细信息,如果您无法解决此问题,请告诉我,我将重新挖掘我的代码。

于 2011-08-03T14:33:07.627 回答
1

get() will move the position of the ByteBuffer.

scCmd.getByteBuffer().slice().get(dest) might solve your issue with moving the position and unintended side effects.

scCmd.getByteBuffer().duplicate().get(dest) might also solve your issue if slice() produces the wrong picture of the origin buffer.

Additionally, it appears as though scCmd.getByteBuffer() creates a redundant reference and you are calling the source and child reference in the same method.

If scCmd.getByteBuffer() is already passing you a slice(), your redundant access to these methods is certainly going to do something other than what you planned.

于 2011-08-08T21:24:01.600 回答
1

初始化顺序很重要,它定义了每个字段的位置。在声明字段时完成初始化(最常见的情况)。或者,如果您在构造函数中执行此操作,则必须记住在成员初始化之后调用构造函数。这是在构造函数中完成初始化的示例:

 public class RunScan extends Struct {
     public final Signed32 numOfClusters;
     public final ClusterData[] clusters;
     public final Signed32 numOfRecons;
     public final ReconData[] recons ;

     public RunScan (int numOfClusters, int numOfRecons) {
        // Initialization done in the constructor for all members 
        // Order is important, it should match the declarative order to ensure proper positioning.
        this.numOfClusters = new Signed32();  
        this.clusters = array(new ClusterData[numOfClusters]);
        this.numOfRecons = new Signed32();
        this.recons = array(new ReconData[numOfRecons]);

        // Only after all the members have been initialized the set method can be used.
        this.numOfClusters.set(numOfClusters);
        this.numOfRecons.set(numOfRecons);
     }
}
于 2011-08-08T20:31:36.733 回答