Dónal
Dónal

Reputation: 187399

servlet request parameter character encoding

I have a Java servlet that receives data from an upstream system via a HTTP GET request. This request includes a parameter named "text". If the upstream system sets this parameter to:

TEST3 please ignore:

It appears in the logs of the upstream system as:

00 54 00 45 00 53 00 54 00 33 00 20 00 70 00 6c   //TEST3 pl
00 65 00 61 00 73 00 65 00 20 00 69 00 67 00 6e   //ease ign
00 6f 00 72 00 65 00 3a                           //ore:   

(The // comments do not actually appear in the logs)

In my servlet I read this parameter with:

String text = request.getParameter("text");

If I print the value of text to the console, it appears as:

T E S T 3  p l e a s e  i g n o r e :

If I inspect the value of text in the debugger, it appears as:

\u000T\u000E\u000S\u000T\u0003\u0000 \u000p\u000l\u000e\u000a\u000s\u000e\u0000 
\u000i\u000g\u000n\u000o\u000r\u000e\u000:

So it seems that there's a problem with the character encoding. The upstream system is supposed to use UTF-16. My guess is that the servlet is assuming UTF-8 and therefore is reading twice the number of characters it should be. For the message "TEST3 please ignore:" the first byte of each character is 00. This is being interpreted as a space when read by the servlet, which explains the space that appears before each character when the message is logged by the servlet.

Obviously my goal is simply to get the message "TEST3 please ignore:" when I read the text request param. My guess is that I could achieve this by specifying the character encoding of the request parameter, but I don't know how to do this.

Upvotes: 11

Views: 19515

Answers (3)

letonai
letonai

Reputation: 536

Use like this

new String(req.getParameter("<my request value>").getBytes("ISO-8859-1"),"UTF-8")

Upvotes: 9

epoch
epoch

Reputation: 16615

Looks like it was encoded with UTF-16LE (Little Endian) encoding, here is a class that successfully prints your string:

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;

public class Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
            String hex = "00 54 00 45 00 53 00 54 00 33 00 20 00 70 00 6c"  +
                            "00 65 00 61 00 73 00 65 00 20 00 69 00 67 00 6e" +
                           "00 6f 00 72 00 65 00 3a"; // + " 00";
            System.out.println(new String(new BigInteger(hex.replaceAll(" ", ""), 16).toByteArray(), "UTF-16LE"));
    }
}

Output:

TEST3 please ignore?

Output with two zero's added to the input

TEST3 please ignore:

UPDATE

To get this working with your Servlet you can try:

  String value = request.getParameter("text");
  try {
      value = new String(value.getBytes(), "UTF-16LE");
  } catch(java.io.UnsupportedEncodingException ex) {}

UPDATE

see the following link, it verifies that the hex produced is in fact UTF-16LE

Upvotes: 1

Petr Mensik
Petr Mensik

Reputation: 27536

Try to use Filter for this

public class CustomCharacterEncodingFilter implements Filter {

    public void init(FilterConfig config) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
                                                       throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        chain.doFilter(request, response);
    }

    public void destroy() {
    }

This should set encoding right for whole application

Upvotes: 2

Related Questions