您的位置:首页 > 编程语言 > Java开发

【java】:对属性文件的读写操作,中文字符解决方案

2008-11-20 15:09 477 查看
 以前一直能看到一些关于配置文件读写出现乱码或者说是不支持中文的问题,昨天突然间有个想法,想看看properties源代码中对于配置文件的读写到底是怎么操作的?研究了一天,终于实现对于*.config和*.properties类型的配置文件完全支持中文,今天我就把研究成果和大家分享一下,也想抛砖引玉,看看大家还有什么好的解决办法。

首先:对properties类的以下代码做一下修改  
  主要是修改saveConvert()方法和loadConvert()方法,大家可以自己建立一个类,然后把properties类的代码拷贝过  
   
  来,然后修改这两个方法就可以了。或者直接将我下面的代码拷贝过去就可以了。  
  我也试过自己建立一个类,然后继承properties类,并且覆盖其中的saveConvert()方法和loadConvert()方法,但是  
   
  这种方法行不通,原因是properties类中的很多函数之间都是相互套用的。  
  修改后的properties类的代码如下所示:  
  package   xiaotang.util;  
  import   java.util.*;  
  package   xiaotang.util;  
   
  import   java.io.IOException;  
  import   java.io.PrintStream;  
  import   java.io.PrintWriter;  
  import   java.io.InputStream;  
  import   java.io.InputStreamReader;  
  import   java.io.BufferedReader;  
  import   java.io.OutputStream;  
  import   java.io.OutputStreamWriter;  
  import   java.io.BufferedWriter;  
  import   java.util.Hashtable;  
  import   java.util.*;  
  /**  
  *    
  *   <p>Title:   </p>    
  *    
  *   <p>Description:   </p>    
  *    
  *   <p>Copyright:   Copyright   (c)   2005</p>    
  *    
  *   <p>Company:   哈尔滨商业大学</p>  
  *    
  *   @author   Onlyfor_love  
  *   @version   1.0  
  */  
   
  public   class   PropertiesExt   extends   Hashtable   {  
   
  private   static   final   long   serialVersionUID   =   4112578634029874840L;  
  protected   PropertiesExt   defaults;  
  public   PropertiesExt()   {  
  this(null);  
  }  
  public   PropertiesExt(PropertiesExt   defaults)   {  
  this.defaults   =   defaults;  
  }  
  public   synchronized   Object   setProperty(String   key,   String   value)   {  
  return   put(key,   value);  
  }  
   
  private   static   final   String   keyValueSeparators   =   "=:   /t/r/n/f";  
   
  private   static   final   String   strictKeyValueSeparators   =   "=:";  
   
  private   static   final   String   specialSaveChars   =   "=:   /t/r/n/f#!";  
   
  private   static   final   String   whiteSpaceChars   =   "   /t/r/n/f";  
   
  public   synchronized   void   load(InputStream   inStream)   throws   IOException   {  
  //把所有的8859-1全部换成GBK,原先这里的编码格式都是8859-1  
  BufferedReader   in   =   new   BufferedReader(new   InputStreamReader(inStream,   "GBK"));  
  while   (true)   {  
  //   Get   next   line  
  String   line   =   in.readLine();  
  if   (line   ==   null)  
  return;  
   
  if   (line.length()   >   0)   {  
   
  //   Find   start   of   key  
  int   len   =   line.length();  
  int   keyStart;  
  for   (keyStart=0;   keyStart<len;   keyStart++)  
  if   (whiteSpaceChars.indexOf(line.charAt(keyStart))   ==   -1)  
  break;  
   
  //   Blank   lines   are   ignored  
  if   (keyStart   ==   len)  
  continue;  
   
  //   Continue   lines   that   end   in   slashes   if   they   are   not   comments  
  char   firstChar   =   line.charAt(keyStart);  
  if   ((firstChar   !=   '#')   &&   (firstChar   !=   '!'))   {  
  while   (continueLine(line))   {  
  String   nextLine   =   in.readLine();  
  if   (nextLine   ==   null)  
  nextLine   =   "";  
  String   loppedLine   =   line.substring(0,   len-1);  
  //   Advance   beyond   whitespace   on   new   line  
  int   startIndex;  
  for   (startIndex=0;   startIndex<nextLine.length();   startIndex++)  
  if   (whiteSpaceChars.indexOf(nextLine.charAt(startIndex))   ==   -1)  
  break;  
  nextLine   =   nextLine.substring(startIndex,nextLine.length());  
  line   =   new   String(loppedLine+nextLine);  
  len   =   line.length();  
  }  
   
  //   Find   separation   between   key   and   value  
  int   separatorIndex;  
  for   (separatorIndex=keyStart;   separatorIndex<len;   separatorIndex++)   {  
  char   currentChar   =   line.charAt(separatorIndex);  
  if   (currentChar   ==   '//')  
  separatorIndex++;  
  else   if   (keyValueSeparators.indexOf(currentChar)   !=   -1)  
  break;  
  }  
   
  //   Skip   over   whitespace   after   key   if   any  
  int   valueIndex;  
  for   (valueIndex=separatorIndex;   valueIndex<len;   valueIndex++)  
  if   (whiteSpaceChars.indexOf(line.charAt(valueIndex))   ==   -1)  
  break;  
   
  //   Skip   over   one   non   whitespace   key   value   separators   if   any  
  if   (valueIndex   <   len)  
  if   (strictKeyValueSeparators.indexOf(line.charAt(valueIndex))   !=   -1)  
  valueIndex++;  
   
  //   Skip   over   white   space   after   other   separators   if   any  
  while   (valueIndex   <   len)   {  
  if   (whiteSpaceChars.indexOf(line.charAt(valueIndex))   ==   -1)  
  break;  
  valueIndex++;  
  }  
  String   key   =   line.substring(keyStart,   separatorIndex);  
  String   value   =   (separatorIndex   <   len)   ?   line.substring(valueIndex,   len)   :   "";  
   
  //   Convert   then   store   key   and   value  
  key   =   loadConvert(key);  
  value   =   loadConvert(value);  
  put(key,   value);  
  }  
  }  
  }  
  }  
   
  /*  
  *   Returns   true   if   the   given   line   is   a   line   that   must  
  *   be   appended   to   the   next   line  
  */  
  private   boolean   continueLine(String   line)   {  
  int   slashCount   =   0;  
  int   index   =   line.length()   -   1;  
  while   ((index   >=   0)   &&   (line.charAt(index--)   ==   '//'))  
  slashCount++;  
  return   (slashCount   %   2   ==   1);  
  }  
   
  /**  
  *    
  *   <p>Title:   </p>    
  *    
  *   <p>Description:   </p>    
  *    
  *   <p>Copyright:   Copyright   (c)   2005</p>    
  *    
  *   <p>Company:   哈尔滨商业大学</p>  
  *    
  *   @author   Onlyfor_love  
  *   @version   1.0  
  */  
  private   String   loadConvert(String   theString)   {  
  //该功能主要是将存储的key和value提取出来,因为存储的中文在原来的properties类中被转换成了别的编码  
  //存储的中文在*.properties文件中以乱码出现  
  char   aChar;  
  int   len   =   theString.length();  
  StringBuffer   outBuffer   =   new   StringBuffer(len);  
  //  
  //   for   (int   x=0;   x<len;   )   {  
  //   aChar   =   theString.charAt(x++);  
  //   if   (aChar   ==   '//')   {  
  //   aChar   =   theString.charAt(x++);  
  //   if   (aChar   ==   'u')   {  
  //   //   Read   the   xxxx  
  //   int   value=0;  
  //   for   (int   i=0;   i<4;   i++)   {  
  //   aChar   =   theString.charAt(x++);  
  //   switch   (aChar)   {  
  //   case   '0':   case   '1':   case   '2':   case   '3':   case   '4':  
  //   case   '5':   case   '6':   case   '7':   case   '8':   case   '9':  
  //   value   =   (value   <<   4)   +   aChar   -   '0';  
  //   break;  
  //   case   'a':   case   'b':   case   'c':  
  //   case   'd':   case   'e':   case   'f':  
  //   value   =   (value   <<   4)   +   10   +   aChar   -   'a';  
  //   break;  
  //   case   'A':   case   'B':   case   'C':  
  //   case   'D':   case   'E':   case   'F':  
  //   value   =   (value   <<   4)   +   10   +   aChar   -   'A';  
  //   break;  
  //   default:  
  //   throw   new   IllegalArgumentException(  
  //   "Malformed   //uxxxx   encoding.");  
  //   }  
  //   }  
  //   outBuffer.append((char)value);  
  //   }   else   {  
  //   if   (aChar   ==   't')   aChar   =   '/t';  
  //   else   if   (aChar   ==   'r')   aChar   =   '/r';  
  //   else   if   (aChar   ==   'n')   aChar   =   '/n';  
  //   else   if   (aChar   ==   'f')   aChar   =   '/f';  
  //   outBuffer.append(aChar);  
  //   }  
  //   }   else  
  outBuffer.append(theString);  
  //   }  
  return   outBuffer.toString();  
  }  
/**  
  *    
  *   <p>Title:   </p>    
  *    
  *   <p>Description:   </p>    
  *    
  *   <p>Copyright:   Copyright   (c)   2005</p>    
  *    
  *   <p>Company:   哈尔滨商业大学</p>  
  *    
  *   @author   Onlyfor_love  
  *   @version   1.0  
  */  
   
  private   String   saveConvert(String   theString,   boolean   escapeSpace)   {  
  //该功能主要是将存储key和value,因为中文的存储在原来的properties类中被转换成了别的编码  
  //存储的中文在*.properties文件中以乱码出现  
  int   len   =   theString.length();  
  StringBuffer   outBuffer   =   new   StringBuffer(len*2);  
  outBuffer.append(theString);  
   
  //   for(int   x=0;   x<len;   x++)   {  
  //   char   aChar   =   theString.charAt(x);  
  //   switch(aChar)   {  
  //   case   '   ':  
  //   if   (x   ==   0   ||   escapeSpace)  
  //   outBuffer.append('//');  
  //  
  //   outBuffer.append('   ');  
  //   break;  
  //   case   '//':outBuffer.append('//');   outBuffer.append('//');  
  //   break;  
  //   case   '/t':outBuffer.append('//');   outBuffer.append('t');  
  //   break;  
  //   case   '/n':outBuffer.append('//');   outBuffer.append('n');  
  //   break;  
  //   case   '/r':outBuffer.append('//');   outBuffer.append('r');  
  //   break;  
  //   case   '/f':outBuffer.append('//');   outBuffer.append('f');  
  //   break;  
  //   default:  
  //  
  //   if   ((aChar   <   0x0020)   ||   (aChar   >   0x007e))   {  
  //   outBuffer.append('//');  
  //   outBuffer.append('u');  
  //   outBuffer.append(toHex((aChar   >>   12)   &   0xF));  
  //   outBuffer.append(toHex((aChar   >>   8)   &   0xF));  
  //   outBuffer.append(toHex((aChar   >>   4)   &   0xF));  
  //   outBuffer.append(toHex(   aChar   &   0xF));  
  //   }   else   {  
  //   if   (specialSaveChars.indexOf(aChar)   !=   -1)  
  //   outBuffer.append('//');  
  //   outBuffer.append(aChar);  
  //   }  
  //   }  
  //   }  
  return   outBuffer.toString();  
  }  
   
  /**  
  *   Calls   the   <code>store(OutputStream   out,   String   header)</code>   method  
  *   and   suppresses   IOExceptions   that   were   thrown.  
  *  
  *   @deprecated   This   method   does   not   throw   an   IOException   if   an   I/O   error  
  *   occurs   while   saving   the   property   list.   As   of   the   Java   2   platform   v1.2,   the   preferred  
  *   way   to   save   a   properties   list   is   via   the   <code>store(OutputStream   out,  
  *   String   header)</code>   method.  
  *  
  *   @param   out   an   output   stream.  
  *   @param   header   a   description   of   the   property   list.  
  *   @exception   ClassCastException   if   this   <code>Properties</code>   object  
  *   contains   any   keys   or   values   that   are   not   <code>Strings</code>.  
  */  
  public   synchronized   void   save(OutputStream   out,   String   header)   {  
  try   {  
  store(out,   header);  
  }   catch   (IOException   e)   {  
  }  
  }  
   
  public   synchronized   void   store(OutputStream   out,   String   header)  
  throws   IOException  
  {  
  BufferedWriter   awriter;  
  awriter   =   new   BufferedWriter(new   OutputStreamWriter(out,   "GBK"));  
  if   (header   !=   null)  
  writeln(awriter,   "#"   +   header);  
  writeln(awriter,   "#"   +   new   Date().toString());  
  for   (Enumeration   e   =   keys();   e.hasMoreElements();)   {  
  String   key   =   (String)e.nextElement();  
  String   val   =   (String)get(key);  
  key   =   saveConvert(key,   false);  
   
  /*   No   need   to   escape   embedded   and   trailing   spaces   for   value,   hence  
  *   pass   false   to   flag.  
  */  
  val   =   saveConvert(val,   false);  
  writeln(awriter,   key   +   "="   +   val);  
  }  
  awriter.flush();  
  }  
   
  private   static   void   writeln(BufferedWriter   bw,   String   s)   throws   IOException   {  
  bw.write(s);  
  bw.newLine();  
  }  
   
  public   String   getProperty(String   key)   {  
  Object   oval   =   super.get(key);  
  String   sval   =   (oval   instanceof   String)   ?   (String)oval   :   null;  
  return   ((sval   ==   null)   &&   (defaults   !=   null))   ?   defaults.getProperty(key)   :   sval;  
  }  
   
  public   String   getProperty(String   key,   String   defaultValue)   {  
  String   val   =   getProperty(key);  
  return   (val   ==   null)   ?   defaultValue   :   val;  
  }  
   
  public   Enumeration   propertyNames()   {  
  Hashtable   h   =   new   Hashtable();  
  enumerate(h);  
  return   h.keys();  
  }  
   
  public   void   list(PrintStream   out)   {  
  out.println("--   listing   properties   --");  
  Hashtable   h   =   new   Hashtable();  
  enumerate(h);  
  for   (Enumeration   e   =   h.keys()   ;   e.hasMoreElements()   ;)   {  
  String   key   =   (String)e.nextElement();  
  String   val   =   (String)h.get(key);  
  if   (val.length()   >   40)   {  
  val   =   val.substring(0,   37)   +   "...";  
  }  
  out.println(key   +   "="   +   val);  
  }  
  }  
   
  public   void   list(PrintWriter   out)   {  
  out.println("--   listing   properties   --");  
  Hashtable   h   =   new   Hashtable();  
  enumerate(h);  
  for   (Enumeration   e   =   h.keys()   ;   e.hasMoreElements()   ;)   {  
  String   key   =   (String)e.nextElement();  
  String   val   =   (String)h.get(key);  
  if   (val.length()   >   40)   {  
  val   =   val.substring(0,   37)   +   "...";  
  }  
  out.println(key   +   "="   +   val);  
  }  
  }  
   
  private   synchronized   void   enumerate(Hashtable   h)   {  
  if   (defaults   !=   null)   {  
  defaults.enumerate(h);  
  }  
  for   (Enumeration   e   =   keys()   ;   e.hasMoreElements()   ;)   {  
  String   key   =   (String)e.nextElement();  
  h.put(key,   get(key));  
  }  
  }  
   
  private   static   char   toHex(int   nibble)   {  
  return   hexDigit[(nibble   &   0xF)];  
  }  
   
  /**   A   table   of   hex   digits   */  
  private   static   final   char[]   hexDigit   =   {  
  '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'  
  };  
  }

