2012-05-24 131 views
-2

我正在尝试使用GWT开发基于Web客户端的在线游戏。字符串数组在分割字符串后抛出ArrayIndexOutOfBoundsException

现在游戏机制工作得很好,我真的很想继续我的开发计划中的下一步,但现在我坚持使用一个简单的编码/解码函数来存储我的数据客户端转换为字符串。

我采取的步骤并不复杂。在运行期间,我的服务器创建游戏对象的“ImageStates”,以便在我的客户端上的Canvas上绘制。每个ImageState都包含许多图层,其中包含在什么特定时间等地点需要绘制的细节。

我试过ObjectInput/OutputStream,结合GZip-Compression和ByteInputStreams,但是我找不到前两个的任何GWT实现,所以我不得不考虑另一个解决方案并碰到gwt-lzma。

我的目标是将这些细节编码成一个字符串,在服务器上压缩它,将压缩后的数据发送到客户端,在那里解压并解码,以便客户端可以“读取”。要做到这一点,我创建了一个编码和解码功能:

编码器:

public static String encodeImageStateContainer(HashMap<String,HashMap<Long,ImageState>> imageStateContainer){ 
    StringBuilder mainStringBuilder = new StringBuilder(); 

    Iterator<Entry<String,HashMap<Long,ImageState>>> imageStateContainerIterator = imageStateContainer.entrySet().iterator(); 
    while(imageStateContainerIterator.hasNext()){ 
     Entry<String,HashMap<Long,ImageState>> tempImageStateManagerMetadata = imageStateContainerIterator.next(); 

     HashMap<Long,ImageState> tempImageStateManager = tempImageStateManagerMetadata.getValue(); 

     if(tempImageStateManager.size() > 0){ 

      if(mainStringBuilder.length() > 0){ 
       mainStringBuilder.append('}'); //Divisor between Image State Managers 
      } 

      mainStringBuilder.append(tempImageStateManagerMetadata.getKey()); 
      mainStringBuilder.append('|'); //Divisor between Name and following Data 

      StringBuilder subOneStringBuilder = new StringBuilder();    

      Iterator<Entry<Long,ImageState>> tempImageStateManagerIterator = tempImageStateManager.entrySet().iterator(); 
      while(tempImageStateManagerIterator.hasNext()){ 
       Entry<Long,ImageState> tempImageStateMetaData = tempImageStateManagerIterator.next(); 

       if(subOneStringBuilder.length() > 0){ 
        subOneStringBuilder.append(')'); //Divisor between Image Objects 
       } 

       subOneStringBuilder.append(tempImageStateMetaData.getKey()); 
       subOneStringBuilder.append('-'); //Divisor between Object Id and Image State Data 

       StringBuilder subTwoStringBuilder = new StringBuilder(); 
       ImageState tempImageState = tempImageStateMetaData.getValue(); 
       subOneStringBuilder.append(tempImageState.getFirstFrameId()); //1. => First Frame Id 
       subOneStringBuilder.append(';'); //Divisor between Image State data types 
       subOneStringBuilder.append(tempImageState.getFramesPerLayer()); //2. => Total Frame Count 
       subOneStringBuilder.append(';'); 
       subOneStringBuilder.append(tempImageState.getMinumimScaleFactor()); //3. => Minimum Scale Factor 
       subOneStringBuilder.append(';'); 

       ImageStateLayer[] tempImageStateLayers = tempImageState.getImageStateLayers(); 
       for(int layerId = 0; layerId < tempImageStateLayers.length; ++layerId){ 

        if(subTwoStringBuilder.length() > 0){ 
         subTwoStringBuilder.append('/'); //Divisor between Image State Layers 
        } 

        //Frame Arrays 
        String[] imageNativePath = tempImageStateLayers[layerId].getImageNativePath(); 
        short[] offsetX = tempImageStateLayers[layerId].getOffsetX(); 
        short[] offsetY = tempImageStateLayers[layerId].getOffsetY(); 
        short[] orientation = tempImageStateLayers[layerId].getOrientation(); 

        //Finalization Arrays 
        byte[] imagePathChange = tempImageStateLayers[layerId].getImagePathChange(); 
        byte[] offsetXChange = tempImageStateLayers[layerId].getOffsetXChange(); 
        byte[] offsetYChange = tempImageStateLayers[layerId].getOffsetYChange(); 
        byte[] orientationChange = tempImageStateLayers[layerId].getOrientationChange(); 


        //Image Path Data 
        StringBuilder subThreeStrignBuilder = new StringBuilder(); 
        for(int imagePathId = 0; imagePathId < imageNativePath.length; ++imagePathId){ 

         if(subThreeStrignBuilder.length() > 0){ 
          subThreeStrignBuilder.append('#'); //Divisor between Frame Data Sets 
         } 

         subThreeStrignBuilder.append(imageNativePath[imagePathId]); 
         subThreeStrignBuilder.append(','); //Divisor between Frame Data Set Data 
         subThreeStrignBuilder.append(imagePathChange[imagePathId]); 
        } 

        subTwoStringBuilder.append(subThreeStrignBuilder.toString()); 
        subTwoStringBuilder.append('['); //Divisor between Frame Data Types 

        //OffsetX Data 
        subThreeStrignBuilder = new StringBuilder(); 
        for(int offsetXId = 0; offsetXId < offsetX.length; ++offsetXId){ 

         if(subThreeStrignBuilder.length() > 0){ 
          subThreeStrignBuilder.append('#'); //Divisor between Frame Data Sets 
         } 

         subThreeStrignBuilder.append(offsetX[offsetXId]); 
         subThreeStrignBuilder.append(','); //Divisor between Frame Data Set Data 
         subThreeStrignBuilder.append(offsetXChange[offsetXId]); 
        } 

        subTwoStringBuilder.append(subThreeStrignBuilder.toString()); 
        subTwoStringBuilder.append('['); //Divisor between Frame Data Types 

        //OffsetY Data 
        subThreeStrignBuilder = new StringBuilder(); 
        for(int offsetYId = 0; offsetYId < offsetY.length; ++offsetYId){ 

         if(subThreeStrignBuilder.length() > 0){ 
          subThreeStrignBuilder.append('#'); //Divisor between Frame Data Sets 
         } 

         subThreeStrignBuilder.append(offsetY[offsetYId]); 
         subThreeStrignBuilder.append(','); //Divisor between Frame Data Set Data 
         subThreeStrignBuilder.append(offsetYChange[offsetYId]); 
        } 

        subTwoStringBuilder.append(subThreeStrignBuilder.toString()); 
        subTwoStringBuilder.append('['); //Divisor between Frame Data Types 

        //Orientation Data 
        subThreeStrignBuilder = new StringBuilder(); 
        for(int orientationId = 0; orientationId < orientation.length; ++orientationId){ 

         if(subThreeStrignBuilder.length() > 0){ 
          subThreeStrignBuilder.append('#'); //Divisor between Frame Data Sets 
         } 

         subThreeStrignBuilder.append(orientation[orientationId]); 
         subThreeStrignBuilder.append(','); //Divisor between Frame Data Set Data 
         subThreeStrignBuilder.append(orientationChange[orientationId]); 
        } 

        subTwoStringBuilder.append(subThreeStrignBuilder.toString()); 

       } 
       subOneStringBuilder.append(subTwoStringBuilder.toString());    
      } 
      mainStringBuilder.append(subOneStringBuilder.toString()); 
     } 
    } 

    return mainStringBuilder.toString(); 
} 

