[字符集與編碼 2] 編碼 解碼 亂碼

編碼規(guī)則

如果你已經(jīng)閱讀了JavaHipster 1中references提到的兩篇文章桥胞,你應(yīng)該明白:從字符集到編碼規(guī)則的過(guò)程奋救,實(shí)際上就是從字符集-->到編號(hào)-->到編碼的過(guò)程滤蝠。
關(guān)于編碼規(guī)則稿辙,主要關(guān)注兩個(gè)方面:

  • 所遵循的字符集
  • 存儲(chǔ)方式:使用幾個(gè)字節(jié)來(lái)存儲(chǔ)字符

ASCII編碼規(guī)則

  • 遵循ASCII字符集航厚,共含有255個(gè)字符(有很多字符是保留字符)
  • 使用1個(gè)字節(jié)存儲(chǔ)(定長(zhǎng))

ISO8859-1編碼規(guī)則

  • 遵循ISO8859-1字符集顷歌,共含有255個(gè)字符。
  • 使用1個(gè)字節(jié)存儲(chǔ)(定長(zhǎng))
  • ISO8859-1兼容ASCII幔睬,也就是說(shuō)眯漩,對(duì)于同樣的字符,ASCII與ISO8859-1對(duì)應(yīng)的編號(hào)(也成為code point碼點(diǎn))都是一樣的麻顶。

GB2312編碼規(guī)則

  • 遵循GB2312字符集赦抖,支持常見(jiàn)的中文。
  • 使用1個(gè)字節(jié)存儲(chǔ)英文和數(shù)字等字符辅肾,使用2個(gè)字節(jié)存儲(chǔ)中文字符队萤。
  • GB2312兼容ASCII。

GBK編碼規(guī)則

  • 遵循GBK字符集矫钓,支持常見(jiàn)的中文要尔,罕見(jiàn)中文,繁體中文新娜,日文的假名赵辕。
  • 使用1個(gè)字節(jié)存儲(chǔ)英文和數(shù)字等字符,使用2個(gè)字節(jié)存儲(chǔ)中文字符概龄。
  • GBK兼容ASCII與GB2312还惠。

UTF-16編碼規(guī)則

  • 遵循Unicode字符集。支持地球上所有常見(jiàn)的自然語(yǔ)言私杜。
  • 使用2個(gè)字節(jié)存儲(chǔ)各種語(yǔ)言的常用字符吸重,使用4個(gè)字節(jié)存儲(chǔ)其他罕見(jiàn)字符互拾。
  • UTF-16并不兼容ASCII或者ISO8859-1,原因是UTF-16使用2個(gè)字節(jié)表示英文和西歐字符嚎幸。
  • 使用UTF-16編碼的文件,在文件頭部均含有BOM寄猩,以說(shuō)明這個(gè)文件使用大端法還是小端法進(jìn)行存儲(chǔ)嫉晶。
  • 在有一些文本編輯器中(比如notepad++),會(huì)把UTF-16稱為UCS-2田篇。

UTF-8編碼規(guī)則

  • 遵循Unicode字符集替废。支持地球上所有常見(jiàn)的自然語(yǔ)言。
  • 使用1個(gè)字節(jié)存儲(chǔ)英文和數(shù)字等字符泊柬,使用3個(gè)字節(jié)存儲(chǔ)常用中文椎镣,使用4個(gè)字符存儲(chǔ)罕見(jiàn)字符。
  • UTF-8兼容ASCII兽赁,但不兼容UTF-16状答,因?yàn)閁TF-8存儲(chǔ)字符所需的空間與UTF-16是不一樣的。
  • UTF-8默認(rèn)不帶BOM刀崖。最好也不要加上BOM惊科。

ANSI

ANSI嚴(yán)格來(lái)說(shuō)并不是一種編碼規(guī)則,它表示:根據(jù)當(dāng)前操作系統(tǒng)以及操作系統(tǒng)的語(yǔ)言亮钦,選擇對(duì)應(yīng)的編碼規(guī)則進(jìn)行編碼馆截。例如,對(duì)于簡(jiǎn)體中文的Windows操作系統(tǒng)蜂莉,ANSI代表GBK蜡娶。在繁體中文Windows操作系統(tǒng)中,ANSI代表Big5映穗。在日文Windows操作系統(tǒng)中窖张,ANSI代表Shift_JIS 編碼。

文件編碼規(guī)則與JVM編碼規(guī)則

對(duì)于一個(gè)文件而言男公,我們可以顯式的指定文件的編碼規(guī)則荤堪。但當(dāng)文件中的內(nèi)容讀到JVM內(nèi)存中后,將會(huì)采用JVM的編碼規(guī)則進(jìn)行重新編碼和存儲(chǔ)枢赔。例如澄阳,在JVM中,Java的char類型和String類型均強(qiáng)制使用UTF-16進(jìn)行編碼踏拜。因此對(duì)于一個(gè)非UTF-16的文件來(lái)說(shuō)碎赢,在數(shù)據(jù)存儲(chǔ)層面,數(shù)據(jù)依舊采用文件本身的編碼規(guī)則進(jìn)行編碼和存儲(chǔ)速梗。但當(dāng)數(shù)據(jù)讀到JVM中肮塞,將采用UTF-16進(jìn)行編碼和存儲(chǔ)襟齿。

下面的例子將解釋:文件編碼規(guī)則與JVM編碼規(guī)則的區(qū)別

//把下面的代碼分別在UTF-8與UTF-16編碼格式的文件下進(jìn)行測(cè)試
char ch1 = 'c';
Character character1 = new Character(ch1);
System.out.println(character1.SIZE); //(1)

char ch2 = '中';
Character character2 = new Character(ch2);
System.out.println(character2.SIZE); //(2)

String str1 = "a";
System.out.println(str1.length()); //(3)
System.out.println(str1.toCharArray().length);  //(4)
System.out.println(str1.getBytes().length); //(5)

String str2 = "中";
System.out.println(str2.length()); //(6)
System.out.println(str2.toCharArray().length); //(7)
System.out.println(str2.getBytes().length); //(8)

Character.SIZE返回的是JVM中char類型占多少bit。對(duì)于(1)和(2)而言枕赵,在UTF8和UTF16環(huán)境下猜欺,打印結(jié)果均是16bit,即兩個(gè)字符拷窜。原因是:無(wú)論文件采用哪種編碼規(guī)則中开皿,在JVM中,char類型均使用2個(gè)字節(jié)存儲(chǔ)字符篮昧。

String.length()返回的是JVM中字符串所對(duì)應(yīng)的代碼單元長(zhǎng)度赋荆。在Java中,字符串是由char字符數(shù)組所組成的懊昨,因此在JVM中字符串也使用UTF16進(jìn)行存儲(chǔ)窄潭。
代碼單元指一種轉(zhuǎn)換格式中最小的一個(gè)分隔,由于UTF16最少使用2個(gè)字節(jié)表示一個(gè)字符酵颁,因此對(duì)于UTF-16而言嫉你,1個(gè)代碼單元等價(jià)于2個(gè)字節(jié)。而對(duì)于UTF-8而言材义,1個(gè)代碼單元等價(jià)于1個(gè)字節(jié)均抽。
對(duì)于(3)和(6)而言,無(wú)論文件使用UTF8還是UTF16進(jìn)行編碼存儲(chǔ)其掂,在JVM中油挥,String均使用UTF-16進(jìn)行存儲(chǔ),因此打印結(jié)果都是1款熬,即一個(gè)代碼單元(UTF-16使用2個(gè)字節(jié)存儲(chǔ)英文和常見(jiàn)中文)深寥。

String.toCharArray().length返回的是:JVM中字符串對(duì)應(yīng)的字符數(shù)組的數(shù)組長(zhǎng)度。由于1個(gè)char便能表示英文和常見(jiàn)中文贤牛。因此對(duì)于(4)和(7)惋鹅,無(wú)論文件使用UTF8還是UTF16進(jìn)行編碼存儲(chǔ),在JVM中均使用UTF16進(jìn)行存儲(chǔ)殉簸,所以返回的數(shù)組長(zhǎng)度均是1

String.getBytes()方法返回的是:字符串在數(shù)據(jù)存儲(chǔ)層面所占的字節(jié)數(shù)闰集。注意:當(dāng)getBytes()方法不含參數(shù)時(shí),則表明遵循文件所采用的編碼規(guī)則般卑。
對(duì)于(5)來(lái)說(shuō)武鲁,如果文件采用UTF8進(jìn)行編碼存儲(chǔ),則返回1蝠检,即UTF8使用1個(gè)字節(jié)存儲(chǔ)英文沐鼠。如果采用UTF16進(jìn)行編碼,則返回4,原因是UTF16采用2個(gè)字節(jié)存儲(chǔ)英文饲梭,另外2個(gè)字節(jié)用于存儲(chǔ)BOM乘盖。對(duì)于(8)來(lái)說(shuō),如果文件采用UTF8進(jìn)行編碼存儲(chǔ)憔涉,則返回3订框,即UTF8使用3個(gè)字節(jié)存儲(chǔ)中文。如果采用UTF16進(jìn)行編碼兜叨,則返回4布蔗,原因是UTF16采用2個(gè)字節(jié)存儲(chǔ)中文,另外2個(gè)字節(jié)用于存儲(chǔ)BOM浪腐。

亂碼的本質(zhì)

亂碼的本質(zhì)就是:編碼與解碼所采用的編碼規(guī)則不一致

如果你未能清晰的理解什么是編碼,什么是解碼顿乒,請(qǐng)看下面這張神圖:

編碼與解碼的神圖

從右到左的這個(gè)過(guò)程就是編碼议街,從左到右的這個(gè)過(guò)程就是解碼。下面通過(guò)兩個(gè)例子進(jìn)一步說(shuō)明璧榄。

編碼與解碼的例子

//類文件本身采用UTF-8格式
String str1 = "中"; //編碼
System.out.println(str1); //解碼

第一行代碼表示編碼的過(guò)程:

  1. 把"中"字讀到JVM內(nèi)存中特漩,在JVM中,String類型使用UTF-16進(jìn)行編碼骨杂。
  2. 由于文件本身采用UTF-8格式涂身,因此JVM將負(fù)責(zé)把UTF-16轉(zhuǎn)為UTF-8。
  3. 由于UTF-8遵循Unicode字符集搓蚪,因此再進(jìn)一步把Unicode碼點(diǎn)按照UTF-8的要求進(jìn)行編碼蛤售。(黃色階段)
  4. 最后把二進(jìn)制數(shù)據(jù)保存到文件中。

第二行代碼則表示解碼的過(guò)程:

  1. 把文件中的二進(jìn)制數(shù)據(jù)讀取出來(lái)妒潭。
  2. 由于文件是UTF-8格式悴能,因此采用UTF-8對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行解碼,并得到Unicode碼點(diǎn)雳灾。(黃色階段)
  3. 由于JVM使用UTF-16格式漠酿,因此數(shù)據(jù)讀到JVM后,JVM負(fù)責(zé)轉(zhuǎn)譯谎亩。
  4. 轉(zhuǎn)譯后炒嘲,UTF-16格式的的"中"字被打印到控制臺(tái)。

在上面的兩行代碼中匈庭,由于編碼階段與解碼階段所采用的編碼規(guī)則都是一致的夫凸,所以肯定不會(huì)造成亂碼。

亂碼的例子

String str2 = new String("中".getBytes(), "GBK"); //(1) getBytes()是編碼嚎花, GBK是解碼
System.out.println(str2.toCharArray().length); //lenght=2, 亂碼

/*
亂碼:UTF8使用3字節(jié)存儲(chǔ)一個(gè)中文寸痢,而GBK使用2字節(jié)。
因此GBK把前兩個(gè)字節(jié)作為一個(gè)中文紊选,最后一個(gè)字節(jié)作為另一個(gè)中文啼止。
但由于unicode與GBK的中文碼點(diǎn)不一樣道逗,因此造成亂碼
*/
for(int i=0; i<str2.toCharArray().length; i++) {
    System.out.print(str2.toCharArray()[i]); 
}

/*
由于str2已被解析為2個(gè)亂碼中文字,因此對(duì)于UTF8的存儲(chǔ)格式献烦,需要6個(gè)字節(jié)存儲(chǔ)兩個(gè)中文字    
*/
System.out.println(str2.getBytes().length); //length=6 

