java jframe - Java entspricht der EncDEURIComponent von JavaScript, die identische Ausgabe produziert?




6 Answers

Betrachtet man die Implementierungsunterschiede, sehe ich Folgendes:

encodeURIComponent :

  • [-a-zA-Z0-9._*~'()!] Zeichen (Regex-Darstellung): [-a-zA-Z0-9._*~'()!]

Java 1.5.0 Dokumentation zu URLEncoder :

  • [-a-zA-Z0-9._*] Zeichen (Regex-Darstellung): [-a-zA-Z0-9._*]
  • Das Leerzeichen " " wird in ein Pluszeichen "+" .

Um das gewünschte Ergebnis zu erhalten, benutzen Sie URLEncoder.encode(s, "UTF-8") und machen Sie dann eine Nachbearbeitung:

  • Ersetze alle Vorkommen von "+" durch "%20"
  • Ersetze alle Vorkommen von "%xx" die irgendeines von [~'()!] repräsentieren, zurück in ihre wörtlichen Gegenstücke
showmessagedialog joptionpane

Ich habe mit verschiedenen Teilen von Java-Code experimentiert und versucht, etwas zu finden, das eine Zeichenfolge mit Anführungszeichen, Leerzeichen und "exotischen" Unicode-Zeichen codiert und eine Ausgabe erzeugt, die identisch mit der encodeURIComponent Funktion von JavaScript ist.

Meine Folter-Testreihe ist: "A" B ± "

Wenn ich die folgende JavaScript-Anweisung in Firebug eingeben:

encodeURIComponent('"A" B ± "');

-Dann bekomme ich:

"%22A%22%20B%20%C2%B1%20%22"

Hier ist mein kleines Java-Testprogramm:

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class EncodingTest
{
  public static void main(String[] args) throws UnsupportedEncodingException
  {
    String s = "\"A\" B ± \"";
    System.out.println("URLEncoder.encode returns "
      + URLEncoder.encode(s, "UTF-8"));

    System.out.println("getBytes returns "
      + new String(s.getBytes("UTF-8"), "ISO-8859-1"));
  }
}

-Dieses Programm gibt aus:

URLEncoder.encode returns %22A%22+B+%C2%B1+%22
getBytes returns "A" B ± "

Schließen, aber keine Zigarre! Was ist der beste Weg, um eine UTF-8-Zeichenkette mit Java zu kodieren, so dass sie dieselbe Ausgabe wie die encodeURIComponent JavaScript encodeURIComponent ?

BEARBEITEN: Ich benutze Java 1.4, das in Kürze zu Java 5 umzieht.




Verwenden der JavaScript Engine, die mit Java 6 ausgeliefert wird:


import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class Wow
{
    public static void main(String[] args) throws Exception
    {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("JavaScript");
        engine.eval("print(encodeURIComponent('\"A\" B ± \"'))");
    }
}

Ausgabe:% 22A% 22% 20B% 20% c2% b1% 20% 22

Der Fall ist anders, aber es ist näher an dem, was Sie wollen.




Ich habe meine eigene Version von encodeURIComponent entwickelt, weil die veröffentlichte Lösung ein Problem hat. Wenn in der Zeichenfolge ein + vorhanden ist, das codiert werden soll, wird es in ein Leerzeichen konvertiert.

Also hier ist meine Klasse:

import java.io.UnsupportedEncodingException;
import java.util.BitSet;

public final class EscapeUtils
{
    /** used for the encodeURIComponent function */
    private static final BitSet dontNeedEncoding;

    static
    {
        dontNeedEncoding = new BitSet(256);

        // a-z
        for (int i = 97; i <= 122; ++i)
        {
            dontNeedEncoding.set(i);
        }
        // A-Z
        for (int i = 65; i <= 90; ++i)
        {
            dontNeedEncoding.set(i);
        }
        // 0-9
        for (int i = 48; i <= 57; ++i)
        {
            dontNeedEncoding.set(i);
        }

        // '()*
        for (int i = 39; i <= 42; ++i)
        {
            dontNeedEncoding.set(i);
        }
        dontNeedEncoding.set(33); // !
        dontNeedEncoding.set(45); // -
        dontNeedEncoding.set(46); // .
        dontNeedEncoding.set(95); // _
        dontNeedEncoding.set(126); // ~
    }

    /**
     * A Utility class should not be instantiated.
     */
    private EscapeUtils()
    {

    }

    /**
     * Escapes all characters except the following: alphabetic, decimal digits, - _ . ! ~ * ' ( )
     * 
     * @param input
     *            A component of a URI
     * @return the escaped URI component
     */
    public static String encodeURIComponent(String input)
    {
        if (input == null)
        {
            return input;
        }

        StringBuilder filtered = new StringBuilder(input.length());
        char c;
        for (int i = 0; i < input.length(); ++i)
        {
            c = input.charAt(i);
            if (dontNeedEncoding.get(c))
            {
                filtered.append(c);
            }
            else
            {
                final byte[] b = charToBytesUTF(c);

                for (int j = 0; j < b.length; ++j)
                {
                    filtered.append('%');
                    filtered.append("0123456789ABCDEF".charAt(b[j] >> 4 & 0xF));
                    filtered.append("0123456789ABCDEF".charAt(b[j] & 0xF));
                }
            }
        }
        return filtered.toString();
    }

    private static byte[] charToBytesUTF(char c)
    {
        try
        {
            return new String(new char[] { c }).getBytes("UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            return new byte[] { (byte) c };
        }
    }
}






Dies ist ein einfaches Beispiel Ravi Wallaus Lösung:

public String buildSafeURL(String partialURL, String documentName)
        throws ScriptException {
    ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
    ScriptEngine scriptEngine = scriptEngineManager
            .getEngineByName("JavaScript");

    String urlSafeDocumentName = String.valueOf(scriptEngine
            .eval("encodeURIComponent('" + documentName + "')"));
    String safeURL = partialURL + urlSafeDocumentName;

    return safeURL;
}

public static void main(String[] args) {
    EncodeURIComponentDemo demo = new EncodeURIComponentDemo();
    String partialURL = "https://www.website.com/document/";
    String documentName = "Tom & Jerry Manuscript.pdf";

    try {
        System.out.println(demo.buildSafeURL(partialURL, documentName));
    } catch (ScriptException se) {
        se.printStackTrace();
    }
}

Ausgabe: https://www.website.com/document/Tom%20%26%20Jerry%20Manuscript.pdf

Es beantwortet auch die hängenden Fragen in den Kommentaren von Loren Shqipognja, wie eine String-Variable an encodeURIComponent() . Die Methode scriptEngine.eval() gibt ein Object , so dass es unter anderem auch über String.valueOf() in String konvertiert werden kann.




Guava-Bibliothek hat PercentEscaper:

Escaper percentEscaper = new PercentEscaper("-_.*", false);

"-_. *" sind sichere Zeichen

false sagt PercentEscaper, um Leerzeichen mit '% 20', nicht '+' zu vermeiden




Related

java javascript unicode utf-8