jsp是什么格式(jsp是网页文件吗)

1.ASCII代码#20世纪60年代,美国制定了一套字符编码,对英文字符和二进制数字的关系做出了统一规定。这就是所谓的ASCII码,一直沿用至今。ASCII码共

1.ASCII代码#

20世纪60年代,美国制定了一套字符编码,对英文字符和二进制数字的关系做出了统一规定。这就是所谓的ASCII码,一直沿用至今。ASCII码共指定128个字符,如空大小写“空格”为32(二进制0010000),大写字母A为65(二进制01000001)。这128个符号(包括32个不能打印的控制符号)只占一个字节的后7位,前1位统一规定为0。0~31是换行、回车、删除等控制字符。、32~126为打印字符,可通过键盘输入并显示。

用英语128个符号编码就够了,但表示其他语言就不够了。比如在法语中,如果一个字母上面有音标,就不能用ASCII码表示。因此,一些欧洲国家决定使用字节中空闲的最高位来编译新的符号。例如,法语中é的代码是130(二进制10000010)。这样,这些欧洲国家使用的编码系统可以表示多达256个符号。

然而,这里又出现了新的问题。不同的国家有不同的字母,所以即使都用256个符号,代表的字母也不一样。例如,130在法语代码中代表é,但在希伯来语代码中它代表字母Gimel (ג),在俄语代码中它代表另一个符号。但是在所有这些编码方式中,0-127的符号都是一样的,唯一的区别就是128-255这一段。

至于亚洲国家的文字,使用的符号比较多,大概有10万个汉字。一个字节只能代表256种符号,肯定不够。您必须使用多个字节来表示一个符号。比如简体中文常用的编码方式是GB2312,用两个字节表示一个汉字,所以理论上最多可以表示65536个符号。

2.Unicode编码#

可以想象,如果有一个代码,世界上所有的符号都会包含在里面。每个符号被赋予一个唯一的代码,那么上述问题将不会发生。Unicode就是这样一种编码。

Unicode是一个很大的字符集合,现在它可以容纳超过一百万个符号。每个符号的编码是不同的。比如U+0639代表阿拉伯字母Ain,U+0041代表英文大写字母A,U+4E25代表汉字“颜”。

需要注意的是,Unicode只是一个符号集。它只指定了一个符号的二进制代码,但没有指定这个二进制代码应该如何存储。这产生了两个问题:

第一个问题是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

记住,Unicode只是映射字符和数字的标准。对支持的字符数量没有限制,也不要求字符占用两个、三个或任何其他数量的字节。Unicode字符如何在内存中编码成字节是另一个话题。它是由UTF (Unicode转换格式)定义的。

3.UTF 8编码#

随着互联网的普及,迫切需要一种统一的编码方法。UTF-8是互联网上使用最广泛的unicode实现之一。其他的实现还有UTF-16和UTF-32,但是在互联网上基本不用。同样,这里的关系是UTF-8是Unicode的实现之一。

UTF-8 (8位Unicode转换格式)是Unicode的可变长度字符编码,也称为通用代码。由肯·汤普森于1992年创立。现在它已经被标准化为RFC 3629。UTF-8用1到4个字节编码Unicode字符。在网页上,简体和繁体中文以及其他语言(如英语、日语和韩语)可以在统一的页面中显示。

UTF-8最大的特点之一是它是一种可变长度的编码方法。它可以用1~4个字节来表示一个符号,字节长度可以根据符号的不同而变化(UTF-8码可以容纳2个21字符,共计200多万个字符)。

UTF-8的编码规则很简单,只有两条:

对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

下表总结了编码规则。字母X表示可以编码的位数。

Unicode符号范围| UTF-8编码方法

UTF字节数(十六进制)|(二进制)

- .

两个字节0000 0080-0000 07FF | 110 xxxxx 10 xxxxx

三个字节0000 0800-0000 FFFF | 1110 xxxxx 10 xxxxx 10 xxxxx

四个字节0001 0000-0010 ffff | 11110 xxxxx 10 xxxxx 10 xxxxx 10 xxxxx

这里,以汉字“颜”为例,演示如何实现8编码。

已知“颜”的unicode是4E25(100111000100101)。根据上表可以发现,4E25在第三行的范围内(0000800-0000FFFF),所以“颜”的8编码需要三个字节,即格式为“1110xxxx 10xxxxxx 10xxxxxx”。然后从“颜”的最后一个二进制位开始,从后向前依次填入格式中的X,多余的位用0填充。这样,“严格”的UTF-8码就是“11100100 1011000 10100101”,换算成十六进制就是E4B8A5。

4.UTF8、UTF16和UTF32 #的区别

首先我们要确定一个概念就是Unicode是一个字符集,它为世界上所有的字符定义了一个唯一的代码。它只规定了每个符号的二进制码,没有制定详细的存储规则。UTF-8、UTF-16和UTF-32是Unicode的存储格式定义。(举一个交流中的例子作为比较。一个信号(类比称为Unicode编码)会被不同的编码方法编码成不同的高低信号。)

UCS-2和UCS-4#

Unicode的诞生是为了整合世界上所有的语言。任何文本都对应于Unicode中的一个值,该值称为代码点。代码的值通常以U+ABCD的格式书写。而字与码点的对应关系是UCS-2(用2个八位字节编码的通用字符集)。顾名思义,UCS-2是用两个字节表示的码位,取值范围是U+0000 ~ U+FFFF。

为了表达更多的词,人们提出了UCS-4,即用四个词段来表示码点。其范围为U+0000000 ~ U+7FFFFFF,其中U+000000 ~ U+0000 FFFF与UCS-2相同。

注意,UCS-2和UCS-4只规定了码位和字符的对应关系,没有规定码位在计算机中的存储方式。指定的存储模式被称为UTF (Unicode转换格式),其中UTF-16和UTF-8被广泛使用。

4.2 UTF-16#

RFC2781规定了UTF-16。它使用两个字节来表示一个代码点。不难猜测,UTF-16完全对应UCS-2,即UCS-2指定的码位直接用Big Endian或Little Endian保存。UTF-16包括三种类型:UTF-16、UTF-16BE(大端)和UTF-16LE(小端)。UTF-16BE和UTF-16LE并不难理解,而UTF-16则需要在文件开头使用一个名为BOM(字节顺序标记)的字符来表示文件是大端还是小端。就是人物BOM U+FEFF。实际上,BOM是一个聪明的想法。UCS-2没有定义U+FEFF,所以只要有FF FE或FEFF这样的字节序列,就可以看作是u+FE FF,可以判断是大端还是小端。

BOM(字节顺序标记)用在文档的开头,告诉读者文档的字节顺序。UTF-8不需要BOM来表示字节顺序,但是可以用BOM来表示编码方式。字符“零宽度不间断空格”的UTF-8编码是EF BB BF。因此,如果接收器接收到以EF BB BF开始的字节流,它知道这是UTF-8编码。只有UTF-16需要添加bom。因为是unicode顺序编码,在BMP范围内是两个字节,所以需要识别是大字节顺序还是小字节顺序。

低位和高位。

低位字节序和高位字节序只是关于在内存中存储和读取一个字节(称为字)的约定。这意味着,当您让计算机使用UTF-16在内存中存储字母A(占用两个字节)时,您使用的endian方案决定了您是将第一个字节放在第二个字节之前还是之后。这个有点难理解。让我们看一个例子:当你用UTF-16保存某一段内容时,它的后半部分在不同的系统中可能是这样的:

00 68 00 65 00 6C 00 6C 00 6F(高字节顺序,高字节在前)

68 00 65 00 6C 00 6C 00 6F 00低位字节顺序,低位字节在前)

端序方案只是微处理器架构师的偏好。例如,英特尔使用低位字节序,摩托罗拉使用高位字节序。

比如说。以各种方式编码的三个字符“ABC”的结果如下:

jsp是什么格式(jsp是网页文件吗)插图

4.3 UTF-32#

UTF-32使用四个单词段来表示码位,这样就可以完整地表示UCS-4的所有码位,而不需要使用像UTF-16这样复杂的算法。与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE和UTF-32LE,UTF-32也需要BOM字符。

4.4文本编辑器如何知道文本#的编码

当一个软件打开一个文本时,它要做的第一件事就是决定用哪个字符集的哪个代码来保存文本。通常,软件采用三种方式来确定文本的字符集和编码:

检测文件头标识(BOM)EF BB BF UTF-8 FE FF UTF-16/UCS-2, big endian FF FE UTF-16/UCS-2, little endian FF FE 00 00 UTF-32/UCS-4, little endian. 00 00 FE FF UTF-32/UCS-4, big-endian.软件自己根据编码规则猜测当前文件的编码提示用户自己输入当前文件的编码

5.GBK、GB2312和GB18030 #的区别

GB2312是ASCll码的扩展,占用两个字节。一个小于127的字符和之前的意思一样,但是两个大于127的字符连在一起就是一个汉字的意思。第一个字节(他称之为高字节)从0xA1到0xF7,最后一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出7000多个简体字。在这些代码中,我们还包括数学符号、罗马和希腊字母以及日语假名。甚至已经是ASCII码的数字、标点符号和字母都被重新编码为两个字节长。这通常被称为“全角”字符,而127号以下的字符被称为“半角”字符。

GB2312能代表的字符还是不够,于是GBK出现了。GBK是GB1212的扩展,也占用2个字节。GBK不再要求低位字节必须是127号之后的内码,只要第一个字节大于127号,就是一个汉字的开头,不管后面有没有扩展字符集的内容。因此,扩展编码方案被称为GBK标准。《GBK》收录了GB2312的全部内容,同时新增汉字(包括繁体字)和符号近2万个。

GB18030采用变长编码,可以是1字节、2字节、4字节。它是GB2312和GBK的扩展,并且与两者完全兼容。

经过上面的介绍,我们可以看到Unicode是一个世界标准,对世界上所有的语言符号都做了一个编码表,而GBK、GB2312等。主要是码汉字。

6.Java #中的编码问题

我们知道,涉及编码的地方一般是字符到字节或者字节到字符的转换,而需要这种转换的场景主要是在I/O的时候,包括磁盘I/O和网络I/O,而I/O造成的乱码大部分是网络I/O..

从用户的浏览器发起一个HTTP请求,代码需要存在的地方是URL、Cookie和参数。服务器收到HTTP请求后,需要解析HTTP协议,其中需要解码URI、Cookie和POST表单参数,服务器还可能需要读取数据库中的数据、本地或网络中的其他文本文件,这些都可能存在编码问题。当Servlet处理完所有请求的数据后,需要将这些数据重新编码,通过Socket发送给用户请求的浏览器,再由浏览器解码成文本。这些过程如下图所示:

jsp是什么格式(jsp是网页文件吗)插图(1)

如上图所示,一个HTTP请求需要在很多地方进行编码和解码。它们的编码和解码规则是什么?以下将重点介绍:

URL的编码和解码

用户提交一个URL,其中可能包含中文字符,因此需要对其进行编码。这个网址怎么编码?根据什么规则?怎么解码?将显示以下URL:

jsp是什么格式(jsp是网页文件吗)插图(2)

端口在Tomcat中配置,而上下文路径在中配置,Servlet路径在Web应用的Web.xml中配置。

& ltservlet映射& gt& ltservlet-name & gt;junshanExample & lt/servlet-name & gt;& lturl模式& gt/servlet/servlet/* & lt;/URL-pattern & gt;& lt/servlet-mapping & gt;配置,PathInfo是我们请求的特定Servlet,QueryString是要传递的参数。注意,这里的URL是直接在浏览器中输入的,所以是Get方法请求的。如果是POST方法请求的,QueryString会通过表单提交给服务器,后面会介绍。

上图中出现了中文的PathInfo和QueryString。当我们在浏览器中直接输入这个URL时,我们将如何在浏览器和服务器上编码和解析这个URL?为了验证浏览器如何对URL进行编码,我们选择FireFox浏览器,并观察我们通过HTTPFox插件请求的URL的实际内容。下面是网址:http://localhost:8080/examples/servlet/servlet/junshan?作者=君山在中国火狐3.6.12的测试结果:

jsp是什么格式(jsp是网页文件吗)插图(3)

军山的编码结果分别为E5909B5B1和be fd c9 bd。根据之前的编码,PathInfo是UTF-8,QueryString是GBK编码。为什么会有“%”?查阅URL的编码规范RFC3986可以知道,浏览器编码URL是将非ASCII字符按照一定的编码格式编码成十六进制数字,然后在十六进制表示的每个字节前面加上“%”,这样最终的URL就变成了上图所示的格式。

从上面的测试结果可以看出,浏览器对PathInfo和QueryString的编码是不一样的,不同的浏览器可能会有不同的PathInfo编码,给服务器的解码造成了很大的困难。我们以Tomcat为例,看看Tomcat是如何接收这个URL并解码的。protected void convert uri(message bytes uri,Request request)抛出异常{ ByteChunk BC = uri . getbytechunk();int length = BC . getlength();CharChunk cc = uri . getcharchunk();cc.allocate(长度,-1);string enc = connector . geturiencoding();如果(enc!= null){ B2C converter conv = request . geturi converter();试试{ if (conv == null) { conv =新B2C转换器(enc);request . seturi converter(conv);} } catch (IOException e) {...}如果(conv!= null) { try { conv.convert(bc,cc,cc.getBuffer()。length-cc . getend());uri.setChars(cc.getBuffer()、cc.getStart()、cc . getlength());返回;} catch (IOException e) {...} } } //默认编码:快速转换字节[]bbuf = BC . get buffer();char[]cbuf = cc . get buffer();int start = BC . getstart();for(int I = 0;我& lt长度;i++){ cbuf[I]=(char)(bbuf[I+start]& amp;0x ff);} uri.setChars(cbuf,0,length);}从上面的代码可以知道,用于解码URL的URI部分的字符集是在连接器中定义的。如果未定义,将使用默认代码ISO-8859-1进行解析。因此,如果有中文网址,最好将URIEncoding设置为UTF-8编码。

如何解析查询?GET HTTP请求的QueryString和POST HTTP请求的表单参数保存为参数,参数值通过request.getParameter获取..首次调用request.getParameter方法时,会对它们进行解码。调用request.getParameter方法时,会调用org . Apache . catalina . connector . request的parseParameters方法。该方法将对GET和POST传递的参数进行解码,但它们的解码字符集可能不同。POST表单的解码将在后面介绍。QueryString的解码字符集是在哪里定义的?通过HTTP的头传输到服务器,也在URL中。它和URI的解码字符集一样吗?从之前浏览器对PathInfo和QueryString的不同编码格式可以猜测解码后的字符集肯定不会一致。确实如此。QueryString的解码字符集要么是在头的ContentType中定义的字符集,要么是默认的ISO-8859-1。要使用ContentType中定义的编码,需要将连接器中的useBodyEncodingForURI设置为true。这个配置项的名称有点混乱。它不使用BodyEncoding来解码整个URI,而是仅使用BodyEncoding来解码QueryString。这一点要注意。

从上面的URL编解码过程来看,比较复杂,在应用中编解码并不是完全由我们控制的。因此,我们应该尽量避免在应用程序的URL中使用非ASCII字符,否则我们很可能会遇到乱码。当然,最好在我们的服务器中设置两个参数,URIEncoding和useBodyEncodingForURI。

HTTP报头的编码和解码

当客户端发起HTTP请求时,除了上述URL之外,还可能在头中传递其他参数,如Cookie和redirectPath。这些用户设置的值也可能有编码问题。Tomcat是如何解码它们的?

对头中的项进行解码也是通过调用request.getHeader完成的,如果请求的头项没有解码,调用MessageBytes的toString方法。这个方法从byte转换成char使用的默认编码是ISO-8859-1,我们无法设置头的其他解码格式,所以如果你在头中设置非ASCII字符进行解码,肯定会出现乱码。

当我们添加标题时,情况也是如此。不要在标题中传递非ASCII字符。如果必须要传递的话,可以先用org . Apache . catalina . util . urlencoder对这些字符进行编码,然后添加到头中,这样就不会在从浏览器到服务器的传输过程中丢失信息。如果我们能够访问这些项目,然后根据相应的字符集对它们进行解码,那该多好啊。

POST格式的编码和解码

如前所述,对POST表单提交的参数的解码发生在第一次调用request.getParameter时。POST表单的参数传递方式与QueryString不同,通过HTTP的主体传递给服务器。当我们点击页面上的提交按钮时,浏览器会先按照ContentType的Charset编码格式对表单中填写的参数进行编码,然后提交给服务器,在服务器上也是由ContentType的字符集进行解码。所以通过POST表单提交的参数一般没有问题,而且这个字符集编码是我们自己设置的,可以通过request . setcharacterencoding(charset)来设置。

另外,对于multipart/form-data类型的参数,也就是上传的文件代码也是用ContentType定义的字符集编码的。值得注意的是,上传的文件以字节流的形式传输到服务器的本地临时目录。这个过程不涉及字符编码,真正的编码是将文件内容添加到参数中。如果无法使用此编码进行编码,将使用默认编码ISO-8859-1进行编码。

HTTP主体的编码和解码

当用户请求的资源已经成功获取后,这些内容会通过Response返回给客户端浏览器,浏览器对这些内容进行编码,然后进行解码。这个流程的编解码器字符集可以通过response.setCharacterEncoding设置,它会覆盖request.getCharacterEncoding的值,并通过Header的Content-Type返回给客户端。当浏览器接收到返回的套接字流时,它将被Content-Type的字符集解码。如果在返回的HTTP头的Content-Type中没有设置字符集,浏览器将根据Html中的字符集进行解码。如果未定义,浏览器将使用默认编码对其进行解码。

编码中需要注意的其他地方。

除了URL和参数编码,服务器端很多地方可能还有编码,比如读取xml、velocity模板引擎、JSP或者从数据库读取数据。

Xml文件可以通过设置头来编码。

& lt?xml版本="1.0 "编码="UTF-8 "?& gt设置速度模板的编码格式:

services . velocity service . input . encoding = utf-8 JSP设置编码格式:

& lt% @页content type = " text/html;charset=UTF-8"% >对数据库的访问是通过客户端JDBC驱动程序完成的。用JDBC访问数据要和数据的内置编码一致,可以通过设置JDBC URL来制定,比如MySQL:

URL = " JDBC:MySQL://localhost:3306/DB?useUnicode = true & ampCharacterEncoding=GBK"8。乱码分析#

让我们来看看。当我们遇到一些乱码的时候,应该如何处理这些问题?乱码问题的唯一原因是在字符到字节或字节到字符的转换中编码和解码的字符集不一致。由于一次操作往往涉及多次编码和解码,当出现乱码时,很难找出哪个环节出了问题。根据我自己的经验,从源头一步步查原因是最快的方法。

9.参考编号

编码博客

为什么Java最多只能识别65535个字符?

Unicode本身只是一个标准,不是具体的实现,字节数也没有限制。目前实用的Unicode版本对应的是UCS-2,采用16位编码空,所以最多可以表示65535个字符。Unicode在发展,6万字符真的不够用。事实上,Unicode现在支持超过100,000个字符(第100个字符在2005年被采用为马拉雅拉姆语。当前的Unicode版本是6.3,制定于2013年9月30日。UCS-2仍然在Java中使用。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

作者:美站资讯,如若转载,请注明出处:https://www.meizw.com/n/114996.html

发表回复

登录后才能评论