解码器:

public static HashMap<String,HashMap<Long,ImageState>> decodeImageStateContainer(String data){  

    String[] imageStateManagerArray = data.split("\\}"); 
    HashMap<String,HashMap<Long,ImageState>> imageStateManagerContainer = new HashMap<String,HashMap<Long,ImageState>>(imageStateManagerArray.length); 

    for(int managerId = 0; managerId < imageStateManagerArray.length; ++managerId){ 
     String[] tempImageStateData = imageStateManagerArray[managerId].split("\\|"); 

     HashMap<Long,ImageState> tempImageStateManager = new HashMap<Long,ImageState>(); 
     imageStateManagerContainer.put(tempImageStateData[0], tempImageStateManager); 

     String[] tempImageStateManagerObjects = tempImageStateData[1].split("\\)"); 

     for(int objectId = 0; objectId < tempImageStateManagerObjects.length; ++objectId){ 
      String[] tempImageObjectData = tempImageStateManagerObjects[objectId].split("\\-"); 

      long imageObjectId = Long.parseLong(tempImageObjectData[0]); 
      String[] imageStateMetaData = tempImageObjectData[1].split("\\;");    
      ImageState tempImageState = new ImageState(Integer.parseInt(imageStateMetaData[1]), Integer.parseInt(imageStateMetaData[0]), Integer.parseInt(imageStateMetaData[2])); 
      tempImageStateManager.put(imageObjectId, tempImageState); 

      String[] tempImageStateLayerMetaData = imageStateMetaData[3].split("\\/"); 
      ImageStateLayer[] tempImageStateLayers = new ImageStateLayer[tempImageStateLayerMetaData.length]; 

      for(int layerId = 0; layerId < tempImageStateLayerMetaData.length; ++layerId){ 
       String[] layerElements = tempImageStateLayerMetaData[layerId].split("\\[");  

       String[] imageNativePathDetails = layerElements[0].split("\\#"); 
       String[] offsetXDetails = layerElements[1].split("\\#"); 
       String[] offsetYDetails = layerElements[2].split("\\#"); 
       **String[] orientationDetails = layerElements[3].split("\\#");** 

       //Image Path Data 
       String[] imageNativePaths = new String[imageNativePathDetails.length]; 
       byte[] imagePathChange = new byte[imageNativePathDetails.length]; 
       for(int id = 0; id < imageNativePathDetails.length; ++id){      
        String[] imagePathDetailElements = imageNativePathDetails[id].split("\\,"); 
        imageNativePaths[id] = imagePathDetailElements[0]; 
        imagePathChange[id] = Byte.parseByte(imagePathDetailElements[1]); 
       } 

       //OffsetX Data 
       short[] offsetX = new short[offsetXDetails.length]; 
       byte[] offsetXChange = new byte[offsetXDetails.length]; 
       for(int id = 0; id < offsetXDetails.length; ++id){ 
        String[] offsetXDetailElements = offsetXDetails[id].split("\\,"); 
        offsetX[id] = Short.parseShort(offsetXDetailElements[0]); 
        offsetXChange[id] = Byte.parseByte(offsetXDetailElements[1]); 
       } 

       //OffsetY Data 
       short[] offsetY = new short[offsetYDetails.length]; 
       byte[] offsetYChange = new byte[offsetYDetails.length]; 
       for(int id = 0; id < offsetYDetails.length; ++id){ 
        String[] offsetYDetailElements = offsetYDetails[id].split("\\,"); 
        offsetY[id] = Short.parseShort(offsetYDetailElements[0]); 
        offsetYChange[id] = Byte.parseByte(offsetYDetailElements[1]); 
       } 

       //Orientation Data 
       short[] orientation = new short[orientationDetails.length]; 
       byte[] orientationChange = new byte[orientationDetails.length]; 
       for(int id = 0; id < orientationDetails.length; ++id){ 
        String[] orientationDetailElements = orientationDetails[id].split("\\,"); 
        orientation[id] = Short.parseShort(orientationDetailElements[0]); 
        orientationChange[id] = Byte.parseByte(orientationDetailElements[1]); 
       } 

       //Create the Layer and Add it to the Array 
       tempImageStateLayers[layerId] = new ImageStateLayer(imageNativePaths,new short[][]{offsetX,offsetY,orientation}, new byte[][]{imagePathChange,offsetXChange,offsetYChange,orientationChange}); 

      } 

      //Connect the Reference to the layers with the Image State 
      tempImageState.setImageStateLayers(tempImageStateLayers); 

     }   

    }  

    return imageStateManagerContainer; 
} 

