zoukankan      html  css  js  c++  java
  • Windows转到linux中,文件乱码,文件编码转换 & 解决sqlplus连接oracle乱码

    转载:http://www.cnblogs.com/wanyao/p/3399269.html

    最近,学习又重新开始Linux学习,所以一直在Centos中,昨天一朋友把他在Windows下写的C程序发给我,我欣然答应,本以为很快就能在我的Linux系统中运行起来。没想到出现了乱码,结果想把这个问题解决,一下子就搞了近三个小时没有解决。今天,又想起来这个问题,竟然一下子就解决了,现在把学到的一些东西总结如下。

    首先Windows下的文件拿到Linux中来查看出现乱码是一种很常见的现象,这方面的资料在网上也有很多。但解决方法大多都类似,有些概念没有解释清楚,也许是个人没有理解清楚。

    尝试方法一:

    一碰到这个问题,我想到的是Linux课上学到的一个命令dos2unix,以前也没用过,这次用了也没有解决问题。

    因为,这个命令主要是用来处理Dos与Linux之间断行的差异的。DOS下的文本文件是以 作为断行标志的,表示成十六进制就是0D 0A。而Unix下的文本文件是以 作为断行标志的,表示成十六进制就是 0A。有时我们会遇到这样一种情况,dos下的文件在unix下显示是不出现断行,显得很乱,这时用这个命令就OK。

    后来在网上查了下,知道是编码格式不一致导致的。因为Dos下编辑的文本默认是以GBK存储的,而Linux默认采取的存储方式是UTF-8,当然会出现乱码了,但是如何去将Dos下的GBK文件转换成UTF-8呢?

    尝试方法二:更改Vim读取时采用的编码

    先补充一个知识,参考博客http://blog.csdn.net/kl222/article/details/4550269

    vim编码方面的基础知识:
    存在3个变量:
    encoding—-该选项使用于缓冲的文本(你正在编辑的文件),寄存器,Vim 脚本文件等等。你可以把 'encoding' 选项当作是对 Vim 内部运行机制的设定。
    fileencoding—-该选项是vim写入文件时采用的编码类型。
    termencoding—-该选项代表输出到客户终端(Term)采用的编码类型。

    所以,我尝试了在Vim中

    :set encoding

    :set fileencoding=utf-8          #让Vim将gbk的文本转换成utf-8后,显示出来

    经过这样改了之后,果然,Vim中看到的乱码消失了,此时心情小小的激动了一下子。

    但是,当我退出Vim再次打开文件时,乱码又出现了,原来是我更改的Vim设置只是临时的,所以我决定将其写死到vim配置文件当中去,操作如下:

    编辑~/.vimrc文件,加上如下几行:

    set fileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936

    set termencoding=utf-8

    set encoding=utf-8

    这时,每次用Vim打开文件时都不出现乱码了,本以为问题解决了,我开始编译程序,当我运行的时候,乱码还是出现了。。。。此时,欲哭无泪

    后来,我仔细想了一下,我更改Vim的配置,只是让我们看到的没有乱码,但从根本上讲,文件的编码方式还是没有变,所以当我用gcc编译后,文件的编码格式应该还是gbk的。这样导致的乱码。所以,我决定找个工具,直接讲gbk文件转换成utf-8。

    尝试三:

    1.查看文件存储格式

    #file test.cpp

    test.cpp: ISO-8859 English text, with CRLF line terminators

    可以看出文件是以ISO-8859存储的。

    2.查看系统语言设置

    #cat /etc/sysconfig/i18n

    LANG="en_US.UTF-8"
    SYSFONT="latarcyrheb-sun16"
    可以看出Linux是以UTF-8编码的

    3.利用工具将文件从ISO-8859转换成UTF-8(这里我采用的是iconv命令)

    #iconv -f ISO-8859 -t UTF-8 test.c -o test_u.c

    这时竟然出现了一个错误:

    iconv: conversion from `ISO-8859' is not supported

    Try `iconv --help' or `iconv --usage

    解决方案:

    ISO-8859换成GBK

    #iconv -f GBK -t UTF-8 test.c -o test_u.c

    终于大功告成!

    参考文献:

    [1].http://blog.csdn.net/kl222/article/details/4550269

    [2].http://www.cnblogs.com/cosiray/archive/2012/05/04/2483111.html

    [3].http://blog.chinaunix.net/uid-26786246-id-3636785.html

    要解决Oracle的客户端乱码问题关键是要把服务器端使用的字符集跟客户端使用的字符集统一起来。Oracle客户端(Sqlplus)通过NLS_LANG环境变量来确定客户端使用的字符集。NLS_LANG参数由以下部分组成:
    NLS_LANG=<Language>_<Territory>.<Clients Characterset>

    NLS_LANG各部分含义如下:
    LANGUAGE指定:
    -Oracle消息使用的语言
    -日期中月份和日显示
    TERRITORY指定
    -货币和数字格式
    -地区和计算星期及日期的习惯
    CHARACTERSET:
    -控制客户端应用程序使用的字符集
    通常设置或者等于客户端(如Windows)代码页 
    或者对于unicode应用设置为UTF8

    RedHat linux AS4.0安装了oracle10g,同时创建数据库实例sc,后来又用dbca建立一个数据库实例st,发现在oracle系统用户下用sqlplus连接st实例时出现乱码,应该是中文无法显示造成的,但连接sc实例时无乱码,显示英文。上网搜集了一下资料,修改了oracle系统用户的环境变量在.bash_profile中新增了以下内容解决:

    export NLS_LANG=AMERICAN_AMERICA.UTF8
    export LANG=en_US.UTF-8

    分析原因:

    引用网上帖子:

    oracle字符集问题一般可以分为三类: 数据库字符集, sqlplus的字符集(客户端字符集), 终端程序的字符集(非oracle的)。

    1、数据库字符集。
            数据库字符集是所有字符问题的核心,只有数据库本身的字符集正确了,客户端的字符集才可能正确。这里只的客户端包括sqlplus以及我们自己读数据库的应用程序。
         在定位问题时,我们需要先看看数据库当前是什么字符集。
        1)查询数据库字符集
           select * from nls_database_parameters
        其中 nls_language表示了显示方式, 就是sqlplus的程序的显示字体,有SIMPLIFIED CHINESE,American america
       其中  nls_characterset是字符集设定, 常用的一些字符集有UTF8,US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK, AL32UTF8
       2)修改数据库字符集
           当发现数据库字符集不正确时,如我们期望时GBK的,而数据库当前是其他的,从而引起中文乱码。这时我们需要修改数据库字符集。步骤如下:
         $sqlplus /nolog
      SQL>conn / as sysdba;
      若此时数据库服务器已启动,则先执行SHUTDOWN IMMEDIATE命令关闭数据库服务器,然后执行以下命令:
      SQL>STARTUP MOUNT;
      SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
      SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
      SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
      SQL>ALTER DATABASE OPEN;
      SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
      SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;
      SQL>SHUTDOWN IMMEDIATE;
      SQL>STARTUP

    2 客户端字符集
          如果服务器端的字符集是正确的,而在客户端下,如sqlplus仍然不能正确显示中文,这一般是由于服务器端的字符集设定与客户端的字符集设定不同造成的。只要将两者修改一致就可以解决问题。
        1)查询客户端字符集
        select * from nls_instance_parameters
        客户端字符集环境select * from nls_instance_parameters,其来源于v$parameter,
        表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表
            select userenv('language') from dual;
        会话字符集环境 select * from nls_session_parameters,其来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,如果会话没有特殊的设置,将与nls_instance_parameters一致。 
        客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。如果多个设置存在的时候,alter session>环境变量>注册表>参数文件
        字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk。  或者.zhs16gbk。注意zhs16gbk前面那个点是必须的哦!!

       2) 修改客户端字符集
    oracle 的sqlplus会去读取OS中环境变量下的nls_lang信息(关键在这里,通过以上命令查看

    select * from nls_database_parameters 显示

    NLS_LANGUAGE                   AMERICAN                               
    NLS_TERRITORY                  AMERICA                                
    NLS_CURRENCY                   $   

    select * from nls_instance_parameters 显示

    NLS_LANGUAGE                   SIMPLIFIED CHINESE                     
    NLS_TERRITORY                  CHINA                                  
    NLS_SORT                                                              
    NLS_DATE_LANGUAGE                                                     
    NLS_DATE_FORMAT                                                       
    NLS_CURRENCY     

     select * from nls_session_parameters 显示  

    NLS_LANGUAGE                   SIMPLIFIED CHINESE                     
    NLS_TERRITORY                  CHINA                                  
    NLS_CURRENCY                   RMB  

    也就是说会话字符集与终端字符集一致,而与数据库字符集设置不一致。

    另一个数据库实例sc

    数据库字符集

    select * from nls_database_parameters 显示

    NLS_LANGUAGE                   AMERICAN                               
    NLS_TERRITORY                  AMERICA                                
    NLS_CURRENCY                   $   

    select * from nls_instance_parameters 显示

    NLS_LANGUAGE                   AMERICAN                               
    NLS_TERRITORY                  AMERICA                                
    NLS_SORT                                                              
    NLS_DATE_LANGUAGE                                                     
    NLS_DATE_FORMAT                                                       
    NLS_CURRENCY    

    在linux下

     select * from nls_session_parameters 显示  

    NLS_LANGUAGE                   AMERICAN                               
    NLS_TERRITORY                  AMERICA    

    用TOD 在windows下显示

    NLS_LANGUAGE                   SIMPLIFIED CHINESE                     
    NLS_TERRITORY                  CHINA                                  
    NLS_CURRENCY                   RMB  

    这个我还搞不明白为什么windows与linux会话字符集为什么不一样。

    更搞不明白的是为什么两个数据库实例用同一个系统用户查询的,也就是说环境变量是一样的,但查询结果终端字符集为什么会不一样?初步分析(当然不一定对,欢迎指正)是两个数据库实例的参数文件不一致引起的,因为alter session>环境变量>注册表>参数文件,也就是说因为环境变量没有设置,但sc与st数据库实例参数文件不同,但是参数文件在什么地方设还不清楚,有高手欢迎指点!


    但基本上问题锁定是因为终端字符集与数据库字符集不一致引起,在用户的环境变量中增加

    export NLS_LANG=AMERICAN_AMERICA.UTF8
    export LANG=en_US.UTF-8

    问题解决

    再次查看客户端字符集

    select * from nls_instance_parameters 还是显示

    NLS_LANGUAGE                   SIMPLIFIED CHINESE                     
    NLS_TERRITORY                  CHINA                                  
    NLS_SORT                                                              
    NLS_DATE_LANGUAGE                                                     
    NLS_DATE_FORMAT                                                       
    NLS_CURRENCY     

     select * from nls_session_parameters 显示  

    NLS_LANGUAGE        AMERICAN

    NLS_TERRITORY         AMERICA

    NLS_CURRENCY         $

    看来只要本次会话字符集正确就没问题了,经过验证确实如此,用

    alter session set NLS_LANGUAGE=‘AMERICAN’后本次会话也不会出现乱码的。

    NSL_LANG包括三个部分(语言_地区.字符集)就是V$NLS_PARAMETERS表中的NLS_LANGUAGE,NLS_TERRITORY,NLS_CHARACTERSET
    例如可以在cmd中键入
    set nls_lang="Simplified chinese_china.utf8"
    set nls_lang="american_america.us7ascii"
    set nls_lang="american_america.zhs16gbk"
    set nls_lang="Simplified chinese_china.zhs16gbk"
    set nls_lang=".utf8"
    set nls_lang=".zhs16gbk"
    set nls_lang=".us7ascii"

    unix下类似, 不过nls_lang要大写NLS_LANG, 在.profile或这.bash_profile(根据你用的shell)里更改NLS_LANG可以长久保持环境变量值.

    3、终端字符集
        如果数据库字符集和sqlplus的字符集一致, 还是不能正确显示了, 那很可能就是你的终端应用程序的字符集不支持了. 例如你用bash登陆sqlplus, 如果你的bash是个小字符集, 那么就不能正常显示了.linux修改bash的字符集, 可以先键入locale, 看有哪些环境变量, 再用export设置.

    转载:http://blog.csdn.net/nini1109/article/details/4158796

  • 相关阅读:
    解决.Net 4.0 A potentially dangerous Request.Form value was detected from the client 异常
    解决背景在360极速模式下不显示的问题
    ASP怎么解除文件上传200kb限制
    mysql导入数据出错
    ECShop出现Strict Standards: Only variables should be passed by reference in的解决方法
    phpmyadmin导入sql数据的纠结
    Veket_Porteus_Puppy安装器by双心
    多系统的福音,bcdedit找回传统启动菜单。取消(恢复)Modern UI风格启动菜单~菜单~
    关于fbinst-ud区的几点看法
    高速公路坐标高程计算软件4.2版本发布
  • 原文地址:https://www.cnblogs.com/zl-graduate/p/6228046.html
Copyright © 2011-2022 走看看