将Delphi代码转换为Java

时间:2016-05-26 14:35:52

标签: java delphi delphi-xe

通过将以下Delphi代码转换为Java,我遇到了问题。 我在这里发布的代码只是我用来描述我的问题的完整代码的一小部分。

type
  TSecureArray = Array of AnsiChar;

const
  CodePosIdx = 10; 

function ReadLenFromArray(aArray:TSecureArray):integer;
var
  HS:integer;
begin
  Hs:=0;
  HS:=Hs+(ord(aArray[3]))*$1000000;
  HS:=Hs+(ord(aArray[4]))*$10000;
  HS:=Hs+(ord(aArray[5]))*$100;
  HS:=Hs+(ord(aArray[6]));
  result:=HS;
end;

function Decrypt(Source: Ansistring): Ansistring;    
var 
  srclen, aArrayLength: integer;
  aArray: TSecureArray;
  cryptedstring:AnsiString;
begin
  aArrayLength:=Length(Source); // length of source-String in my test case is 1046
for i:=1 to aArrayLength do                                      
    aArray[i]:=Source[i];

  srclen:=ReadLenFromArray(aArray);  // function returns 858862149 in my test case
  cryptedString:='';
  for i:=1 to srclen do
    cryptedstring:=cryptedstring+aArray[aArraylength-srclen-ord(aArray[CodePosIdx])+i];
end;
在Java中我已经将这段Delphi代码实现为:

 protected static int readLenFromArray(char secureArray[])
    {
        int arrayLength = secureArray.length;
        int hs = 0;

        if(2<arrayLength)
        {
        hs = hs + (int) secureArray[2] * 0x1000000;
        }

        if(3<arrayLength)
        {
        hs = hs + (int) secureArray[3] * 0x10000;
        }

        if(4<arrayLength)
        {
        hs = hs + (int) secureArray[4] * 0x100;
        }

        if(5<arrayLength)
        {
        hs = hs + (int) secureArray[5];
        }

        return hs;


 }

    protected static String deCrypt(String code)
    {  
    int codePosIdx = 10;
    char [] secureArray;
    int srcLen;
    int arrayLength;

    arrayLength = source.length();   // 1046 in my test case

    for (i=0; i<arrayLength; i++)
    {
     secureArray[i] = source.charAt(i);
    }
    srcLen = readLenFromArray(secureArray); //  function returns 858862149 in my test case
    StringBuilder tmpStr = new StringBuilder();

    for(i=0; i<srcLen; i++)
    {
    tmpStr = tmpStr.append(secureArray[arrayLength - srcLen - 1 - (int) secureArray[codePosIdx - 1] + i]);
    }
    cryptCode = tmpStr.toString();

    return cryptCode;
    }

我的问题是在Java中检查for-Loop中的条件。 在我的测试用例aArray[i + (int) secureArray[codePosIdx - 1]]中等于aArray[-858861172],与Delphi相反,它会导致IndexOutOfBound异常。我通过if语句在Java readLineFromArray函数中避免了它。但是我如何在decrypt函数中解决这个问题,以便为所有参数值保留函数的功能。 任何真正适用的建议!

2 个答案:

答案 0 :(得分:6)

问题是你声明的Delphi和Java中的数组是不一样的 您在Delphi中使用AnsiChar,这是一个字节 Java始终是unicode,因此char类型是两个字节 您需要将Java数组声明为byte aArray[]

第二个例程失败,因为Java String由两个字节chars组成,因此永远不会有效。
您需要再次传递byte aArray[]并进行处理。

因为您不再使用字符串,所以不能依赖.length()函数来获取输入的长度,您必须自己进行测试以查看终止零字节的位置是,或传递长度作为参数。

答案 1 :(得分:1)

为了我无法在评论中获得的代码格式化,这是一个答案。

我想我可以使用非初始化(即零或随机垃圾)数据来查找函数中的基本控制流问题。你的功能如下:

function Decrypt(Source: Ansistring): Ansistring;    
var 
  srclen, aArrayLength: integer;
  aArray: TSecureArray;
  cryptedstring:AnsiString;
begin
  aArrayLength:=Length(Source); // length of source-String in my test case is 1046

....然后突然......

  srclen:=ReadLenFromArray(aArray);  // function returns 858862149 in my test case
  for i:=1 to aArrayLength do                                      
    aArray[i]:=Source[i];

这是坚果!你没有初始化aArray无处,也没有初始化容器(长度又名大小又称卷)和数据本身,但你将nil = NULL指针传递给ReadLenFromArray !!!

我想你想要这样的东西:

function Decrypt(const Source: Ansistring): Ansistring;    
....
begin
  aArrayLength := Length(Source); 

  SetLength(aArray, aArrayLength); //  !!!!! init the container
  for i := 1 to aArrayLength do                                      
    aArray[i - 1] := Source[i];    //  !!!!! init the data in the container

  srclen := ReadLenFromArray(aArray); // now and only now can you use the array
   .....rest of function

你应该注意,由于历史原因(我认为你不是很感兴趣),Delphi中的字符串被索引1到Length,动态数组被索引0到Length-1 - 所以我纠正了for循环中的索引

据我所知,你也忘了在Java中初始化secureArray - 你永远不要设置它的长度,所以我只能想知道在赋值循环期间数据的位置。

基本上你的ReadLengthFromArray函数只占用数组的切片,并且(在Intel-endian机器上)反转字节顺序。

更明显和简化的代码就像

function ReadLenFromArray(const aArray:TSecureArray): integer;
var
  HS : LongRec absolute Result;
begin
  if (High(aArray) < 6) or (Low(aArray) > 3) then 
     raise EAccessViolation.Create('The passed aArray does not have required data!');

  HS.Bytes[3] := ord(aArray[3]);
  HS.Bytes[2] := ord(aArray[4]);
  HS.Bytes[1] := ord(aArray[5]);
  HS.Bytes[0] := ord(aArray[6]);
end;

http://docwiki.embarcadero.com/Libraries/Berlin/en/System.SysUtils.LongRec