现在我的问题:如果我编码它的服务器和解码上它直接后来它需要大约三个编码周期,直到我在解码器的这个特定位置得到一个IndexOutofBoundsException,最后一行是根据堆栈跟踪错误的那条线:

for(int layerId = 0; layerId < tempImageStateLayerMetaData.length; ++layerId){ 
       String[] layerElements = tempImageStateLayerMetaData[layerId].split("\\[");  

       String[] imageNativePathDetails = layerElements[0].split("\\#"); 
       String[] offsetXDetails = layerElements[1].split("\\#"); 
       String[] offsetYDetails = layerElements[2].split("\\#"); 
       String[] orientationDetails = layerElements[3].split("\\#"); 

我不会说我是专家,但在测试编码器后,我可以肯定地说它生成的字符串总是有效的,我得到这个错误的字符串也是完整的。我的解码功能一定有问题,但我不知道它可能是什么。

正如我所说的,前三个周期正确编码和解码,要编码的数据没有显着变化。编码字符串没有办法导致字符串数组小于4个元素。基本上,就我所了解的代码而言,这个错误不能存在。

我认为这可能是某种内存分配问题,它会阻止字符串被正确拆分,但这只是一个无知程序员的想法。

任何帮助深表感谢!

+0

好的,我找到了解决我的问题的方法: 编码时,我正在将数字类型打印到我的字符串中。在选择我的Seperator符号时,我没有采用负值,导致在考虑数字之前出现' - ',这导致我在尝试用' - '分割时无法控制分割字符串。 我用另一个字符替换减号,现在一切正常! :-) – Corsair

+0

下一次,请只发布相关代码。如果您为自己的问题找到了答案,请不要回复评论,而要有正确的答案,以便人们知道已经回答,并且不会浪费时间。 – Renato

+0

您好,感谢您只发布相关信息的建议。这只是我在这个问题上停留了几天,而当我在这里发布这个话题时,我将要完全放弃,这是纯粹的运气,我后来偶然遇到了这个解决方案。 是的,我应该回答这个问题,而不是评论它。事实上,这是我最初想要做的。但后来该网站告诉我,我必须等待8个小时,因为我是一个新用户,所以我希望有人至少会看到评论。 另外,我想我至少节省了时间来回答这个问题;-) – Corsair

回答

2

我找到了解决我的问题:

虽然编码,我在印刷数字类型到我的字符串。在选择我的Seperator符号时,我没有采用负值,导致在考虑数字之前产生了一个' - ',导致我在尝试用' - '分割时无法控制分割我的字符串。我用另一个字符替换了减号,现在一切正常!