📄 filesystemsourcefactory.java
字号:
/* created at 2005-12-24 */
package com.clustering.data;
import java.io.BufferedReader;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.regex.Pattern;
/**
* 通过该类来创建数据源
*
* @author Avon
* @version 0.9
* @since 0.9
*/
public final class FileSystemSourceFactory {
/**
* 使用location位置的记录,按照默认的格式创建数据源
*
* @param location
* 数据源文件的位置
* @return
*/
public final static FileSystemSource createSimpleSource(String location) {
return createSimpleSource(location, null, null, false);
}
/**
* 使用location位置的记录,按照formatter格式,以info为信息创建数据源.
* <p>
* 如果在创建数据源时要求把文件中的矩阵转置,那么创建的数据源的就是按照转置后的矩阵创建,并且这个数据源中的信息也是与按照转置矩阵创建的。
* 如果想为该方法提供{@link info}参数,那么这个{@link info}参数也是用来说明未转置的矩阵,而不是转置后的矩阵,觉得这样能方便
*
* @param location
* 数据源文件的位置
* @param formatter
* 数据源文件的格式
* @param info
* 数据源文件的信息,如果是转置矩阵,那么也按照文件中的矩阵的形式设置数据源信息参数
* @param transposable
* 是否按照转置创建数据源
* @return
*/
public final static FileSystemSource createSimpleSource(String location, Formatter formatter, SourceInfo info,
boolean transposable) {
if (null == location)
throw new IllegalArgumentException("The location of datasource file is missed.");
else if (!new File(location).exists()) {
throw new IllegalArgumentException("Data source file[" + location + "] does not exist.");
}
if (null == formatter) {
formatter = new FileSystemFormatter();
}
// XXX 如果info为null,那么按照location文件的头初始化info,这里没有实现
// 这里吧info的检查逻辑放到SimpleFileSystemSourceImpl中了
SimpleFileSystemSourceImpl source = new SimpleFileSystemSourceImpl(location, formatter, info, transposable);
return source;
}
public final static FileSystemSource createComplexSource(String location) {
return createComplexSource(location, null, null, false);
}
public final static FileSystemSource createComplexSource(String location, Formatter formatter, SourceInfo info,
boolean transposable) {
throw new UnsupportedClassVersionError("Current release does not support complex file system source.");
}
/*
* 所谓Simple就是指把所有的记录都保存到内存中,而不考虑任何内存使用策略。 @author Avon
*/
private static class SimpleFileSystemSourceImpl extends FileSystemSource implements SimpleSource {
// 这里的recordNum和colNum只是临时变量,这两个变量用来保存文件中实际的记录数和行数
private int rowNum;
private int colNum;
private boolean isColNull;
private boolean isRowNull;
// 存储records的list,本质就是数组
private ArrayList<Record> records;
public SimpleFileSystemSourceImpl(String location, Formatter formatter, SourceInfo sourceInfo,
boolean transposable) {
super(location, formatter, sourceInfo, transposable);
/*
* 默认情况下,假设没有指定数据源信息
* 对于非转置阵,isColNull用来说明用户是否设置了列数,isRowNull用来说明用户是否设置了行数
* 对于转置阵,isColNumm用来说明用户是否设置了行数,isRowNull用来说明用户是否设置了列数
*/
isColNull = isRowNull = true;
if (null != sourceInfo) {
// 列信息保存的不是有效的信息
if (sourceInfo.getColumnNum() < 0) {
if (-1 != sourceInfo.getColumnNum())
log.warn("If u r not sure about source info's column number, set it to -1.[position:"
+ new Exception().getStackTrace()[0].getLineNumber() + "].");
// 默认情况下假设没有指定数据源信息
}
// 如果数据源信息中保存的是有效的列信息
else {
if (sourceInfo.getColumnNum() > Integer.MAX_VALUE) {
throw new RuntimeException(
"SimpleFileSystemSource is not suitable for current source, there are too many columns in data source file "
.concat(location));
}
if (!transposable) {
colNum = (int) sourceInfo.getColumnNum();
isColNull = false;
} else {
rowNum = (int) sourceInfo.getColumnNum();
isRowNull = false;
}
}
// 行信息保存的不是有效的信息
if (sourceInfo.getRecordNum() < 0) {
if (-1 != sourceInfo.getRecordNum())
log.warn("If u r not sure about source info's record number, set it to -1.[position:"
+ new Exception().getStackTrace()[0].getLineNumber() + "].");
// 默认情况下假设没有指定数据源信息
}
// 行信息保存的是有效的信息
else {
if (sourceInfo.getRecordNum() > Integer.MAX_VALUE) {
throw new RuntimeException(
"SimpleFileSystemSource is not suitable for current source, there are too many records in data source file "
.concat(location));
}
// 不需要转置时
if (!transposable) {
// 读取文件时计算行数
isRowNull = false;
}
// 需要转置时
else {
// 读取文件时计算列数
isColNull = false;
}
}
} // 没有设置数据源信息,那么isColNull = isRowNull = true;
if (!transposable && !isRowNull)
records = new ArrayList<Record>(rowNum);
else if (transposable && !isColNull) {
records = new ArrayList<Record>(rowNum);
} else {
// 没有给数据源信息,无法优化
records = new ArrayList<Record>();
}
/*
* 本来不打算使用BufferedReader,但是没有数据源的格式,所以这里使用了reader,如果以后规定了
* 数据源的格式,就需要重新写FileSystemSource的readLine函数了
*/
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(location));
} catch (FileNotFoundException e) {
}
// 认为很难把转置的情况和不转置的情况合并到一个init中
if (!transposable)
init1(reader);
else
init2(reader);
if (null == sourceInfo) {
sourceInfo = new SourceInfo();
}
sourceInfo.setColumnNum(colNum);
sourceInfo.setRecordNum(rowNum);
// 这里并没有具体严格的设置列类型
if (null == sourceInfo.getColumnTypes()) {
Class[] clazzs = new Class[colNum];
for (int i = 0; i < clazzs.length; i++) {
clazzs[i] = Double.class;
}
}
this.sourceInfo = sourceInfo;
}
/*
* 把文件中的内容直接转化为数据源,不考虑转置问题。
* 如果指定了数据源信息,那么就存在信息校验的问题,如果指定的数据源信息与文件实际的信息不一致,那么将按照文件中的情况修改数据源信息
*/
private void init1(BufferedReader reader) {
while (true) {
String s = readLine(reader);
// #作为注释
if (null == s) {
break;
} else if (s.startsWith("#") || s.equals("")) {
continue;
}
records.add(new RecordImpl(s));
// 记录太多,无法用SimpleSystemSource来表示
if (rowNum == Integer.MAX_VALUE) {
throw new RuntimeException(
"SimpleFileSystemSource is not suitable for current source, there are too many records in data source file "
.concat(location));
}
rowNum++;
}
if (!isColNull) {
if (colNum > sourceInfo.getColumnNum()) {
log.warn("Threr are " + colNum + " columns in " + location
+ " which is more than the column number[" + sourceInfo.getColumnNum()
+ "] u predict in Method createSource or source file. "
+ "Here, the program simply set the column number to " + colNum + ".[position:"
+ new Exception().getStackTrace()[0].getLineNumber() + "].");
}
// 如果指定的属性个数>实际的属性个数,即使数据源文件中没有这些属性的值,也要创建这些属性,认为可能这些属性都是0而被省略了
}
if (!isRowNull) {
if (rowNum > sourceInfo.getRecordNum()) {
log.warn("There are " + rowNum + " records in " + location
+ " which is more than the record number[" + sourceInfo.getRecordNum()
+ "] u predict in Method createSource or source file."
+ "Here, the program simply set the record number to " + rowNum + ".[position:"
+ new Exception().getStackTrace()[0].getLineNumber() + "].");
} else if (sourceInfo.getRecordNum() > rowNum) {
log.warn("File[" + location + "] does not contains enough records. u predicted "
+ sourceInfo.getRecordNum() + ", but actually there is only " + rowNum
+ ". Here, program simply set the record number to " + rowNum + "[position:"
+ new Exception().getStackTrace()[0].getLineNumber() + "].");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -