Java中与Python的repr()等效的方法是什么?

27

是否有一种类似于Python的 repr 方法的 Java 方法?例如,假设该函数被命名为 repr,

"foo\n\tbar".repr()
"foo\n\tbar"
会返回"foo\n\tbar",而不是像toString方法那样返回带有换行缩进的字符串"foo \n bar"。
9个回答

10

在一些项目中,我使用下面的辅助函数来完成类似于Python中字符串的repr的操作:

private static final char CONTROL_LIMIT = ' ';
private static final char PRINTABLE_LIMIT = '\u007e';
private static final char[] HEX_DIGITS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

public static String toPrintableRepresentation(String source) {

    if( source == null ) return null;
    else {

        final StringBuilder sb = new StringBuilder();
        final int limit = source.length();
        char[] hexbuf = null;

        int pointer = 0;

        sb.append('"');

        while( pointer < limit ) {

            int ch = source.charAt(pointer++);

            switch( ch ) {

            case '\0': sb.append("\\0"); break;
            case '\t': sb.append("\\t"); break;
            case '\n': sb.append("\\n"); break;
            case '\r': sb.append("\\r"); break;
            case '\"': sb.append("\\\""); break;
            case '\\': sb.append("\\\\"); break;

            default:
                if( CONTROL_LIMIT <= ch && ch <= PRINTABLE_LIMIT ) sb.append((char)ch);
                else {

                    sb.append("\\u");

                    if( hexbuf == null ) 
                        hexbuf = new char[4];

                    for( int offs = 4; offs > 0; ) {

                        hexbuf[--offs] = HEX_DIGITS[ch & 0xf];
                        ch >>>= 4; 
                    }

                    sb.append(hexbuf, 0, 4);
                }
            }
        }

        return sb.append('"').toString();
    }
}

相比于其他提供的解决方案,它的主要优点在于不仅过滤一组有限的非可打印字符(如那些基于replace的解决方案),而是所有的非可打印ASCII字符。有些地方可能可以写得更好,但它确实完成了它的工作...

请注意,就像Python函数一样,这个函数将用引号括起字符串。如果你不想要这样,你需要在while循环之前和之后消除append('"')调用。


6

6

Java没有repr-Function,但是repr为您提供了帮助(完全透明披露:我是repr的作者)。


它是否已发布在Maven上? - Tobia
还没有。你是第一个问的人。 - llogiq

1
如果您正在使用 Groovy,它提供了一个类似于 Apache Commons Lang 的 StringEscapeUtils class
StringEscapeUtils.escapeJava("foo\n\tbar")

1

看起来Jython已经做到了这一点。理论上,您可以包含Jython jar,在解释器中启动,并实际运行repr(object)以获取所需对象。可能比您想要的开销更大,但确切地实现了您所描述的内容。

如果您想在应用程序中嵌入Jython解释器,请考虑http://wiki.python.org/jython/JythonFaq/EmbeddingJython


1

这样做可以实现,但有点取巧,它使用了StringUtils和Common Lang中的replaceEach来实现简单替换:

String hello = "hello\n\tworld\n\n\t";       
        String replaced = StringUtils.replaceEach(hello, new String[] {"\n", "\t", "\r", "\f"}, 
                                                         new String[] {"\\n", "\\t", "\\r", "\\f"});
        System.out.println("Replaced " + replaced);

1

我认为没有特定的方法 - 但是这个方案可以在不使用commons-lang的情况下解决它:

public class test {

public test() throws Exception {
    byte[] hello = "hello\n\tworld\n\n\t".getBytes();
    System.out.println(new String(hexToByte(stringToHex(hello).replaceAll("0a", "5c6e")
                                                              .replaceAll("09", "5c74"))));
}

public static void main(String[] args) throws Exception {
    new test();
}

public static String stringToHex(byte[] b) throws Exception {
    String result = "";
    for (int i = 0; i < b.length; i++) {
        result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
    }
    return result;
}

public static byte[] hexToByte(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
    }
    return data;
}

}


0

如果你只会在字符串上使用它,那么你可以编写一个方法,通过遍历字符串并将特殊字符(根据你想要的定义)替换为它们的转义代码。这就是我会做的事情。(我进行了快速搜索,谷歌上没有找到任何结果,因此编写该方法可能比寻找现有实现更快)


0
如果有这样的方法,它将使得在Java中编写quines变得非常容易,因为它可以解决引号转义的问题。由于在Java中最简单的quines都需要手动插入带有其字符代码的引号字符,所以很可能不存在这样的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接