简单的可配置的数据生成器
2016-04-02 11:46
477 查看
我们在做测试时,特别是做数据库方面的测试时,经常需要生成数据表数据,并且往往仅需要指定主键信息(单主键或者是复合主键)以及各属性基本信息,基本需求如下:
1. 可指定主键为单主键或者是复合主键,如果是复合主键,可指定各主键之间的大致比例;
2. 可指定各属性的数据类型以及针对每个数据类型的简单配置,如int型可设置min & max;
3. 可指定数据表大小以及输出文件个数(数据库在导入一个大文件时容易失败)。
基于上面的需求,我们的配置文件可定义如下:
配置文件的简单说明:
# 注释
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型
源码如下:
随机数生成器:
数据生成器:
输出示例:
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(); } } } }
输出示例:
相关文章推荐
- Android网络编程(二)HttpClient与HttpURLConnection
- xmapp下Access forbidden的处理
- windows下安装mysql-5.7.11-winx64
- html中设置锚点定位的几种常见方法(#号定位)
- iptables 一些使用命令
- levelDB编译
- 导航
- C#泛型的初始化
- 解决切花activity出现白屏问题
- yii2 ar的setAttributes方法注意
- js--引用类型--RegExp
- 多屏显示
- jQuery实现鼠标选文字发新浪微博的方法
- Haproxy配置实例
- presentation流程图神器--ProcessOn
- Linux _ socket 文件系统套接字
- 简要描述javascript中的作用域链
- 【个人机房重构】策略模式在下机
- 自定义实现mapreduce计算的value类型
- 解析对象体内与方法体内引用内部方法的不同