java读取文本数据,生成 java对象
最近项目有遇到一个需求,其他系统会定时生成一批文本文件放到FTP中,我们所做的这个项目则定时从ftp中下载生成的文件,将其解析并保存到数据库中。需要解析的文本文件格式是这样的。
userName|age|address|tel
张三|11|火星|1388888888
李四|12|木星|1388888888
王五|13|土星|1388888888
小三|15|太阳|1388888888
小四|16|地球|1388888888
小五|14|不详|1388888888
需要将如上内容初始化成的对象类:
public class Person {
private String userName;
private int age;
private String addess;
private String tel;
//getter/setter
@Override
public String toString() {
return "Person [userName=" + userName + ", age=" + age + ", addess=" + addess + ", tel=" + tel + "]";
}
}
要将如上的内容转换映射成java对象,自然想到的是使用反射。但是这样如何取得每个值对应至哪一个属性呢?
为解决这个问题,我想到的是使用自定义注解来实现, 在注解中标注文本拆分成数组的下标。自定义注解如下:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface BOIndex {
int index();
}
其中的index是用于标识每行内容拆分后的数组下标。接下来则是要将以上的实体类加上这个注解。
public class Person {
@BOIndex(index = 0)
private String userName;
@BOIndex(index = 1)
private int age;
@BOIndex(index = 2)
private String addess;
@BOIndex(index = 3)
private String tel;
//getter/setter
@Override
public String toString() {
return "Person [userName=" + userName + ", age=" + age + ", addess=" + addess + ", tel=" + tel + "]";
}
}
再编写一个工具方法,用于将读到的内容利用反射初始化person对象的属性当中。
public static <T> T getMappingPo(Class<T> classz, Object[] objs) throws Exception {
Field[] fields = classz.getDeclaredFields();
Object object = classz.newInstance();
int length = objs.length;
for(Field fild : fields ) {
String typeStr = fild.getType().getSimpleName().toLowerCase();
Annotation[] annos = fild.getAnnotations();
if(annos.length > 0) {
for(Annotation anno : annos ) {
if(("BOIndex".equals(anno.annotationType().getSimpleName()))) {
BOIndex myAmoncation = (BOIndex) anno;
int index = myAmoncation.index();
if(index < length) {
fild.setAccessible(true);
if("double".equals(typeStr)) {
fild.set(object, Double.valueOf(objs[index] ==null? "0" : objs[index].toString()));
}else if("int".equals(typeStr) || "integer".equals(typeStr)) {
fild.set(object, Integer.valueOf(objs[index] ==null? "0" : objs[index].toString()));
}else if("float".equals(typeStr)) {
fild.set(object, Float.valueOf(objs[index] ==null? "0" : objs[index].toString()));
}else if("long".equals(typeStr)) {
fild.set(object, Long.valueOf(objs[index] ==null? "0" : objs[index].toString()));
}else if("date".equals(typeStr)) {
fild.set(object, SGS.asDate(objs[index] ==null? null : objs[index].toString()));
}else {
fild.set(object, objs[index]);
}
}
}
}
}
}
return (T)object;
}
准备好如上工作,接下来我们测试一下,这里我们只测试一条文本内容,就省去使用IO来读到文本文件的步骤。
public static void main(String[] args) throws Exception {
String str = "张三|11|火星|1388888888";
String[] fileds = str.split("\\|");
Person p = SGS.getMappingPo(Person.class, fileds);
System.out.println(p);
}
输出结果如下:
Person [userName=张三, age=11, addess=火星, tel=1388888888]
注意:这里在使用String类的split方法中,如果后面是连续为空值时,则会忽略部分切分出的空值,造成数组的length更小,所以这里建议使用StringUtils中的工具方法来split,如下:
public static void main(String[] args) throws Exception {
String str = "张三|11|火星|1388888888";
//String[] fileds1 = str.split("\\|");
String[] fileds = StringUtils.splitPreserveAllTokens(str, "\\|");
Person p = getMappingPo(Person.class, fileds);
System.out.println(p);
}