Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将UTF-8字符编码函数从PHP转换为Java_Java_String_Utf 8_Character Encoding - Fatal编程技术网

将UTF-8字符编码函数从PHP转换为Java

将UTF-8字符编码函数从PHP转换为Java,java,string,utf-8,character-encoding,Java,String,Utf 8,Character Encoding,我正在尝试将一个PHP编码函数转换为Android Java方法。因为Java字符串长度函数处理UTF-8字符串的方式不同。在转换第二个UTF-8STR2时,我未能使翻译后的Java代码与PHP代码一致。第一个非UTF-8字符串不起作用 原始PHP代码是: function myhash_php($string,$key) { $strLen = strlen($string); $keyLen = strlen($key); $j=0 ; $hash = "

我正在尝试将一个PHP编码函数转换为Android Java方法。因为Java字符串长度函数处理UTF-8字符串的方式不同。在转换第二个UTF-8STR2时,我未能使翻译后的Java代码与PHP代码一致。第一个非UTF-8字符串不起作用

原始PHP代码是:

 function myhash_php($string,$key) {
    $strLen = strlen($string);
    $keyLen = strlen($key);
    $j=0 ; $hash = "" ; 
    for ($i = 0; $i < $strLen; $i++) {
        $ordStr = ord(substr($string,$i,1));
        if ($j == $keyLen) { $j = 0; }
        $ordKey = ord(substr($key,$j,1));
        $j++;
        $hash .= strrev(base_convert(dechex($ordStr + $ordKey),16,36));

    }
    return $hash;  
}
$str1 = "good friend" ;
$str2 = "好友" ;    //  strlen($str2) == 6
$key  = "iuyhjf476" ;
echo "php encode str1 '". $str1 ."'=".myhash_php($str1, $key)."<br>";
echo "php encode str2 '". $str2 ."'=".myhash_php($str2, $key)."<br>";
产生错误结果的当前翻译Java代码有:

    public static String   hash_java(String  string, String  key) {
        //Integer strLen  = byteLenUTF8(string) ; // consistent with php strlen("好友")==6
        //Integer keyLen  = byteLenUTF8(key) ;    //   byteLenUTF8("好友") == 6
        Integer strLen  = string.length() ;      //     "好友".length()  ==  2
        Integer keyLen  = key.length() ;
        int j=0 ;
        String  hash = "" ;
        int ordStr, ordKey ;
        for (int i = 0; i < strLen; i++) {
            ordStr = ord_java(string.substring(i,i+1));  //string is String,  php  substr($string,$i,$n)  ==  java string.substring(i, i+n)
            // ordStr = ord_java(string[i]);  //string is byte[], php  substr($string,$i,$n)  ==  java string.substring(i, i+n)
            if (j == keyLen) { j = 0; }
            ordKey = ord_java(key.substring(j,j+1));
            j++;
            hash += strrev(base_convert(dechex(ordStr + ordKey),16,36));
        }
        return hash;
    }
    // return the ASCII code of the first character of str
    public static int      ord_java( String str){
        return( (int)  str.charAt(0)  ) ;
    }
    public static String   dechex(int input  ) {
        String hex  = Integer.toHexString(input ) ;
        return hex ;
    }
    public static String   strrev(String str){
        return  new StringBuilder(str).reverse().toString() ;
    }
    public static String   base_convert(String str, int fromBase, int toBase) {
        return Integer.toString(Integer.parseInt(str, fromBase), toBase);
    }

    String  str1 = "good friend" ;
    String  str2 = "好友" ;
    String  key  = "iuyhjf476" ;
    Log.d(LogTag,"java encode str1 '"+ str1  +"'="+hash_java(str1, key)) ;
    Log.d(LogTag,"java encode str2 '"+ str2  +"'="+hash_java(str2, key)) ;

Java方法中UTF-8 str2的编码输出不正确。如何解决此问题?

在Java中,使用UTF-8字符编码将字符串转换为字节数组。然后,将编码算法应用于这个字节数组,而不是字符串

您的PHP程序似乎隐式地执行相同的操作,例如处理字符
为三个单独的字节值

编辑: 在评论中,您说您收到了用户在Android上输入的字符串。因此,我们从一个来自某个UI小部件的Java
字符串开始

您需要该Java字符串来提供与给定PHP函数在使用相同的UTF-8字符串时产生的结果相同的结果。结果字符串将只使用ASCII字符,因此其字符编码问题较少(不管是ISO-8859-1还是UTF-8)

PHP
string
数据类型不知道编码,只存储一个字节序列,因此通常它可能包含ISO-8859-1字节,其中一个字节表示一个字符,或UTF-8字节序列,其中字符通常占用多个字节,或任何其他编码。PHP
字符串
不知道如何将字节解释为字符,它只是查看和计算字节

因此,PHP字符串所称的“字符”,实际上是UTF-8编码的字节,Java端在执行其算法时必须模拟这种行为

Java的
String
数据类型与PHP非常不同,不是基于字节序列,而是(主要)将字符串视为字符序列。因此,如果使用Java字符串的字符,将不会看到PHP看到的相同元素序列

当Java在类似
的字符串上迭代时好友",有两个步骤,两个字符各一个(查看字符的Unicode代码点编号),而PHP有六个步骤,UTF-8表示的每个字节一个,查看字节值

因此,要模拟PHP,在Java中必须使用UTF-8编码将
字符串
转换为
字节[]
数组。这样,一个Java
字节
将对应一个PHP字符

评论 顺便说一句,“UTF-8字符串”在Java中没有意义

这与PHP不同,例如,
“Maß”
作为ISO-8859-1字符串(长度为3)不同于
“Maß”
作为UTF-8字符串(长度为4)

在Java中,字符串是字符序列,这就是为什么例如
“好友“
的长度为2,因为只有两个字符恰好来自非拉丁语脚本。[对于通常遇到的大多数Unicode字符,这是正确的,但也有例外。]在Java中,UTF-8这样的术语只有在字符串和字节序列之间转换时才起作用。

不用于测试-如果不完全了解您所做的事情以及文件的编码方式,这很容易产生意外的结果。对于UTF-8,您应该将所有内容都视为原始字节,并且永远不要使用
字符串进行en/解码。例如PHP:

$test1 = pack( 'H*', '414243' );  // "ABC" in hexadecimal: 2 digits per byte
$test2 = pack( 'H*', 'e5a5bde58f8b' );  // "好友" in hexadecimal, UTF-8 encoded, 3 bytes per character
Java中的示例:

byte[] test1 = new byte[] { 0x41, 0x42, 0x43 };  // "ABC"
byte[] test2 = new byte[] { (byte)0xe5, (byte)0xa5, (byte)0xbd, (byte)0xe5, (byte)0x8f, (byte)0x8b };  // "好友"
只有这样,您才能确保测试设置正确,并且不受源文件编码方式的约束。如果Java文件以UTF-8编码,而PHP文件以UTF-16LE编码,那么失败的情况会更糟,因为到目前为止,您没有将定义(原始字节)和假设(基于文本编码的字符串)分开


(当人们想要对文本进行加密/解密时,这也是一个很大的误解:他们操作(任何编程语言的)
String
,而不是实际的字节,然后想知道为什么不同的编程语言会产生不同的结果。)

使用是一个错误——“转换”从
String
byte[]
已经太晚了。在PHP和Java中,文件的文本编码可以是任何内容-提供与任何编码无关的字节是唯一安全的方法。@AmigoJack一般来说,我同意。但是“文件的文本编码”是如何实现的呢“适用于OP的问题?文字肯定只是测试用例。我忘了在代码中输入strev方法,我添加了它。现在您可以轻松地运行代码了。如何修复java代码以使其与PHP代码一致?正如我所说的,使用UTF-8将字符串转换为字节数组,然后用等效的字节数组操作替换所有当前的字符串操作。@RalfKleberhoff我们既看不到PHP文件是否保存在UTF-8中,也看不到编码-它必须设置在某个地方,同样,由于它不在文件中,PHP文件依赖于安装。对于测试,我们必须像对待原始字节一样对待文本,而不是假设任何东西——否则测试在操作和结果上都会产生误导。什么?PHP不是应用程序,并且(除非严格用作脚本解释器)依赖于HTTP(您甚至还没有对其编码提出疑问)。了解一个范围的结束和另一个范围的开始。在Java中获取输入很容易-将其放入
字符串中会导致问题,因为它不可能是UTF-8-请参阅
$test1 = pack( 'H*', '414243' );  // "ABC" in hexadecimal: 2 digits per byte
$test2 = pack( 'H*', 'e5a5bde58f8b' );  // "好友" in hexadecimal, UTF-8 encoded, 3 bytes per character
byte[] test1 = new byte[] { 0x41, 0x42, 0x43 };  // "ABC"
byte[] test2 = new byte[] { (byte)0xe5, (byte)0xa5, (byte)0xbd, (byte)0xe5, (byte)0x8f, (byte)0x8b };  // "好友"