使用 URLDecoder 和 URLEncoder 对中文字符进行编码和解码

article/2025/10/7 1:06:04

摘要:

  URLDecoder 和 URLEncoder 用于完成普通字符串 和 application/x-www-form-urlencoded MIME 字符串之间的相互转换。在本文中,我们以使用URLDecoder解决GET请求中文乱码问题为场景说明 URLDecoder/URLEncoder 的用法,并给出了 application/x-www-form-urlencoded MIME 字符串的编码规则。


一. URLDecoder/URLEncoder 使用场景概述

  URLDecoder 和 URLEncoder 用于完成普通字符串 和 application/x-www-form-urlencoded MIME 字符串之间的相互转换。在介绍 application/x-www-form-urlencoded MIME 字符串之前,我们先考虑如下场景,如下图所示:

            URL.png-14.8kB

  我们知道,在我们向客户端发起请求时,浏览器会根据请求URL生成相应的请求报文发送给服务器。在这个过程中,如果我们在浏览器中的地址栏中所输入的URL包含中文字符时,浏览器首先会将这些中文字符进行编码然后再发送给服务器。实际上,浏览器会将它们转换为 application/x-www-form-urlencoded MIME 字符串,如下图所示:

            转码.png-48.7kB

  更确切的,当URL地址里包含非西欧字符的字符串时,浏览器都会将这些非西欧字符串转换成application/x-www-form-urlencoded MIME 字符串。在开发过程中,我们可能涉及将普通字符串和这种特殊字符串的相关转换,这就需要使用 URLDecoder 和 URLEncoder类进行实现,其中:

  • URLDecoder类包含一个decode(String s,String enc)静态方法,它可以将application/x-www-form-urlencoded MIME字符串转成普通字符串;

  • URLEncoder类包含一个encode(String s,String enc)静态方法,它可以将普通字符串转换成application/x-www-form-urlencoded MIME字符串。

下面程序示范了普通字符串转与 application/x-www-form-urlencoded MIME 字符串之间的转化。

public class URLDecoderTest {public static void main(String[] args) throws Exception {// 将application/x-www-form-urlencoded字符串转换成普通字符串// 其中的字符串直接从上图所示窗口复制过来,chrome 默认用 UTF-8 字符集进行编码,所以也应该用对应的字符集解码System.out.println("采用UTF-8字符集进行解码:");String keyWord = URLDecoder.decode("%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6+Rico", "UTF-8");System.out.println(keyWord);System.out.println("\n 采用GBK字符集进行解码:");System.out.println(URLDecoder.decode("%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6+Rico", "GBK"));// 将普通字符串转换成application/x-www-form-urlencoded字符串System.out.println("\n 采用utf-8字符集:");String urlStr = URLEncoder.encode("天津大学", "utf-8");System.out.println(urlStr);System.out.println("\n 采用GBK字符集:");String urlStr2 = URLEncoder.encode("天津大学", "GBK");System.out.println(urlStr2);}
}/* Output: 采用UTF-8字符集进行解码:天津大学 Rico采用GBK字符集进行解码:澶╂触澶у Rico采用utf-8字符集:%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6采用GBK字符集:%CC%EC%BD%F2%B4%F3%D1%A7*///:~

  特别地,仅包含西欧字符的普通字符串和application/x-www-form-urlencoded MIME字符串无须转换,而包含中文字符的普通字符串则需要转换,转换的方法是每个中文字符占2个字节,每个字节可以转换成2个十六进制的数字,所以每个中文字符将转换成“%XX%XX”的形式。当然,采用不同的字符集时,每个中文字符对应的字节数并不完全相同,所以使用URLEncoder和URLDecoder进行转换时也需要指定字符集。特别地,字符串应以同样的字符集进行编码和解码,否则会产生意想不到的结果,如上述程序示例所示。


二. 解决GET请求中文乱码问题

  URLDecoder的一个应用场景就是解决GET请求的中文乱码问题,如下述代码所示:

<%@page import="java.net.URLDecoder"%>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head><title>Test</title>
</head>
<body><%String param1 = request.getQueryString();String param2 = URLDecoder.decode(param1, "utf-8");out.print(param2.split("=")[1] + "<br>");%>
</body>
</html>

  特别需要注意的是,使用此方式对GET请求参数进行解码时,我们必须先对 request.getQueryString 方法的返回值(例如,“name=摩羯西门吹雪”)进行解码,然后再从中取出我们所需要的参数值。如果先取出参数值,然后再对参数值进行解码,则我们将得到乱码,如下图所示:

            乱码.png-21.5kB

  此外,对于包含中文字符的POST请求参数,我们只需在获取请求参数前通过以下代码语句进行转码即可:

    request.setCharacterEncoding("utf-8");

三. URLEncoder & URLDecoder

  对 String 编码时,使用以下规则:

  • 字母、数字和字符, “a” 到 “z”、”A” 到 “Z” 和 “0” 到 “9” 保持不变;
  • 特殊字符 “.”、”-“、”*” 和 “_” 保持不变;
  • 空格字符 ” ” 转换为一个加号 “+”。

除此之外,所有的其他字符都是不安全的。因此需要使用一些编码机制将它们转换为一个或多个字节,每个字节用一个包含 3 个字符的字符串 “%xy” 表示,其中 xy 为该字节的两位十六进制表示形式,推荐的编码机制是 UTF-8。例如,使用 UTF-8 编码机制,字符串 “The string ü@foo-bar” 将转换为 “The+string+%C3%BC%40foo-bar”,因为在 UTF-8 中,字符 ü 编码为两个字节,C3 (十六进制)和 BC (十六进制),字符 @ 编码为一个字节 40 (十六进制)。

 关于 URLDecoder 类的使用,转换过程正好与 URLEncoder 类使用的过程相反,此不赘述。


  关于JSP中文乱码更多的介绍,包括 页面乱码、参数乱码、表单乱码、源文件乱码 等知识,见我的另外两篇博客:《JSP中文乱码问题终极解决方案(上)》 和 《JSP中文乱码问题终极解决方案(下)》。


引用

使用URLDecoder和URLEncoder对中文进行处理


http://chatgpt.dhexx.cn/article/KUuMO4pQ.shtml

相关文章

URLEncode

目录 转换规则那哪些字符是需要转化的呢&#xff1f;和编码无关结论 参考 转换规则 urlencode&#xff1a;返回字符串&#xff0c;此字符串中除了-_.之外的所有非字母数字字符都将被替换成百分号&#xff08;%&#xff09;后跟两位十六进制数&#xff0c;空格则编码为加号&…

在线URLEncode编码,URLDecode解码工具

在线URLEncode编码&#xff0c;URLDecode解码工具 在线URLEncode编码&#xff0c;URLDecode解码工具 本工具支持对URL进行编码和解码&#xff0c;纯客户端计算&#xff0c;数据不会上传到服务器中&#xff0c;请放心使用。 https://tooltt.com/urlencode/

URL编码(encode)和URL解码(decode)

由于URL中支持的字符是有限的&#xff0c;所以一些特殊字符&#xff08;比如说&#xff1a;&、空格、加号等&#xff09;和中文需要经过URL编码。 URL编码的大体过程&#xff1a; 1、将字符经过一定的字符集&#xff08;通常是UTF-8&#xff09;编码 比如&#xff1a;&a…

URLDecoder和URLEncoder的使用总结

其实&#xff0c;这两个类的使用并不复杂&#xff0c;URLDecoder和URLEncoder它的作用主要是用于普通字符串和application/x-www-form-rulencoded MIME字符串之间的转换&#xff0c;一般的人会以为后一个字符串比较专业&#xff0c;以为有什么高深的知识&#xff0c;其实不然&a…

详解HTTP GET请求

实例1&#xff1a;NodeMcu通过TCP实现HTTP GET请求&#xff08;无请求主体&#xff09; srv net.createConnection(net.TCP, 0) srv:on("receive", function(sck, c) print(c) end) srv:connect(80,"fanyi.youdao.com") srv:on("connection", …

我是如何实现HttpGet请求传body参数的!

前言 最近调用公司项目一个接口时&#xff0c;发现该接口是一个Get请求&#xff0c;入参在Body 中&#xff08;json格式&#xff09;。场景如下&#xff1a;A服务需发送http请求调用B服务的接口&#xff08;该接口为Get方式&#xff0c;入参是一个json字符串在body中传递&…

使用CloseableHttpClient 模拟发送HttpGet和HttpPost请求

项目中经常会用到模拟Http请求&#xff0c;而jdk 下的 rt.jar核心库中也有 java.net提供了这方面的功能&#xff0c;但是总体而言&#xff0c;功能还是缺少灵活性和全面性&#xff0c;HttpClient的出现就是弥补了其缺失的功能。HttpClient不是浏览器客户端&#xff0c;而是一个…

python实现http get请求

接口请求方式为get请求&#xff0c;如下图抓包查看 Python实现脚本请求接口并以中文打印接口返回的数据 遇到问题没人解答&#xff1f;小编创建了一个Python学习交流QQ群&#xff1a;778463939 寻找有志同道合的小伙伴&#xff0c;互帮互助,群里还有不错的视频学习教程和PDF电…

我是如何实现HttpGet请求传body参数的?

点击关注公众号&#xff0c;利用碎片时间学习 前言 最近调用公司项目一个接口时&#xff0c;发现该接口是一个Get请求&#xff0c;入参在Body 中&#xff08;json格式&#xff09;。 场景如下&#xff1a;A服务需发送http请求调用B服务的接口&#xff08;该接口为Get方式&#…

HTTP get方式传json

文章目录 一、背景&#xff1f;二、尝试的过程1.postman(成功)2.hutool(失败)3.AsyncHttpClient(成功) 总结 一、背景&#xff1f; 最近项目中有个三方接口,需要使用get请求传递json, 这个让人有点懵,一般来说get参数都会直接拼接在url后, 复杂的参数都使用post方式传递, 尝试…

HTTP GET请求的最大长度?

HTTP GET请求的最大长度是多少&#xff1f; 是否定义了一个响应错误&#xff0c;如果服务器收到超过此长度的GET请求&#xff0c;服务器可以/应该返回该错误&#xff1f; 更新&#xff1a;如标记中所示&#xff0c;这是在Web服务API的上下文中&#xff0c;尽管也很有趣地看到了…

Arduino ESP32 获取网络数据(HTTP GET方式)

Arduino ESP32 获取网络数据(HTTP GET方式) 相关篇《Arduino ESP32 获取网络数据(HTTP POST方式)》《Arduino ESP32 获取网络数据(HTTP PATCH方式)》《Arduino ESP32 获取网络数据(HTTP PUT方式)》 本实例介绍&#xff0c;ESP32通过联网&#xff0c;访问指定服务器网站&#xf…

HTTP - get/post请求详解与本质区别总结

前言 在客户机和服务器之间进行请求、响应时&#xff0c;两种最常被用到的方法是&#xff1a;get和post。 get&#xff1a;从指定的资源请求数据&#xff08;从服务器获取数据&#xff09; post&#xff1a;向指定的资源提交要被处理的数据&#xff08;向服务器传送数据&#…

transferTo源码分析

transferTo源码分析 如图

netty(五) 【 transferTo 零拷贝实例】

前言&#xff1a; 在linux 中 transferTo 方法就可以完成传输&#xff0c;在 windows 中依次调用transferTo最多能传8M文件&#xff0c;需要分段传文件&#xff0c;而且要注意传输起点位置 模拟服务端实验源码&#xff1a; package com.dev.nio.TRANSFERTO;import java.io.IO…

MultipartFile的transferTo方法的坑

前言 最近用SpringBoot写文件上传功能&#xff0c;使用参数绑定之后确实是非常的方便了。但是&#xff0c;项目部署就出现了问题&#xff0c;搞得我一脸懵逼。后来&#xff0c;才发现是因为我使用了相对路径导致的&#xff0c;这个绝对是一个坑人的地方&#xff0c;不过也说明需…

通过零拷贝进行有效的数据传输(java、c)

目录 日期转移&#xff1a;传统方法 数据传输&#xff1a;零复制方法 构建文件服务器 性能比较 概要 相关阅读 许多Web应用程序提供大量的静态内容&#xff0c;这相当于从磁盘上读取数据并将完全相同的数据写回响应套接字。该活动似乎需要较少的CPU活动&#xff0c;但效率…

NIO中的零拷贝--transferTo

1、我们说零拷贝&#xff0c;是从操作系统的角度来说的。因为内核缓冲区之间&#xff0c;没有数据是 重复的&#xff08;只有 kernel buffer 有一份数据&#xff09;。 2、零拷贝不仅仅带来更少的数据复制&#xff0c;还能带来其他的性能优势&#xff0c;例如更少的上下 文切…

使用transferTo上传文件容器为jetty的问题

报错 springboot 内嵌的 tomcat替换jetty 9.4.44 后出现的问题。 jetty容器使用transferTo 上传问题会提示找不到文件。 ava.io.FileNotFoundException: C:\Users\XXX\AppData\Local\Temp\D:\workspace\1675246694267.xlsx(文件名、目录名或卷标语法不正确。) 跟进代码发现 是下…

Java很简单的文件上传(transferTo方式)

采用file.Transto 来保存上传的文件&#xff0c;代码简单&#xff0c;速度快. package com.springbootemaildemo.controller;import com.springbootemaildemo.entity.ResponseEntity; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import…