InputStream重复使用问题

项目场景:

项目是一个读取银行流水文件来分析流水真实性及根据流水构造客户画像,生成尽调报告等


问题描述

项目里 对csv格式的文件读取分析存在问题,排查一遍之后,发现是 同事用 io流重复使用导致,熟悉Java的人可能都知道,Java中的Inputstream是不能重复读取的 :

/**
     * 读取 csv 文件
     */
    private void dealCSV(InputStream in, List<List<String>> list) throws UnsupportedEncodingException {
        boolean flag = false;
        boolean utf_flag_16 = false;
        CSVReader csvReader = new CSVReader(new InputStreamReader(in, "gbk"));
        for (String[] row : csvReader) {
            if (!flag) {
                for (String s : row) {
                    // 如果通篇没有这两个字,则判断该文件读取乱码
                    if (s.contains("交易") || s.contains("额")) {
                        flag = true;
                        break;
                    }
                }
            }
            list.add(Arrays.asList(row));
        }
        // 文件读取乱码,采用 utf-8 读取
        if (!flag) {
            list.clear();
            csvReader = new CSVReader(new InputStreamReader(in, StandardCharsets.UTF_8));
            for (String[] row : csvReader) {
                List<String> items = new ArrayList<>(Arrays.asList(row));

                if (!utf_flag_16) {
                    for (String s : row) {
                        // 如果通篇没有这两个字,则判断该文件读取乱码
                        if (s.contains("交易") || s.contains("额")) {
                            utf_flag_16 = true;
                            break;
                        }
                    }
                }
                list.add(items);
            }

            // 2023.8.2新增 utf-16格式,有些csv格式转换utf-8也是乱码
            setUtf16(in, utf_flag_16, list, true);
        }

        // 特殊字符处理
        for (List<String> item : list) {
            if (CollectionUtils.isNotEmpty(item)) {
                int size = item.size();
                for (int i = 0; i < size; i++) {
                    String str = item.get(i);
                    if (StringUtils.isNotBlank(str)) {
                        str = str.replace("\uFEFF", "");
                        item.set(i, str);
                    }
                }
            }
        }

    }

原因分析:

分析: 两次使用了 InputStream in 流,在InputStream读取的时候,会有一个pos指针,他指示每次读取之后下一次要读取的起始位置,当读到最后一个字符的时候,pos指针不会重置,导致 第一次读取如果是格式不对导致乱码,第二次使用 UTF-8时使用的 InputStream 已经读到最后了,不会再读取出什么东西,导致后面的代码失效


解决方案:

具体解决方案:明确了问题,解决方式就很简单了
.采用可以重复使用的 流

private ByteArrayOutputStream getBOS(InputStream in) {
	ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
	try {
		BufferedInputStream br = new BufferedInputStream(in);
		for(int c=0;(c=br.read())!=-1;){
			bos.write(c);
		}
		br.close();
	} catch (Exception e) {
		logger.error("",e);
	} 
	return bos;
}

这个时候的bis是可以被多次重复读取,close对其无效,但是要注意每次读前,调用bis.reset();方法需要将游标重置到流的头部。

InputStream bis = new ByteArrayInputStream(bos.toByteArray());
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值