将 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
我在将以下 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