在游戏开发过程中,需要与大量的配置文件打交道,如经验,装备属性,宠物属性等。通常是策划配置好配置文件,然后交个程序处理。这就需要一个通用的配置文件读取工具,将配置文件的内容转为程序可以处理的数据。下面是利用Java反射实现的一个demo版本: 实现原理:反射。 1.FileUtil.java: 这是一个文件工具类,目前只有一个方法,即将读取文件,将文件内容转为String。 注:1.读取后需要与原文件内容保持一致,包括回车换行。 2.注意配置文件的格式:配置文件的每一列都以tab切分;第一行为列的中文注释,第二行为列的属性名,第三行以后才是属性的内容。下面是一个例子:id 名字 年龄id name age1000 landon 2310001 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(this, new 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 age1000 landon 2310001 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) 编辑 收藏 所属分类:
Program 、
GameServer