您的位置:首页 > 其它

简单的可配置的数据生成器

2016-04-02 11:46 477 查看
我们在做测试时,特别是做数据库方面的测试时,经常需要生成数据表数据,并且往往仅需要指定主键信息(单主键或者是复合主键)以及各属性基本信息,基本需求如下:

1. 可指定主键为单主键或者是复合主键,如果是复合主键,可指定各主键之间的大致比例;

2. 可指定各属性的数据类型以及针对每个数据类型的简单配置,如int型可设置min & max;

3. 可指定数据表大小以及输出文件个数(数据库在导入一个大文件时容易失败)。

基于上面的需求,我们的配置文件可定义如下:

#size: table size
#int: 0; real: 1; decimal: 2; date: 3; string: 4; char: 5; bool: 6
#int; min; max
#real; exponent; precision
#decimal; p; s
#date; begin; end
#string; length
#char
#bool
size: 3000
key: 1; 2
0; 0; 10000
1; 6; 5
2; 10; 4
3; 1158886166837; 1458886166837
4; 300
5
6


配置文件的简单说明:

# 注释
size关键字指定数据表大小

key关键字指定主键信息,如果仅是单主键,可写成"key: 1";例子中表示这是一个双主键,第一主键对应两个第二主键(具体看最后的输出)

下面就是各属性的配置信息

0; 0; 10000 整形,min为0,max为10000

1; 6; 5 实型,6为指数范围,5为实数有效位

2; 10; 4 decimal数据类型,10为整个decimal的有效位最大长度,4为小数有效位最大长度

3; 1158886166837; 1458886166837 date数据类型,后面两个为起止日期的long型表示

4; 300 字符串型,300为字符串的最大长度,字符串平均长度为150

5 char型

6 bool型

源码如下:

随机数生成器:

package datagenerator;

import java.util.Date;

public class RanDataGene {

public static long getInteger(long min, long max){
long result = min + (long)((max - min + 1) * Math.random());
return result;
}

public static String getDouble(int exponent, int precision){
char [] numbers = "0123456789".toCharArray();
StringBuilder result = new StringBuilder();
result.append((Math.random() < 0.5 ? "+" : "-"));
result.append(numbers[(int)(Math.random() * 10)] + ".");
precision = (int)(Math.random() * precision);
for(int i = 0; i < precision; i++){
result.append(numbers[(int)(Math.random() * 10)]);
}
result.append("e" + (Math.random() < 0.5 ? "+" : "-") + ((int)(Math.random() * (exponent + 1))));
return result.toString();
}

//a.b; .b; a.
public static String getDecimal(int p, int s){
StringBuilder result = null;
while(true){
char [] numbers = "0123456789".toCharArray();
result = new StringBuilder(Math.random() < 0.5 ? "+" : "-");
int ranp = (int)(Math.random() * (p - s + 1));
for(int i = 0; i < ranp; i++){
result.append(numbers[(int)(Math.random() * 10)]);
}
result.append(".");
int rans = (int)(Math.random() * (s + 1));
for(int i = 0; i < rans; i++){
result.append(numbers[(int)(Math.random() * 10)]);
}
if(!result.toString().matches("[-+.]+")){
break;
}
}
return result.toString();
}

public static Date getDate(long begin, long end){
return new Date((long)(Math.random() * (end - begin + 1) + begin));
}

public static String getString(int length){
//no tab
char [] chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
toCharArray();
int randomLength = (int)(Math.random() * (length + 1));
StringBuilder result = new StringBuilder();
for(int i = 0; i<randomLength; i++){
result.append(chars[(int)(Math.random() * 62)]);
}
return result.toString();
}

public static char getChar(){
char [] chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
toCharArray();
return chars[(int)(Math.random() * 62)];
}

public static boolean getBoolean(){
return Math.random() < 0.5 ? true : false;
}
}


数据生成器:

package datagenerator;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;

/**
* @author LiYuming
* @time 20160402
* 简单的可配置的数据生成器
*/

