Java 比特布弗问题的解决方法

Java 比特布弗问题的解决方法,java,bytebuffer,javolution,Java,Bytebuffer,Javolution,我使用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

我使用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,我的代码遇到了类似的情况。通常,对于当前结构对象,不能在与包含数组中元素数的成员相同的结构中定义可变长度数组

试着这样做:

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]);      
    }
}
然后需要一个两阶段的方法来读写,首先读/写头部数据,然后读/写主体数据


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

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

试着这样做:

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]);      
    }
}
然后需要一个两阶段的方法来读写,首先读/写头部数据,然后读/写主体数据


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

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

 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);
     }
}

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

 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);
     }
}
get将移动ByteBuffer的位置

scCmd.getByteBuffer.slice.getdest可能会解决移动位置和意外副作用的问题

scCmd.getByteBuffer.duplicate.getdest也可以解决您的问题,如果slice生成的原始缓冲区图片错误

此外,scCmd.getByteBuffer似乎创建了一个冗余引用,并且您正在使用相同的方法调用源引用和子引用

如果scCmd.getByteBuffer已经向您传递了一个切片,那么您对这些方法的冗余访问肯定会执行与计划不同的操作。

get将移动ByteBuffer的位置

scCmd.getByteBuffer.slice.getdest可能会解决移动位置和意外副作用的问题

scCmd.getByteBuffer.duplicate.getdest也可以解决您的问题,如果slice生成的原始缓冲区图片错误

此外,scCmd.getByteBuffer似乎创建了一个冗余引用,并且您正在使用相同的方法调用源引用和子引用


如果scCmd.getByteBuffer已经向您传递了一个切片,那么您对这些方法的冗余访问肯定会做一些您计划之外的事情。

感谢您的帮助。我将测试我们的服务器端是否准备好了。作为一般的非特定的库主题,考虑在处理原始字节[]类型数据时确保实现是客户机/服务器平台不可知的。例如,如果字节表示数字,则必须考虑endianess。总的来说,我对这个答案投了赞成票,因为它使用了一种性能更高/更一致的方法,即首先发送一个头,指示即将发生的事情的长度,然后发送变量数据包。这允许服务器读取固定的标题,然后动态分配内容并完全/高效地读取。感谢您的帮助。我将测试我们的服务器端是否准备好了。作为一般的非特定的库主题,考虑在处理原始字节[]类型数据时确保实现是客户机/服务器平台不可知的。例如,如果字节表示数字,则必须考虑endianess。总的来说,我对这个答案投了赞成票,因为它使用了一种性能更高/更一致的方法,即首先发送一个头,指示即将发生的事情的长度,然后发送变量数据包。这允许服务器读取固定的标题,然后动态分配内容并完全/高效地读取。感谢您的帮助。根据您的建议,避免了UnderflowException,但我仍然无法从ClusterData数组中获得正确的值numOfCluster值很好。当我将ByteBuffer转换为byte[]以便放入套接字时。我试过接受Jimn235的建议,但还是一样。因此,我必须编写自己的方法来手动创建ByteBuffer,并将RunScan的所有内容复制到该ByteBuffer中,然后将该ByteBuffer转换为byte[],谢谢您的帮助。根据你的建议
n、 虽然避免了UnderflowException,但我仍然无法从ClusterData数组中获得正确的值numOfCluster值很好。当我将ByteBuffer转换为byte[]以便放入套接字时。我试过接受Jimn235的建议,但还是一样。因此,我必须编写自己的方法来手动创建ByteBuffer,并将RunScan的所有内容复制到该ByteBuffer中,然后将该ByteBuffer转换为byte[]。您好Jimn235,谢谢您的建议。请参考我对Dautelle回复的评论。使用您的建议,我看不到不同的结果。我对您的复制代码感兴趣,只是想看看它是否能比您的描述更简单。如果没有完整的代码库,很难知道缓冲区的外观背后是什么。嗨,Jimn235,谢谢你的建议。请参考我对Dautelle回复的评论。使用您的建议,我看不到不同的结果。我对您的复制代码感兴趣,只是想看看它是否能比您的描述更简单。如果没有完整的代码库,就很难知道缓冲区的外观背后是什么。
 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);
     }
}