将 Delphi 代码转换为 Java

Converting Delphi code to Java

我在将以下 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]))*00000;
  HS:=Hs+(ord(aArray[4]))*000;
  HS:=Hs+(ord(aArray[5]))*0;
  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 循环的条件。 在我的测试用例中,aArray[i + (int) secureArray[codePosIdx - 1]] 等于 aArray[-858861172],与 Delphi 相反,它会导致 IndexOutOfBound 异常。我通过 if 语句在 Java readLineFromArray 函数中避免了它。但是我如何在我的 decrypt 函数中解决这个问题,以便为所有参数值保留函数的功能。 任何建议真的很受欢迎!

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

第二个例程失败,因为 Java String 由两个字节 chars 组成,因此永远不会工作。
同样,您需要传递 byte aArray[] 并对其进行处理。

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

为了我无法在评论中获得的代码格式,将此作为答案。

我想我可以使用未初始化(即:零或随机垃圾)数据在您的函数中看到一个基本的控制流问题。你的功能是这样的:

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