【发布时间】:2015-05-26 21:30:50
【问题描述】:
我正在尝试解析以下文件,其中包含以下格式的信息:
表名
VARIABLE_LIST_OF_COLUMNS
VARIABLE_NUMBER_OF_ROWS(由制表符分隔)
一个例子(使用','作为问题的分隔符;实际的分隔符是一个制表符):
学生
身份证
名字
1,迈克
2,金佰利
这个想法是建立一个插入sql语句的列表(代码sn-p的上下文)。
我想知道的是,这种多行解析是否完全可以使用 java 8 流 API?这是我目前拥有的:
public final class StatementGeneratorMain {
public static void main(final String[] args) throws Exception{
List<String> fileNames = Arrays
.asList("STUDENTS.txt");
fileNames.stream()
.forEach(fileName -> {
String tableName;
List<String> columnNames;
List<String[]> dataRows;
try (BufferedReader br = getBufferedReader(fileName)) {
tableName = br.lines().findFirst().get();
} catch (Exception e) {
throw new RuntimeException(e);
}
try (BufferedReader br = getBufferedReader(fileName)) {
//skip the first line because its been processed.
columnNames = br.lines().skip(1).filter(v -> v.split("\t").length == 1).collect(toList());
} catch (Exception e) {
throw new RuntimeException(e);
}
try (BufferedReader br = getBufferedReader(fileName)) {
//skip the first line and the columns length to get the data
//columns are identified as being splittable on the delimiter
dataRows = br.lines().skip(1 + columnNames.size()).map(s -> s.split("\t"))
.collect(toList());
} catch (Exception e) {
throw new RuntimeException(e);
}
String columns = columnNames.stream().collect(joining(",","(",")"));
List<String> dataRow = dataRows.stream()
.map(arr -> Arrays.stream(arr).map(x -> "'" + x + "'").collect(joining(",", "(", ")")))
.map(row -> String.format("INSERT INTO %s %s VALUES %s;", tableName, columns, row))
.collect(toList());
dataRow.forEach(l -> System.out.println(l));
});
}
private static BufferedReader getBufferedReader(String fileName) {
return new BufferedReader(new InputStreamReader(StatementGeneratorMain.class.getClassLoader().getResourceAsStream(
fileName)));
}
}
这段代码为我完成了这项工作,但我真的不喜欢它,因为我三次读取同一个文件(一次用于表名,再次推断列,再次获取行)。我也不认为这是正确的功能风格。
我正在寻找一种更优雅的方式来使用流 API 进行这种多行/多记录解析。
为了完整起见,输出为:
INSERT INTO STUDENTS (ID, NAME) 值 ('1','Mike');
INSERT INTO STUDENTS (ID, NAME) 值 ('2','Kimberly');
此时我对数值列和空值之类的东西不太讲究。
【问题讨论】:
-
如果您的代码有效并且您正在寻找改进它的方法,那么您可能应该在codereview.stackexchange.com 而不是 Stack Overflow 上发布您的问题。
-
顺便说一句,我不确定您为什么需要
getBufferedReader方法。如果您想从文件中获取行流,只需使用Files.lines(Paths.get(fineName))(如果需要,您也可以添加字符集)。 -
@Pshemo 有很好的建议。我要补充一点,如果列名是一行上的 CSV(而不是单独一行上的每个列名),您的生活和代码会更简单,因为您实际上需要将它们作为 CSV 并且它解决了弄清楚的问题列名停止而行开始的位置。
-
顺便说一句,Bobby Tables 很喜欢你引用数据库输入的方式。
-
@Pshemo 谢谢,我想我会在那里回答问题。
标签: java parsing java-8 java-stream