項目需要解析用逗號(,)分隔的文本文件,然後將其中的數據轉換成xml文件進行導入到財務系統中....
考慮到以後可能文件格式會變化,因此使用了動態的創建方法,即通過格式文件來動態解析txt文件..本程序使用了apache的Digester來動態生成格式文件,使用CGLib動態生成目標類.步驟如下:
1、定義文件和字段的元數據格式,如果出現其他的文件格式只需要實現元數據接口即可..接口代碼:
- public interface FileMeta {
- public String getName();
- public List<fieldmeta></fieldmeta> getFieldMeta();
- }
- public interface FieldMeta {
- public String getName();
- public String getType();
- public int getLength();
- public int getScale();
- public String getComment();
- public boolean isAllowNull();
- }
本例使用的是逗號分隔,如果出現其他分隔符怎麼辦?爲此,定義了一個分隔符接口:LineSpliter
- public interface LineSpliter {
- public String getSpliterRegx();
- public String[] split(String lineData);
- }
此處缺省實現了此接口,用於逗號分隔DefaultLineSpliter,定義如下:
- public class DefaultLineSpliter implements {
- public String defaultSpliterRegx = ",";
- public String getSpliterRegx() {
- return defaultSpliterRegx ;
- }
- public String[] split(String lineData) {
- return StringUtils.splitPreserveAllTokens(lineData,defaultSpliterRegx );
- }
- }
比如:如果行數據爲aaa,bbb,,,,, 通過jdk的實現會返回aaa和bbb,而通過Lang包處理會返回包括後面空的字段.
2、接下來使用DigesterDigester包根據xml規則生成對象..
首先需要了解digester包的使用方法,這裏簡單的說一下:disgeter可以根據一定的規則將xml文件解析成一組對象...具體這裏,我先定義
一個規則文件,
- <digester-rules>
- <pattern value='XXXFileMeta'>
- <object-create-rule classname="com.xxx.file.DefaultFileMeta"/>
- <set-properties-rule/>
- <pattern value="field">
- <object-create-rule classname="com.xxx.file.DefaultFieldMeta"/>
- <set-properties-rule/>
- <bean-property-setter-rule pattern="beanname1"/>
- <bean-property-setter-rule pattern="beanname2"/>
- <bean-property-setter-rule pattern="beanname3"/>
- <bean-property-setter-rule pattern="beanname4"/>
- pattern>
- digester-rules>
接着定義缺省的文件元數據文件,格式如下:
- <DefaultFileMeta name="com.xxx.file.DefaultFileMeta">
- <field>
- <beanname1>Codebeanname1>
- <beanname2>Namebeanname2>
- <beanname3>Datebeanname3>
- <beanname4>Remakebeanname4>
- field>
- DefaultFileMeta>
代碼如下:GeneratorObject.createObject(){}
初始化CGLib
- @SuppressWarnings("unchecked")
- private void init(Class target, FileMeta fileMeta) {
- List<fieldmeta></fieldmeta> fields = fileMeta.getFieldMeta();
- String[] getters = new String[fields.size()];
- String[] setters = new String[fields.size()];
- Class[] types = new Class[fields.size()];
- try {
- for (int i=0; i < fields.size(); i++) {
- FieldMeta fieldMeta = fields.get(i);
- getters[i] = "get" + ConverterUtils.upperCaseFirstChar(fieldMeta.getName());
- setters[i] = "set" + ConverterUtils.upperCaseFirstChar(fieldMeta.getName());
- types[i] = Class.forName(fieldMeta.getType());
- }
- } catch(ClassNotFoundException e) {
- logger.error("類沒有找到.." + e.getMessage());
- }
- this.bulkBean = BulkBean.create(target, getters, setters, types);
- }
- @SuppressWarnings("unchecked")
- private Object createObject(Class target, FileMeta fileMeta, Object[] values) {
- Object targetObject = null;
- try {
- targetObject = target.newInstance();
- } catch (Exception e){
- logger.error("創建對象出錯,目標類-->" + target.getName(), e);
- }
- bulkBean.setPropertyValues(targetObject, values);
- return targetObject;
- }
- @SuppressWarnings("unchecked")
- public List createObjects() {
- //初始化BulkBean
- init(targetClass, fileMeta);
- List result = new ArrayList();
- LineIterator iterator = null;
- try {
- iterator = FileUtils.lineIterator(this.dataFile, DEF_ENCODING);
- while(iterator.hasNext()) {
- String line = iterator.nextLine();
- //過濾掉數據文件中的空行
- if (StringUtils.isBlank(line)) {
- continue;
- }
- Object[] values = this.parseLine(line, fileMeta);
- Object object = createObject(this.targetClass, fileMeta, values);
- result.add(object);
- }
- } catch (IOException e) {
- logger.error("讀取文件名出錯!-->" + this.dataFile.getName(), e);
- } finally {
- LineIterator.closeQuietly(iterator);
- }
- return result;
- }
本例綜合使用了apache的代碼包,靈活實現了文本文件的解析...