是否可以解析分隔文件并查找列数据类型? e.g
分隔文件:
Email,FirstName,DOB,Age,CreateDate
test@test1.com,Test User1,20/01/2001,24,23/02/2015 14:06:45
test@test2.com,Test User2,14/02/2001,24,23/02/2015 14:06:45
test@test3.com,Test User3,15/01/2001,24,23/02/2015 14:06:45
test@test4.com,Test User4,23/05/2001,24,23/02/2015 14:06:45
输出:
Email datatype: email
FirstName datatype: Text
DOB datatype: date
Age datatype: int
CreateDate datatype: Timestamp
这样做的目的是读取分隔文件并动态构建表创建查询并将数据插入该表。
我尝试使用apache验证器,我相信我们需要解析整个文件以确定每个列的数据类型。
编辑:我尝试过的代码:
CSVReader csvReader = new CSVReader(new FileReader(fileName),',');
String[] row = null;
int[] colLength=(int[]) null;
int colCount = 0;
String[] colDataType = null;
String[] colHeaders = null;
String[] header = csvReader.readNext();
if (header != null) {
colCount = header.length;
}
colLength = new int[colCount];
colDataType = new String[colCount];
colHeaders = new String[colCount];
for (int i=0;i<colCount;i++){
colHeaders[i]=header[i];
}
int templength=0;
String tempType = null;
IntegerValidator intValidator = new IntegerValidator();
DateValidator dateValidator = new DateValidator();
TimeValidator timeValidator = new TimeValidator();
while((row = csvReader.readNext()) != null) {
for(int i=0;i<colCount;i++) {
templength = row[i].length();
colLength[i] = templength > colLength[i] ? templength : colLength[i];
if(colHeaders[i].equalsIgnoreCase("email")){
logger.info("Col "+i+" is Email");
} else if(intValidator.isValid(row[i])){
tempType="Integer";
logger.info("Col "+i+" is Integer");
} else if(timeValidator.isValid(row[i])){
tempType="Time";
logger.info("Col "+i+" is Time");
} else if(dateValidator.isValid(row[i])){
tempType="Date";
logger.info("Col "+i+" is Date");
} else {
tempType="Text";
logger.info("Col "+i+" is Text");
}
logger.info(row[i].length()+"");
}
不确定这是否是最好的方法,任何正确方向的指针都会有所帮助
答案 0 :(得分:2)
如果您希望自己编写而不是使用第三方库,那么最简单的机制可能是为每种数据类型定义正则表达式,然后检查所有字段是否满足它。这里有一些示例代码可以帮助您入门(使用Java 8)。
public enum DataType {
DATETIME("dd/dd/dddd dd:dd:dd"),
DATE("dd/dd/dddd",
EMAIL("\\w+@\\w+"),
TEXT(".*");
private final Predicate<String> tester;
DateType(String regexp) {
tester = Pattern.compile(regexp).asPredicate();
}
public static Optional<DataType> getTypeOfField(String[] fieldValues) {
return Arrays.stream(values())
.filter(dt -> Arrays.stream(fieldValues).allMatch(dt.tester)
.findFirst();
}
}
请注意,这取决于枚举值的顺序(例如,测试日期之前的日期时间)。
答案 1 :(得分:1)
是的,这是可能的,您必须先解析整个文件。为每种数据类型制定一套规则。迭代列中的每一行。如果该列中的某行违反该数据类型的规则,则每个列都包含每种数据类型,并取消数据类型。迭代列后,检查为列保留的数据类型。例如。假设我们有两个数据类型integer和text ...整数规则...它必须只包含数字0-9并且可以以' - '开头。文字可以是任何东西。
我们的专栏:
345
-1ab
123
整数数据类型将被第二行删除,因此它将是文本。如果第二行只是-1,那么你将留下整数和文本,所以它将是整数,因为文本永远不会被删除,因为我们的规则说文本可以是任何东西......如果你离开,你基本上不必检查文本没有其他数据类型答案是文本。希望这能回答你的问题
答案 2 :(得分:0)
我的项目需要一些类似的逻辑。搜索了很多,但是没有找到正确的解决方案。对我来说,我需要将字符串对象传递给应该返回 obj数据类型的方法。终于我从@sprinter找到了帖子,它看起来与我的逻辑相似,但是我需要传递字符串而不是字符串数组。
根据我的需要修改了代码,并在下面发布。
public enum DataType {
DATE("dd/dd/dddd"),
EMAIL("@gmail"),
NUMBER("[0-9]+"),
STRING("^[A-Za-z0-9? ,_-]+$");
private final String regEx;
public String getRegEx() {
return regEx;
}
DataType(String regEx) {
this.regEx = regEx;
}
public static Optional<DataType> getTypeOfField(String str) {
return Arrays.stream(DataType.values())
.filter(dt -> {
return Pattern.compile(dt.getRegEx()).matcher(str).matches();
})
.findFirst();
}
}
例如:
Optional<DataType> dataType = getTypeOfField("Bharathiraja");
System.out.println(dataType);
System.out.println(dataType .get());
Output:
Optional[STRING]
STRING
请注意,常规exp模式会根据要求而有所不同,因此无需按实际需要修改模式。
快乐编码!