在上面的例子中滓窍,str2的值其實(shí)是一個(gè)亂碼。原因是在執(zhí)行第(1)行代碼時(shí)巩那,經(jīng)歷了編碼和解碼兩個(gè)過(guò)程:

  1. 執(zhí)行"中".getBytes();時(shí)吏夯,返回的是"中"字按照文件的編碼格式(即UTF-8)進(jìn)行編碼后的二進(jìn)制數(shù)據(jù)。
  2. new String(XXX, "GBK",)即横;的構(gòu)造函數(shù)則是表示對(duì)上一步獲得的二進(jìn)制數(shù)據(jù)噪生,按照GBK編碼規(guī)則進(jìn)行解碼,已得到對(duì)應(yīng)的字符串东囚。

到這里你應(yīng)該就明白了跺嗽,第一步使用的是UTF-8進(jìn)行編碼,第二步則使用了GBK進(jìn)行解碼页藻,肯定會(huì)造成亂碼啦桨嫁!

常見(jiàn)疑問(wèn)

如何確定不同編碼規(guī)則的兼容性?

可以通過(guò)下面幾個(gè)實(shí)驗(yàn)來(lái)確定(這里主要是說(shuō)兼容英文和數(shù)字):
實(shí)驗(yàn)一:

  1. 在MyEclipse中創(chuàng)建一個(gè)類份帐,右鍵-->properties璃吧,設(shè)置編碼格式為UTF-8(假設(shè)這個(gè)文件不含中文)。
  2. 把這個(gè)文件修改為ASCII废境, ISO8859-1畜挨, GB2312, 你會(huì)發(fā)現(xiàn)該文件均不會(huì)造成亂碼彬坏。也就是說(shuō)對(duì)于英文和數(shù)字朦促,UTF-8與ASCII,ISO8859-1栓始,GB2312是兼容的务冕。
  3. 如果把這個(gè)文件從UTF-8修改為UTF-16格式,你會(huì)發(fā)現(xiàn)文件亂碼幻赚。也就是說(shuō)禀忆,UTF-8與UTF-16是不兼容的。

實(shí)驗(yàn)二:
假設(shè)實(shí)驗(yàn)一中的類是UTF-16格式的(文件不含中文)落恼,修改為UTF-8箩退,ASCII,ISO8859-1佳谦,GB2312戴涝,你會(huì)發(fā)現(xiàn)文件都會(huì)造成亂碼。也就是會(huì)所,UTF-16與UTF-8啥刻,ASCII奸鸯,ISO8859-1,GB2312都不兼容可帽。

UTF-8和UTF-16到底是什么關(guān)系娄涩?

UTF-8與UTF-16均支持Unicode字符集。所以對(duì)于同一個(gè)字符來(lái)說(shuō)映跟,使用UTF-8編碼與UTF-16編碼的碼點(diǎn)都是一樣的蓄拣。例如“中”字均使用20013作為碼點(diǎn)。但是在數(shù)據(jù)存儲(chǔ)層面努隙,UTF-8與UTF-16是不一樣的球恤。例如,我們可以直接把20013轉(zhuǎn)為二進(jìn)制數(shù)字進(jìn)行存儲(chǔ)荸镊,也可以在20013后面加上后綴000碎捺,然后再轉(zhuǎn)為二進(jìn)制進(jìn)行存儲(chǔ)。從這個(gè)例子中便可以知道贷洲,如果不同的編碼規(guī)則實(shí)現(xiàn)了同一個(gè)字符集,那么該字符的碼點(diǎn)應(yīng)該是相同的晋柱,但是在數(shù)據(jù)存儲(chǔ)方面卻不一定相同优构。具體的存儲(chǔ)細(xì)節(jié)詳見(jiàn)References的第一篇

我應(yīng)該使用哪種編碼規(guī)則雁竞?

建議首選UTF-8钦椭。原因如下:

  • 因?yàn)閁TF-8支持所有自然語(yǔ)言,
  • 在存儲(chǔ)空間方面比UTF-16更具有優(yōu)勢(shì)碑诉。
  • 兼容ASCII彪腔,ISO8859-1,方便轉(zhuǎn)換进栽。

什么時(shí)候使用UTF-16?

答:建議永遠(yuǎn)不要選擇UTF-16!因?yàn)閁TF-16含有BOM邻吭,BOM非衬蟠疲坑爹的東西,一不小心就會(huì)造成各種錯(cuò)誤唠帝。而且UTF-8完全可以代替UTF-16屯掖。

為什么使用UTF-16存儲(chǔ)一個(gè)常見(jiàn)中文字符卻占4個(gè)字節(jié)?

答:UTF-16存儲(chǔ)一個(gè)常見(jiàn)中文字符需要2個(gè)字節(jié)襟衰,但是UTF-16本身含有BOM贴铜,BOM也需要占據(jù)2個(gè)字節(jié)。

在哪些地方需要設(shè)置編碼規(guī)則?

  1. 對(duì)于一個(gè)myeclipse項(xiàng)目中绍坝,所有的.java, .jsp, .txt, .xml, .js, .css等常見(jiàn)文件徘意,最好都設(shè)置為UTF-8編碼規(guī)則。
  2. 把tomcat等中間件設(shè)置為UTF-8編碼規(guī)則陷嘴。
  3. 把數(shù)據(jù)庫(kù)設(shè)置為UTF-8編碼規(guī)則映砖。
  4. 對(duì)于接收的參數(shù),比如前端傳過(guò)來(lái)的參數(shù)灾挨,均使用UTF-8進(jìn)行編碼和解碼邑退。

char類型對(duì)中文的支持

Java中的char類型使用2個(gè)字節(jié)表示中文,英文字符劳澄〉丶迹可能有人會(huì)問(wèn):對(duì)于一個(gè)使用UTF-8編碼的類,它使用3個(gè)字節(jié)存儲(chǔ)中文秒拔,但是我們依然可以在這個(gè)類里面莫矗,把中文字符保存到2個(gè)字節(jié)長(zhǎng)度的char類型中,這是為什么呢砂缩?原因是:在數(shù)據(jù)存儲(chǔ)層面作谚,一個(gè)中文字符確實(shí)是按照UTF-8的規(guī)定,以3個(gè)字節(jié)的方式保存在文件中庵芭。但是當(dāng)中文字符被讀到JVM內(nèi)存中妹懒,該字符會(huì)被轉(zhuǎn)為UTF-16,并以2個(gè)字節(jié)的方式保存在JVM內(nèi)存中双吆。簡(jiǎn)單來(lái)說(shuō)就是:在UTF-8文件中眨唬,中文字符以UTF-8進(jìn)行存儲(chǔ),但是讀到JVM內(nèi)存中時(shí)好乐,會(huì)轉(zhuǎn)換成UTF-16進(jìn)行存儲(chǔ)匾竿。另外還需要注意的是,由于char的長(zhǎng)度是2個(gè)字節(jié)蔚万,因此char類型無(wú)法表示罕見(jiàn)中文字符岭妖。

References

  1. http://my.oschina.net/goldenshaw/blog?catalog=536953
  2. http://blog.xieyc.com/common-code-standard-unicode-utf-iso-8859-1-etc/
  3. http://www.regexlab.com/zh/encoding.htm
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市反璃,隨后出現(xiàn)的幾起案子区转,更是在濱河造成了極大的恐慌,老刑警劉巖版扩,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废离,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡礁芦,警方通過(guò)查閱死者的電腦和手機(jī)蜻韭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門悼尾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人肖方,你說(shuō)我怎么就攤上這事闺魏。” “怎么了俯画?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵析桥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我艰垂,道長(zhǎng)泡仗,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任猜憎,我火速辦了婚禮娩怎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胰柑。我一直安慰自己截亦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布柬讨。 她就那樣靜靜地躺著崩瓤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪踩官。 梳的紋絲不亂的頭發(fā)上谷遂,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音卖鲤,去河邊找鬼。 笑死畴嘶,一個(gè)胖子當(dāng)著我的面吹牛蛋逾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窗悯,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼区匣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蒋院?” 一聲冷哼從身側(cè)響起亏钩,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎欺旧,沒(méi)想到半個(gè)月后姑丑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辞友,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年栅哀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了震肮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡留拾,死狀恐怖戳晌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情痴柔,我是刑警寧澤沦偎,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站咳蔚,受9級(jí)特大地震影響豪嚎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屹篓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一疙渣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堆巧,春花似錦妄荔、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至荒揣,卻和暖如春篷角,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背系任。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工恳蹲, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俩滥。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓嘉蕾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親霜旧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子错忱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容