然后写一个常用的配置文件操作类:  
  package   xiaotang.util;  
  import   java.io.*;  
   
  public   class   writeToProperty   {  
  private   String   fileName;  
  private   PropertiesExt   prop   =   new   PropertiesExt();  
  private   InputStream   fileStream   =   null;  
  private   OutputStream   outStream   =   null;  
  /**  
  *构造函数  
  *   @param   fileName   文件名字,包含路径  
  */  
  public   writeToProperty(String   fileName)   {  
  this.fileName   =   fileName;  
  }  
   
  //读取文件,不存在则创建文件  
  private   void   readFile()   {  
  try   {  
  File   f   =   new   File(fileName);  
  fileStream   =   new   FileInputStream(f);  
  prop.load(fileStream);  
  }  
  catch   (Exception   e)   {  
  e.printStackTrace();  
  }  
  finally   {  
  try   {  
  if   (fileStream   !=   null)  
  fileStream.close();  
  }  
  catch   (IOException   ex)   {  
  ex.printStackTrace();  
  }  
  }  
   
  }  
   
  private   void   writeFile()   {  
  try   {  
  File   f   =   new   File(fileName);  
  outStream   =   new   FileOutputStream(f);  
  }  
  catch   (Exception   e)   {  
  e.printStackTrace();  
  }  
  }  
   
  /**  
  *   返回指定key的vlaue  
  *   @param   key  
  *   @return  
  */  
  public   String   getValue(String   key)   {  
  readFile();  
  if   (key   !=   null   &&   !key.equals(""))  
  return   prop.getProperty(key);  
  else  
  return   "";  
  }  
   
  /**  
  *返回指定key的vlaue,如果key不存在则返回defaultValue值  
  *   @param   key  
  *   @param   defaultValue  
  *   @return  
  */  
  public   String   getValue(String   key,   String   defaultValue)   {  
  if   (key   !=   null   &&   !key.equals(""))  
  return   prop.getProperty(key,   defaultValue);  
  else  
  return   "";  
  }  
   
  /**  
  *   设置对应key的数值,如果key存在的覆盖value的数值,如果key不存则创建  
  *   @param   key  
  *   @param   value  
  */  
  public   void   setValue(String   key,   String   value)   {  
  readFile();  
  writeFile();  
  prop.setProperty(key,   value);  
  try   {  
  prop.store(outStream,   "GBK");  
  }  
  catch   (IOException   ex)   {  
  ex.printStackTrace();  
  }  
  finally   {  
  try   {  
  outStream.close();  
  }  
  catch   (IOException   ex1)   {  
  ex1.printStackTrace();  
  }  
  }  
  }  
  }  
  ////////////////////////////////////////////////////////////  
  接着写一个测试类就可以了:  
  package   xiaotang.util;  
   
  import   xiaotang.util.PropertiesExt;  
  import   java.io.*;  
  /**  
  *    
  *   <p>Title:   </p>    
  *    
  *   <p>Description:   </p>    
  *    
  *   <p>Copyright:   Copyright   (c)   2005</p>    
  *    
  *   <p>Company:   哈尔滨商业大学</p>  
  *    
  *   @author   Onlyfor_love  
  *   @version   1.0  
  */  
  public   class   PropertyFile   {  
  public   static   void   main(String[]   args)   {  
  writeToProperty   wt   =   new   writeToProperty("d://hello.properties");  
  //writeToProperty   wt   =   new   writeToProperty("d://hello.config");  
  wt.setValue("一","我是谁?");  
  wt.setValue("二","我是陈晓棠");  
  String   one   =   wt.getValue("一");  
  String   two   =   wt.getValue("二");  
  System.out.println(one);  
  System.out.println(two);  
  }  
   
  }  
  回头你再看看你的配置文件,中文依然是中文。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息