junit測試用例從src/test/resources下的txt文件讀取多行數據並隨機選擇一行


踩坑背景

我遇到的這個問題,在 windows 平台上,測試用例運行正常,但是到了 linux 平台上構建時,測試用例總是運行失敗!
而且因為自動構建又不能打斷點,所以只好一點點地分析問題所在!

我的需求是這樣的:

  • 首先,在 src/test/resources 文件夾下面創建 xxxx.txt 文件

  • 接着,從 xxxx.txt 文件中讀取字符串

  • 最后,把字符串按行分割,並且過濾掉一些不需要的行(比如注釋行)

但是郁悶的是,我在 windows 上隨機選擇的一行數據總是我期望的,但是在 linux 平台上隨機選擇的一行總是空字符串

從測試資源文件中讀取字符串

protected String getContentFromResource(String filePath) throws IOException, URISyntaxException {
    URL resource = Thread.currentThread().getContextClassLoader().getResource(filePath);
    URI uri = resource.toURI();
    byte[] bytes = Files.readAllBytes(Paths.get(uri));
    String result = new String(bytes, StandardCharsets.UTF_8);
    log.info("Get content from resource is {} blank: {}",
            StringUtils.isNotBlank(result) ? "not" : "", uri.getPath());
    return result;
}

protected int randomInRange(int low, int high) {
    return ThreadLocalRandom.current().nextInt(low, high);
}

一開始總懷疑是讀取不到數據,但是嘗試多次后發現,在 linux 系統上測試用例是可以正常讀取到文件中的數據!

隨機選取一行

protected String randomLine(String lines, Predicate<String> predicate) {
    List<String> validLines = Arrays.stream(lines.split("\r\n"))
            .filter(predicate).collect(Collectors.toList());
    if (validLines.size() == 0) {
        return "";
    }
    int index = randomInRange(0, validLines.size());
    if (index < validLines.size()) {
        return validLines.get(index);
    } else {
        return "";
    }
}

找了好久才發現問題就出在 lines.split("\r\n")。txt文件在 windows 平台上行尾是 \r\n , 但是到了 linux 平台上,行尾卻是 \n

同樣是對從 txt 文件中讀取到字符串調用 split("\r\n") ,結果在 linux 平台上總是只得到一行,但在 windows 平台上卻是正常的多行!

深入解析Linux下\r\n的問題

解決方案

/**
 * 讀取多行數據的問題。
 *
 * @param lines 多行數據字符串
 * @return 分割后的多行
 */
protected List<String> readLines(String lines) {
    List<String> result = new LinkedList<>();
    try (StringReader reader = new StringReader(lines);
         BufferedReader buffer = new BufferedReader(reader)) {
        String line;
        // 按行讀取字符串
        while ((line = buffer.readLine()) != null) {
            result.add(line);
        }
    } catch (IOException e) {
        log.error("IO Exception occurred.", e);
    }
    return result;
}

然后再把 Arrays.stream(lines.split("\r\n")) 替換成 readLines(lines).stream()

修改后的 randomLine 代碼如下:

protected String randomLine(String lines, Predicate<String> predicate) {
    List<String> validLines = readLines(lines).stream()
            .filter(predicate).collect(Collectors.toList());
    if (validLines.size() == 0) {
        return "";
    }
    int index = randomInRange(0, validLines.size());
    if (index < validLines.size()) {
        return validLines.get(index);
    } else {
        return "";
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM