在游戲開發過程中,需要與大量的配置文件打交道,如經驗,裝備屬性,寵物屬性等。通常是策劃配置好配置文件,然后交個程序處理。這就需要一個通用的配置文件讀取工具,將配置文件的內容轉為程序可以處理的數據。下面是利用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(String
args)

{
//將工程下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 閱讀(2118)
評論(0) 編輯 收藏 所屬分類:
Program 、
GameServer