public class DataGenerator {

//待生成数据表的大小
private int tableSize;
//多主键之间的比例值
private int[] keyRatio = null;
//各属性信息
private class AttributeInfo {
//数据类型
//int: 0; real: 1; decimal: 2; date: 3; string: 4; char: 5; bool: 6
byte type;
//数据类型的描述信息
Long info1;
Long info2;
public AttributeInfo(byte type, Long info1, Long info2) {
super();
this.type = type;
this.info1 = info1;
this.info2 = info2;
}
}
//属性信息列表
private List<AttributeInfo> attributes = null;
private String splitStr = "\t";

public DataGenerator() {
super();
attributes = new ArrayList<AttributeInfo>();
}

public static void main(String[] args) {
long startTime = System.currentTimeMillis();
if(args.length != 3) {
System.out.println("error parameters!");
return;
}
//配置信息
File inputFile = new File(args[0]);
//输出文件名模板
File outputFile = new File(args[1]);
//输出文件个数
int outputFileSize = Integer.parseInt(args[2]);
DataGenerator dg = new DataGenerator();
dg.parse(inputFile);
dg.generate(outputFile, outputFileSize);
System.out.println("sucess!\ntime: " + ((System.currentTimeMillis() - startTime) / 1000) + "s");
}

private void parse(File inputFile) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(inputFile), "utf-8"));
String inputLine = null;
while((inputLine = br.readLine()) != null) {
if(inputLine.trim().startsWith("#") || inputLine.trim().equals(""))
continue;
if(inputLine.trim().toLowerCase().startsWith("size")) {
tableSize = Integer.parseInt(inputLine.split(":")[1].trim());
continue;
}
if(inputLine.trim().toLowerCase().startsWith("key")) {
String[] arr = inputLine.split(":")[1].split(";");
keyRatio = new int[arr.length - 1];
for(int i = 1; i < arr.length; i++) {
keyRatio[i - 1] = (int)(Integer.parseInt(arr[i].trim()) /
Integer.parseInt(arr[0].trim()));
}
continue;
}
String[] arr = inputLine.split(";", -1);
AttributeInfo attribute = new AttributeInfo(Byte.parseByte(arr[0].trim()),
arr.length < 2 ? null : Long.parseLong(arr[1].trim()),
arr.length < 3 ? null : Long.parseLong(arr[2].trim()));
attributes.add(attribute);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(br != null)	br.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}

private void generate(File outputFile, int outputFileSize) {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile.getAbsolutePath()
+ "_0.txt"), "utf-8"));
Random random = new Random();
List<HashSet<Integer>> keyValues = new ArrayList<HashSet<Integer>>();
for(int i = 0; i < keyRatio.length; i++)
keyValues.add(new HashSet<Integer>());
int sizePerFirstKey = 1;
for(int i = 0; i < keyRatio.length; i++)
sizePerFirstKey *= keyRatio[i];
int key = 0, fileName = 1, fileSize = tableSize / outputFileSize;
for(int i = 0; i < tableSize;) {
for(int j = 0; j < sizePerFirstKey; j++) {
bw.write(key + splitStr);
for(int k = 0; k < keyRatio.length; k++) {
int tmp = Math.abs(random.nextInt());
while(keyValues.get(k).contains(tmp))
tmp = random.nextInt();
bw.write(tmp + splitStr);
keyValues.get(k).add(tmp);
}
for(int k = 0; k < attributes.size(); k++) {
switch(attributes.get(k).type) {
case 0 :
bw.write(RanDataGene.getInteger(attributes.get(k).info1,
attributes.get(k).info2) + "");
break;
case 1 :
bw.write(RanDataGene.getDouble(attributes.get(k).info1.intValue(),
attributes.get(k).info2.intValue()) + "");
break;
case 2 :
bw.write(RanDataGene.getDecimal(attributes.get(k).info1.intValue(),
attributes.get(k).info2.intValue()) + "");
break;
case 3 :
bw.write(RanDataGene.getDate(attributes.get(k).info1,
attributes.get(k).info2).getTime() + "");
break;
case 4 :
bw.write(RanDataGene.getString(attributes.get(k).info1.intValue()) +
"");
break;
case 5 :
bw.write(RanDataGene.getChar() + "");
break;
case 6 :
bw.write(RanDataGene.getBoolean() + "");
break;
default :
System.out.println("error data type!");
return;
}
if(k < attributes.size() - 1)
bw.write(splitStr);
}
bw.write("\n");
}
key++;
i += sizePerFirstKey;
for(int j = 0; j < keyRatio.length; j++)
keyValues.get(j).clear();
if(i >= fileSize * fileName) {
bw.flush();
if(i < tableSize)
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile.getAbsolutePath() +
"_" + fileName + ".txt"), "utf-8"));
fileName++;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(bw != null) bw.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}


输出示例:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: