0

如何解码包含“Total\x20Value”等字符的字符串,我的实际值为“Total Value”

使用 javascript 它被浏览器解码,例如:

如果我在浏览器控制台上写:

var a = 'Total\x20Value';

然后我打印一个然后它将打印“总值”意味着浏览器自动解码了这个字符串

现在我的问题是如何在 Java 代码中执行此操作,我希望在 Java 代码中解码此字符串,但我没有办法在 Java 中对其进行解码。还有一件事我不能为这种情况使用字符串替换解决方案,因为给定的字符串只包含一个空格字符,但在运行时我会得到不同的字符,所以我需要一个通用的解决方案,我可以在没有任何替换操作的情况下解码任何字符串。

另一个字符串示例是:

"尺寸\x5f13420895086619127059036175667828\x7e\x24\x7e1\x7e\x24\x7e1"

它的真实字符串是:

“DIMENSION_13420895086619127059036175667828~$~1~$~1”。

提出一些建议如果可以使用一些预定义的类在 Java 中实现,我已经经历了许多解决方案,但对我没有任何帮助。

4

3 回答 3

0

这些 \xNN 子字符串只是编码字符的十六进制 ASCII 码。您可以在此处找到这样的 ASCII 表

您可以创建自己的映射,其中包含十六进制到字符的映射,并使用它来操作您的字符串。例子:

import java.util.HashMap;
import java.util.Map;

public class NewClass {
    public static void main(String[] args){
        String str1 = "Total\\x20Value";
        String str2 = "DIMENSION\\x5f13420895086619127059036175667828\\x7e\\x24\\x7e1\\x7e\\x24\\x7e1"; 
        System.out.println(decode(str1));
        System.out.println(decode(str2));
    }
    public static String decode(String str){
        Map<String,String> map = new HashMap<>();
        //you can extend this to x<256 if you expect your strings to contain special characters like (Ã,Ç,Æ,§,¾ ...) 
        for(int i = 0; i< 128; i++){
            map.put((i<16?"\\x0":"\\x")+Integer.toHexString(i), Character.toString((char)i));            
        }

        for(String key: map.keySet()){
            if(str.contains(key)){
                str = str.replace(key, map.get(key));
            }
        }
        return str;
    }
}
于 2017-06-21T12:03:55.577 回答
0

此解决方案涉及将正则表达式转换为十六进制字符串,然后获取表示十六进制字符串的等效 ASCII 值。最后用等效的 ASCII 字符替换十六进制字符串。

    public static void main(String[] args) {

    String input = "Total\\x20Value\\x7e";  

    String modifiedInput = input.replace("\\", "0");


     for (int i = 0 ; i<modifiedInput.length() ; i++)
     {  
            if(i<=modifiedInput.length()-3){
            if (modifiedInput.charAt(i) == '0' && modifiedInput.charAt(i+1)=='x')
            {
                String subString = modifiedInput.substring(i, i+4) ;

                String ascii = convert(subString);

            modifiedInput = modifiedInput.replace(subString.toString(), ascii);

            }
            }   

     }

     System.out.println(modifiedInput);


    }

    public static String convert(String hexDigits){
       // byte[] bytes = new byte[hexDigits.length];

        byte[] bytes = new byte[1];

            bytes[0] = Integer.decode(hexDigits).byteValue();

        String result;
        result = new String(bytes);
        return result;
    }

}
于 2017-06-22T07:08:02.477 回答
0

我怀疑解决您遇到的问题的更好方法是修复这些字符串的创建方式,因此它们没有子字符串,例如\x20or\x7e开始。

但是,这些字符串很可能来自您可能无法控制的第三方 API。如果是这种情况,以下方法应该会有所帮助。它采用您要解码的字符串值,包含此类子字符串,并用适当的字符替换它们:

import java.util.regex.*;

// ...

private static String decode(String input) {
    Pattern p = Pattern.compile("\\\\x[0-9A-Fa-f]{2}");
    Matcher m = p.matcher(input);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
        String matchedText = m.group(0);
        int characterCode = Integer.parseInt(matchedText.substring(2), 16);
        m.appendReplacement(sb,
            Matcher.quoteReplacement(Character.toString((char)characterCode)));
    }

    m.appendTail(sb);
    return sb.toString();
}

有几点需要注意:

  • 此代码的整体结构基于Matcher 文档中的示例代码。

  • 一个正则表达式,用于匹配\x24or \x7eis形式的子字符串\\x[0-9A-Fa-f]{2}。请注意,我们必须将反斜杠加倍,\因为\在正则表达式中具有特殊含义,并且我们希望匹配实际\字符。但是,\在 Java 字符串字面量中也有特殊含义,因此我们需要再次将其加倍。

  • 我们需要使用Matcher.quoteReplacement来确保我们要替换的字符串被解释为该字符串而不是其他任何东西。在替换字符串中,$1例如将被解释为第一个匹配的组,并且$它本身会导致抛出异常。(幸运的是,您的第二个示例字符串包含$字符 - 没有那些我很可能错过了这个。)

  • 您可能需要考虑将 移动Pattern到某个地方的静态最终常量,以避免每次调用该方法时都编译正则表达式。

于 2017-06-21T10:22:37.437 回答