개발 관련/Java
HTTP 주소를 URL 인코딩하기.
snoworca
2017. 8. 31. 11:06
JAVA 에서 특정 URL 경로로 데이터를 가져오기 위하여 URL Encoding 을 해야할 때 여간 귀찮은 것이 아니다.
그래서 아래처럼 URLEncoder 클래스를 수정한 BorwerURLEncoder 를 만들었다.
사용법은 URLEncoder 와 동일하며, 마치 브라우저 창에서 URL 주소를 입력해 놓은 것처럼 출력되도록 하였다.
BrowserURLEncoder.java
import java.io.CharArrayWriter; import java.io.UnsupportedEncodingException; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.UnsupportedCharsetException; import java.util.BitSet; public class BrowserURLEncoder { static BitSet dontNeedEncoding; static final int caseDiff = ('a' - 'A'); static String dfltEncName = "utf-8"; static { dontNeedEncoding = new BitSet(256); int i; for (i = 'a'; i <= 'z'; i++) { dontNeedEncoding.set(i); } for (i = 'A'; i <= 'Z'; i++) { dontNeedEncoding.set(i); } for (i = '0'; i <= '9'; i++) { dontNeedEncoding.set(i); } dontNeedEncoding.set('#'); dontNeedEncoding.set('?'); dontNeedEncoding.set(':'); dontNeedEncoding.set('@'); dontNeedEncoding.set('-'); dontNeedEncoding.set('_'); dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); dontNeedEncoding.set('!'); dontNeedEncoding.set('$'); dontNeedEncoding.set('&'); dontNeedEncoding.set('('); dontNeedEncoding.set(')'); dontNeedEncoding.set('/'); dontNeedEncoding.set('*'); dontNeedEncoding.set('+'); dontNeedEncoding.set(','); dontNeedEncoding.set(';'); dontNeedEncoding.set('='); } public static String encode(String url) { return encode(url, dfltEncName); } public static String encode(String urlString, String encoding) { try { URL url = new URL(urlString); StringBuilder urlStrBuilder = new StringBuilder(); int port = url.getPort(); String path = url.getPath(); String query = url.getQuery(); urlStrBuilder.append(url.getProtocol()) .append("://") .append(url.getHost()) .append(port > 0 ? ":" + port : ""); if (path != null && !path.isEmpty()) { path = encodeString(path, encoding); urlStrBuilder.append(path); } if (query != null && !query.isEmpty()) { query = encodeString(query, encoding); urlStrBuilder.append("?").append(query); } return urlStrBuilder.toString(); } catch (Exception e) { return urlString; } } private static String encodeString(String s, String enc) throws UnsupportedEncodingException { boolean needToChange = false; StringBuffer out = new StringBuffer(s.length()); Charset charset; CharArrayWriter charArrayWriter = new CharArrayWriter(); if (enc == null) throw new NullPointerException("charsetName"); try { charset = Charset.forName(enc); } catch (IllegalCharsetNameException e) { throw new UnsupportedEncodingException(enc); } catch (UnsupportedCharsetException e) { throw new UnsupportedEncodingException(enc); } for (int i = 0; i < s.length();) { int c = (int) s.charAt(i); if (dontNeedEncoding.get(c)) { out.append((char) c); i++; } else { do { charArrayWriter.write(c); if (c >= 0xD800 && c <= 0xDBFF) { if ((i + 1) < s.length()) { int d = (int) s.charAt(i + 1); if (d >= 0xDC00 && d <= 0xDFFF) { charArrayWriter.write(d); i++; } } } i++; } while (i < s.length() && !dontNeedEncoding.get((c = (int) s.charAt(i)))); charArrayWriter.flush(); String str = new String(charArrayWriter.toCharArray()); byte[] ba = str.getBytes(charset); for (int j = 0; j < ba.length; j++) { out.append('%'); char ch = Character.forDigit((ba[j] >> 4) & 0xF, 16); if (Character.isLetter(ch)) { ch -= caseDiff; } out.append(ch); ch = Character.forDigit(ba[j] & 0xF, 16); if (Character.isLetter(ch)) { ch -= caseDiff; } out.append(ch); } charArrayWriter.reset(); needToChange = true; } } return (needToChange ? out.toString() : s); } }