好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

C# utf8编码时转换成shiftjis时出现乱码问题的处理

C# utf8编码时转换成shiftjis时出现乱码问题的处理

最近在做项目时遇到导出CSV文件时,因客户方要求导出CSV文件一定要是shift-jis编码的CSV文件,而我们数据库存储时是unicode储存的,所以导出时会有很多?的编码,这是因为:

借住码表来解释:

Shift_JIS

A

B

C

D

E

F

NUL

SOH

STX

ETX

EOT

ENQ

ACK

BEL

BS

HT

LF

VT

FF

CR

SO

SI

DLE

NAK

SYN

ETB

CAN

EM

SUB

ESC

FS

GS

RS

US

SP

!

"

#

$

%

&

'

(

)

*

+

,

-

.

/

:

;

<

=

>

?

@

A

B

C

D

E

F

G

H

I

J

K

L

M

N

O

P

Q

R

S

T

U

V

W

X

Y

Z

[

]

^

_

`

a

b

c

d

e

f

g

h

i

j

k

l

m

n

o

p

q

r

s

t

u

v

w

x

y

z

{

|

}

~

DEL

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

Shift_JIS 是一个日本电脑系统常用的编码表。它能容纳全形及半形拉丁字母、平假名、片假名、符号及日语汉字。

它被命名为Shift_JIS的原因,是它在放置全形字符时,要避开原本在0xA1-0xDF放置的半角假名字符。

在微软及IBM的日语电脑系统中,即使用了这个编码表。这个编码表称为 CP932 。

节结

以下字元在Shift_JIS使用一个字节来表示。

ASCII字符 (0x20-0x7E),但“/”被“¥”取代

ASCII控制字符 (0x00-0x1F、0x7F)

JIS X 0201标准内的半角标点及片假名(0xA1-0xDF)

在部分操作系统中,0xA0用来放置“不换行空格”。

以下字元在Shift_JIS使用两个字节来表示。

JIS X 0208字集的所有字符

“第一位字节”使用0x81-0x9F、0xE0-0xEF (共47个)

“第二位字节”使用0x40-0x7E、0x80-0xFC (共188个)

使用者定义区

“第一位字节”使用0xF0-0xFC (共47个)

“第二位字节”使用0x40-0x7E、0x80-0xFC (共188个)

在Shift_JIS编码表中,并未使用0xFD、0xFE及0xFF。

在微软及 IBM 的日语电脑系统中,在0xFA、0xFB及0xFC的两字节区域,加入了388个JIS X 0208没有收录的符号和汉字。

因为unicode的很多编码而shift-jis并没有用到,所以在转换时shift-jis没有对应的编码转换,所以转换成byte时都是以63来代替,即是?显示出来,因些我们要跟据原来字符串的字节码所对应的字符替换成shift-jis能显的相应字符。

我们的设计思路如下:

1、用一张转换表来处理保存要替换的编码表和字符表。

2、用两种处理方式来处理转换代码。

     a:用编码来替换,有些特殊字符并没显示出字符串,但是他却是存在的,如空字符,0xa0,shift-jis里并没有对应的编码。还有一些特殊字符,如utf-8是new byte[] {0xef, 0xbb,0xbf}的空字符串。

     b:在字符串转换前替换掉。如一些明显可保存的字付串。如?替换成~,直接Replace替换掉.

问题就会随之而来,我们在表时只能保存像 0xef, 0xbb,0xbf 这样的字符串,怎么样转换成new byte[] {0xef, 0xbb,0xbf}呢?

我们处理的方式如下:

01 private   byte [] ConvertStringToByte( string   originalStr)

02 {

03      if   ( string .IsNullOrEmpty(originalStr))  return   null ;

04      string [] originalSplit = originalStr.Split( ',' );           

05      int   originalFirstValue = 0, originalSecondValue = 0, originalThirdValue = 0;

06      byte [] resultByte;

07      originalFirstValue = Convert.ToInt32(originalSplit[0].Trim(), 16);

08      if   (originalSplit.Length == 2)

09      {

10          originalSecondValue = Convert.ToInt32(originalSplit[1].Trim(), 16);

11          resultByte =  new   byte [] { BitConverter.GetBytes(originalFirstValue)[0], BitConverter.GetBytes(originalSecondValue)[0] };

12      }

13      else    if   (originalSplit.Length == 3)

14      {

15          originalSecondValue = Convert.ToInt32(originalSplit[1].Trim(), 16);

16          originalThirdValue = Convert.ToInt32(originalSplit[2].Trim(), 16);

17          resultByte =  new   byte [] { BitConverter.GetBytes(originalFirstValue)[0], BitConverter.GetBytes(originalSecondValue)[0], BitConverter.GetBytes(originalThirdValue)[0] };

18      }

19      else

20      {

21          resultByte =  new   byte [] { BitConverter.GetBytes(originalFirstValue)[0] };

22      }

23      return   resultByte;

24 }

根据传入的代码转换成相应字节流。而后概据我们的处理逻辑编写代码进行替换。

代码如下:

01 public   string   ReplaceString( string   content)

02   {

03       List<MessyCodeHandleBE> messyCodeHandleBEList = RetrieveAll();

04  

05       foreach   (MessyCodeHandleBE entity  in   messyCodeHandleBEList)

06       {

07           if   (entity.ConvertType == MessyCodeHandleConvertTypeChoices.ENCODEREPLACE)

08           {

09               content = content.Replace(Encoding.UTF8.GetString(ConvertStringToByte(entity.OriginalCode)), entity.ReplaceCode);

10           }

11           else

12           {

13               content = content.Replace(entity.OriginalCode, entity.ReplaceCode);

14           }

15       }

16       return   content;

17   }

而一个特殊字符的编码如何取得可以跟据以下代码自己计算,代码如下:

1 private   string   ConvertToShiftJis( string   content)

2 {

3      Encoding orginal = Encoding.GetEncoding( "utf-8" );

4      Encoding ShiftJis = Encoding.GetEncoding( "Shift-JIS" );

5      byte [] unf8Bytes = orginal.GetBytes(content);

6      byte [] myBytes = Encoding.Convert(orginal, ShiftJis, unf8Bytes);

7      string   JISContent = ShiftJis.GetString(myBytes);

8      return   JISContent;

9 }

在调试时查看其字节编码,如图:

而239的16进制是0xef,187的16进制是0xbb,191的16进制是0xbf.

总结

就是查找字符串对应shift-jis编码为63时对应的byte[]字节是什么,再用Replace替换掉就OK了。如果你有什么新的发现,欢迎留言交流。

作者: spring yang

出处: http://www.cnblogs.com/springyangwc/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于C# utf8编码时转换成shiftjis时出现乱码问题的处理的详细内容...

  阅读:51次

CopyRight:2016-2025好得很程序员自学网 备案ICP:湘ICP备09009000号-16 http://www.haodehen.cn
本站资讯不构成任何建议,仅限于个人分享,参考须谨慎!
本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。
本网站刊载的所有内容(包括但不仅限文字、图片、LOGO、音频、视频、软件、程序等)版权归原作者所有。任何单位或个人认为本网站中的内容可能涉嫌侵犯其知识产权或存在不实内容时,请及时通知本站,予以删除。

网站内容来源于网络分享,如有侵权发邮箱到:kenbest@126.com,收到邮件我们会即时下线处理。
网站框架支持:HDHCMS   51LA统计 百度统计
Copyright © 2018-2025 「好得很程序员自学网
[ SiteMap ]