Java 中边读数据库边写到文件,可以处理大型数据文件而不会消耗太多内存。

从数据库查询结果集中提取单行数据,并按列格式化为字符串形式。主要功能如下:
遍历结果集的每一列。
根据不同的数据类型转换列值为字符串。
使用StringBuilder拼接各列值,列间以colSeparator分隔。
替换字符串中的换行符\n和回车符\r为空字符。
将处理后的行字符串添加到data列表中,每行后附加rowSeparator。

/**
 * 查询单行记录
 * @param data 数据列表,用于存储查询结果
 * @param rs 结果集对象
 * @param meta 结果集元数据对象
 * @param endCount 结束计数,用于处理行尾分隔符
 * @throws SQLException 如果查询过程中出现数据库错误
 */

/**
	 * 单行记录
	 * @param data
	 * @param rs
	 * @param meta
	 * @param formate
	 * @throws SQLException
	 */
	private void queryOneRow(List<String> data, ResultSet rs, ResultSetMetaData meta,int endCount) throws SQLException {
		StringBuilder buffer = new StringBuilder();
		int length = meta.getColumnCount();
		for (int i = 1; i <= length; i++) {
			String value = "";
			switch (meta.getColumnType(i)) {
			case java.sql.Types.BIGINT:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Long.toString(rs.getLong(i));
					break;
				} 
				break;
			case java.sql.Types.TINYINT:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Integer.toString(rs.getInt(i));
					break;
				}
				break;
			case java.sql.Types.SMALLINT:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Integer.toString(rs.getInt(i));
					break;
				} 
				break;
			case java.sql.Types.INTEGER:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Integer.toString(rs.getInt(i));
					break;
				} 
				break;
			case java.sql.Types.FLOAT:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Double.toString(rs.getDouble(i));
					break;
				} 
				break;
			case java.sql.Types.DOUBLE:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Double.toString(rs.getDouble(i));
					break;
				} 
				break;
			case java.sql.Types.DECIMAL:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Double.toString(rs.getDouble(i));
					break;
				} 
				break;
			case java.sql.Types.NUMERIC:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = String.valueOf(rs.getObject(i));//Double.toString(rs.getDouble(i));
					break;
				} 
				break;
			case java.sql.Types.REAL:
				if(NumberUtils.isNumber(rs.getObject(i)+"")){
					value = Double.toString(rs.getDouble(i));
					break;
				} 
				break;
			case java.sql.Types.CHAR:
			case java.sql.Types.LONGVARCHAR:
			case java.sql.Types.VARCHAR:
				value = rs.getString(i);
				break;
			case java.sql.Types.DATE:
			case java.sql.Types.TIMESTAMP:
			case java.sql.Types.TIME:
				AbstractDateExecute dateExecute = DateFactory.getDateExecute(info.getDesJob().getDataSource().getDbType());
				value = dateExecute.getDateValue(meta.getColumnType(i), rs, i,
						"yyyy-MM-dd",
						info.getDesJob().getDesJobConf().getColumns().get(i-1).getFieldType());
				break;
			case java.sql.Types.CLOB:
				Clob clob = rs.getClob(i);
				if (clob != null) {
					value = clob.getSubString(1, (int) clob.length());
				}
				break;
			case java.sql.Types.BLOB:
				Blob blob = rs.getBlob(i);
				if(blob != null) {
					value = new String(blob.getBytes(1, (int) blob.length()));
				}
				break;
			case java.sql.Types.BIT:
				boolean o = rs.getBoolean(i);
				if(o==true){
					value = "1";
				}else if(o==false){
					value = "0";
				}
				break;
			case java.sql.Types.NCHAR:
			case java.sql.Types.NVARCHAR:
				value = rs.getString(i);
				break;
			case java.sql.Types.BINARY:
			case java.sql.Types.VARBINARY:
			case java.sql.Types.STRUCT:
			case java.sql.Types.DISTINCT:
			case java.sql.Types.LONGVARBINARY:
				value = rs.getString(i);
				break;
			}
			if (value == null) {
				value = "";
			}
			buffer.append(value);
			if(i<length){
				buffer.append(this.colSeparator);
			}
		}
		String temp = StringUtils.replace(buffer.toString(), "\n", "");
		temp = StringUtils.replace(temp, "\r", "");
//		if(endCount!=1){
//			temp = rowSeparator+temp;
//		}
//		data.add(temp);
		data.add(temp+rowSeparator);
		buffer = null;
	}


 * 此方法主要用于处理大量文本内容,将其转换为字节数组形式
 * 这对于存储或传输大量文本数据时非常有用
 

/**
 * 将字符串列表转换为字节数组
 * 
 * @param data 字符串列表,包含要转换的内容
 * @param charsetName 字符集名称,用于指定字符串编码
 * @return 字节数组,包含转换后的字节
 * 
 * 此方法主要用于处理大量文本内容,将其转换为字节数组形式
 * 这对于存储或传输大量文本数据时非常有用
 */
private byte[] getRowsContents(List<String> data, String charsetName) {
    // 使用StringBuilder来高效地拼接字符串
    StringBuilder content = new StringBuilder("");
    
    // 检查数据列表是否非空且包含元素
    if(data != null && !data.isEmpty()){
        // 遍历字符串列表,将所有字符串拼接起来
        for(String str : data){
            content.append(str);
        }
    }
    
    // 将拼接好的字符串转换为字节数组
    byte[] bs = null;
    try {
        // 使用指定的字符集将字符串转换为字节数组
        bs = content.toString().getBytes(this.charset);
    } catch (UnsupportedEncodingException e) {
        // 如果指定的字符集不受支持,则记录警告信息,并使用默认方式转换
        logger.warn("getBytes error", e);
        bs = content.toString().getBytes();
    }
    
    // 返回转换后的字节数组
    return bs;
}
/**
 * 清除IO共享内存中的MappedByteBuffer
 * 通过调用sun.misc.Cleaner的clean方法来完成清理,该方法在Java官方文档中未记录,因此使用doPrivileged来确保安全
 * 
 * @param buffer 要清除的MappedByteBuffer,如果为null,则不执行任何操作
 */
private void unmap(final MappedByteBuffer buffer) {
    // 当传入的buffer为null时,直接返回,不执行任何操作
    if (buffer == null) {
        return;
    }
    // 使用doPrivileged执行清理操作,以确保对MappedByteBuffer内部机制的操作不会因安全限制而失败
    AccessController.doPrivileged(new PrivilegedAction<Object>() {
        public Object run() {
            try {
                // 获得并调用cleaner方法,用于清理内存映射
                Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
                if (getCleanerMethod != null) {
                    getCleanerMethod.setAccessible(true);
                    Object cleaner = getCleanerMethod.invoke(buffer, new Object[0]);
                    Method cleanMethod = cleaner.getClass().getMethod("clean", new Class[0]);
                    if (cleanMethod != null) {
                        cleanMethod.invoke(cleaner, new Object[0]);
                    }
                }
            } catch (Exception e) {
                // 记录异常信息,便于问题追踪
            	logger.error(e.getMessage());
            }
            return null;
        }
    });
}

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值