I want to fly higher
programming Explorer
posts - 114,comments - 263,trackbacks - 0
    在游戏开发过程中,需要与大量的配置文件打交道,如经验,装备属性,宠物属性等。通常是策划配置好配置文件,然后交个程序处理。这就需要一个通用的配置文件读取工具,将配置文件的内容转为程序可以处理的数据。下面是利用Java反射实现的一个demo版本:
    实现原理:反射。
    1.FileUtil.java:
    这是一个文件工具类,目前只有一个方法,即将读取文件,将文件内容转为String。
        注:1.读取后需要与原文件内容保持一致,包括回车换行。
              2.注意配置文件的格式:配置文件的每一列都以tab切分;第一行为列的中文注释,第二行为列的属性名,第三行以后才是属性的内容。下面是一个例子:
id 名字  年龄
id name age
1000 landon 23
10001 tracy 31
    下面看源码,注释很详细:
    
package com.game.tools.config;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

/**
 * 
 * 文件工具类
 * 
 * @author landon
 * @version 1.0 2011/8/1
 *
 
*/

public class FileUtils
{
    
/**
     * 
     * 将文件内容转化为文本字符串
     * 与文件中的内容保持一致
     * 
     * @param fileName    文件名字
     * @return
     
*/

    
public static String convertFileToString(String fileName)
    
{
        StringBuilder builder = new StringBuilder();
        File file = new File(fileName);
        
        
try
        
{
            BufferedReader reader = new BufferedReader(new FileReader(file));
            String str = null;
            
            
while((str = reader.readLine()) != null)
            
{
                builder.append(str);
                builder.append("\r\n");//保持一致,添加回车换行符
            }

        }

        
catch(IOException e)
        
{
            e.printStackTrace();
        }

        
        
return builder.toString();
    }

}


    2.ConfigBaseData.java:
    这是配置文件基础对象类。主要功能是读取配置文件内容然后加到一个集合中。
        注:1.每一个配置文件都对应一个ConfigBaseData的一个子类
              2.每一个ConfigBaseData对象的内容即为配置文件的一行,返回的集合是配置文件的所有行,即所有内容。
    下面是源码,注释写的很详细:
    
package com.game.tools.config;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


/**
 * 
 * 配置文件基础对象类,利用反射设置Field的值
 * 忽略了一些条件判断和异常捕捉
 * 
 * @author landon
 * @version 1.0 2011/8/1
 *
 
*/

public class ConfigBaseData implements Cloneable
{
    
/**
     * 每一个配置文件都会对应有一个ConfigBaseData的子类型
     * 配置文件的每一行数据即为一个ConfigBaseData对象
     * 利用反射初始化每一个对象的属性为配置文件中的内容列
     * 将配置文件的所有数据加到一个List中
     * 
     * @param convertString    配置文件内容字符串
     * @param configDataClass    具体的配置文件类Class
     * @param configDataList    读取配置文件后的集合对象
     
*/

    
public static final void initialAllObjects(String convertString,
            Class<? extends  ConfigBaseData> configDataClass,
            List<ConfigBaseData> configDataList)
    
{
        String[] linesArray = convertString.split("\r\n");//回车换行符切分
        String[] tabArray = linesArray[1].split("\t");//tab划分列的type/属性名/域
        
        
//从第三行开始读取内容
        for(int i = 2;i < linesArray.length;i++)
        
{
            String[] contentTabArray = linesArray[i].split("\t");//读取内容
            ConfigBaseData baseData = null;
            
            
try
            
{
                baseData = configDataClass.newInstance();//实例化
            }

            
catch(Exception e)
            
{
                e.printStackTrace();
            }

            
            
if(baseData != null)
            
{
                initalOneObject(baseData, tabArray, contentTabArray);
            }

            
            configDataList.add(baseData);//加入到一个集合类中
        }

    }

    
    
/**
     * 
     * 初始一个配置文件对象的属性值
     * 
     * @param data
     * @param filedType    配置文件的列名
     * @param fieldContent    配置文件列名对应的内容
     
*/

    
public static final void initalOneObject(ConfigBaseData data,String[] filedType,String[] fieldContent)
    
{
        
for(int i = 0;i < filedType.length;i++)
        
{
            data.setFieldValue(filedType[i], fieldContent[i]);
        }

    }

    
    
    
    
/**
     * 
     * 利用反射设置域值
     * 
     * @param key    配置文件的filed key(属性名)
     * @param value    配置文件filed对应的value(属性值)
     * @return
     
*/

    
public boolean setFieldValue(String key,String value)
    
{
        
try
        
{
            Field filed = getClass().getField(key);//得到属性所对应的Field对象
            Class<?> fieldType = filed.getType();//得到属性的类型
            
            
if(fieldType == Integer.TYPE)//int类型
            {
                filed.set(this, Integer.parseInt(value));//this表示运行时的那个对象
            }

            
else if(fieldType == Integer.class)//Intege类型
            {
                filed.set(this, Integer.valueOf(value));
            }

            
else if(fieldType == Short.TYPE)//short类型
            {
                filed.set(this, Short.parseShort(value));
            }

            
else if(fieldType == Short.class)//Short类型
            {
                filed.set(this, Short.valueOf(value));
            }

            
else if(fieldType == Long.TYPE)//long类型
            {
                filed.set(this, Long.parseLong(value));
            }

            
else if(fieldType == Long.class)//Long类型
            {
                filed.set(this, Long.valueOf(value));
            }

            
else if(fieldType == Float.TYPE)//float类型
            {
                filed.set(this, Float.parseFloat(value));
            }

            
else if(fieldType == Float.class)//Float类型
            {
                filed.set(this, Float.valueOf(value));
            }

            
else if(fieldType == Double.TYPE)//double类型
            {
                filed.set(this, Double.parseDouble(value));
            }

            
else if(fieldType == Double.class)//Double类型
            {
                filed.set(this, Double.valueOf(value));
            }

            
else if(fieldType == Boolean.TYPE)//boolean类型
            {
                filed.set(this, Boolean.getBoolean(value));
            }

            
else if(fieldType == Boolean.class)//Boolean类型
            {
                filed.set(this, Boolean.valueOf(value));
            }

            
else if(fieldType == String.class)//String类型
            {
                filed.set(this, value);
            }

            
else if(fieldType == Date.class)//Date类型
            {
                filed.set(thisnew SimpleDateFormat("yyy-MM-dd hh:mm:ss").parse(value));
            }

            
            
return true;
        }

        
catch(Exception e)
        
{
            e.printStackTrace();
        }

        
        
return false;
    }

}


    下面我们就可以简单的熟悉一下这个工具的用法:
    a.首先需要一个配置文件,testConfig.txt,放在工程下面的res目录下,内容和刚开始举得例子一样,注意格式:
id 名字  年龄
id name age
1000 landon 23
10001 tracy 31
    b.写一个该配置文件对应的配置文件类,TestConfigData.java,注意这个类需要继承ConfigBaseData,并且类中的属性名需要和上面的配置文件中的列名一致。下面是源码,注释很详细:
    
package com.cyou.social.tools.config;

/**

* 配置文件testconfig对应的文件类,需要继承ConfigBaseData
* 类的属性名需要和配置文件的列名需要保持一致
* 为方便测试,属性都设置public,如果设置成了private,需要设置field的accessible方法

@author landon
*
*/

public class TestConfigData extends ConfigBaseData
{
    
/** id */
    
public int id;

    
/** 名字 */
    
public String name;

    
/** 年龄 */
    
public int age;
}


    c.下面就可以测试了:Client.java:

package com.cyou.social.tools.config;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * 配置文件工具测试类
 * 
 * @author landon
 *
 
*/

public class Client 
{
    
public static void main(Stringargs)
    
{
        
//将工程下res目录下的testConig的配置文件转为字符串
        String fileString = FileUtils.convertFileToString("res\\testconfig.txt");
        
//所有的数据集合
        List<ConfigBaseData> list = new ArrayList<ConfigBaseData>();
        
        
try 
        
{
            ConfigBaseData.initialAllObjects(fileString, TestConfigData.class, list);
        }
 
        
catch (Exception e)
        
{
            e.printStackTrace();
        }

        
        
//测试查看,遍历输出
        for(ConfigBaseData  data : list)
        
{
            TestConfigData testData 
= (TestConfigData)data;
            
            System.out.println(testData.id);
            System.out.println(testData.name);
            System.out.println(testData.age);
            System.out.println();
        }

    }

}


    哈哈,当然测试通过了。这只是一个demo版本,还需要很多细节去改进,比如一些条件判断和异常捕捉等。

posted on 2011-08-06 21:42 landon 阅读(2113) 评论(0)  编辑  收藏 所属分类: ProgramGameServer

只有注册用户登录后才能发表评论。


网站导航: