1. 程式人生 > >【lris.commons】檔案讀取器FileContentGetter的實現

【lris.commons】檔案讀取器FileContentGetter的實現

FileContentGetter是原xqq.commons中用於檔案讀取的一個類,其中集成了一些通用的對錶格檔案或者文字檔案的讀取方法。

最早應用在單位上班時的drp專案中,其中的一些方法也使用了drp.commons.util中的工具。之後xuqiaoqiao.cc專案,ss18專案,lina專案,畢業論文的apocalypto專案中均大量使用。

現對其程式碼進行重構。

 

FileContentGetter的應用場景:對文字檔案(txt,html等)或表格檔案(csv檔案)進行讀取,將內容儲存為String,List<String>,或者List<Map<String,String>>(表格檔案)

 

主要方法:

(1)String FileContentGetter.toString(File file);//讀取為String

(2)List<String> FileContentGetter.toStringList(File file);//讀取為String列表

(3)List<Map<String,String>> FileContentGetter.toStringMapList(File file);//讀取為表格資料

 

方法(1)的實現

public static String toString(File file, String charset, long max_value) {
  try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file, Charset.forName(charset)))) {
    StringBuilder ret = new StringBuilder();
    bufferedReader.lines().parallel().limit(max_value).forEach(ret::append);
    return ret.toString();
  } catch (IOException e) {
    e.printStackTrace();
  }
  return null;
}

  其中引數file指定了檔案,charset標註瞭解析使用的字符集,而max_value指出了最大的讀取行數。

  在IO這塊,使用bufferedreader類進行讀取,並將其定義寫到了try後面的括號中,從而省略關閉流這一步驟,簡化程式碼。

  在內容的獲取這塊,對於多行檔案,採用StringBuilder拼接的形式,採用bufferreader的lines方法,將IO流轉換成操作性更強的Stream,並通過stream的limit方法設頂最大讀取行數,通過ret::append構建新增到ret的函式Consumer,將其傳入stream的處理中,實現將內容附加到ret後面。

 

方法(2)的實現

  

public static List<String> toStringList(File file, String charset, long max_value) {
    try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file, Charset.forName(charset)))) {
    return bufferedReader.lines().parallel().limit(max_value).collect(Collectors.toList());
  } catch (IOException e) {
    e.printStackTrace();
  }
  return null;
}

  方法2與方法1大同小異,不過省略了StringBuilder的操作,因為stream可以直接轉換成List,通過collect方法直接轉換即可。

 

方法(3)的實現

   方法3用於讀取表格檔案,一般而言,對於單條資料,以map的形式儲存,更方便對資料的操作,也就是每個資料都可以根據其目錄名去訪問。這裡涉及到一個問題,有些檔案是沒有目錄的,或者有些檔案,在最終資料操作時,能直接尋秩訪問,相比尋目錄名訪問,要更加方便一些。

  也就是,方法3需要實現兩種方法,一種能讀取第一行表示的目錄檔案(withHead),而第二種能自動生成目錄(autoHead)。

withHead

  public static List<Map<String, String>> toStringMapList_withHead(File file, String charset, String separate, long max_value) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file, Charset.forName(charset)))) {
            String[] head = bufferedReader.readLine().split(separate);
            return bufferedReader.lines().parallel().limit(max_value).map(a1 -> {
                Map<String, String> tempMap = new HashMap<>();
                String[] stringArrayTemp = a1.split(separate);
                IntStream.range(0, stringArrayTemp.length).forEach(a2 -> tempMap.put(head[a2], stringArrayTemp[a2]));
                return tempMap;
            }).collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

  開啟流之後先讀取一行,通過指定的分割符separate分割之後,暫存,用於表示目錄列表。

  之後讀取剩下的所有行,對每一行執行分割操作,尋內容的秩到目錄列表中尋找對應的目錄,並存入當前Map中,最終將所有map收集為list,作為返回值

 

autoHead

   public static List<Map<String, String>> toStringMapList_autoHead(File file, String charset, String separate, long max_value) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file, Charset.forName(charset)))) {
            return Stream.concat(Stream.of(firstLine), bufferedReader.lines().parallel().limit(max_value)).map(a1 -> {
                Map<String, String> tempMap = new HashMap<>();
                String[] stringArrayTemp = a1.split(separate);
                IntStream.range(0, Math.min(head.length, stringArrayTemp.length)).forEach(a2 -> tempMap.put(HEADS_OF_AUTO_NAME[a2], stringArrayTemp[a2]));
                return tempMap;
            }).collect(Collectors.toList());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

  需要另外自定義目錄列表

  private static final String[] HEADS_OF_AUTO_NAME =
            {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU"};

  操作上更簡單一些,不需要先讀一行了,而是直接從目錄列表中獲取對應目錄。

 

上述兩個方法有重複部分,可以抽出

  

 public static List<Map<String, String>> toStringMapList_withHead(File file, String charset, String separate, String nullPlace, long max_value) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file, Charset.forName(charset)))) {
            String[] head = bufferedReader.readLine().split(separate);
            return getMaps(separate, max_value, bufferedReader, head);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

  public static List<Map<String, String>> toStringMapList_autoHead(File file, String charset, String separate, String nullPlace, long max_value) {
        try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file, Charset.forName(charset)))) {
            return getMaps(separate, max_value, bufferedReader, HEADS_OF_AUTO_NAME);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


 private static List<Map<String, String>> getMaps(String separate, long max_value, BufferedReader bufferedReader, String[] headsOfAutoName) {
        return bufferedReader.lines().parallel().limit(max_value).map(a1 -> {
            Map<String, String> tempMap = new HashMap<>();
            String[] stringArrayTemp = a1.split(separate);
            IntStream.range(0, stringArrayTemp.length).forEach(a2 -> tempMap.put(headsOfAutoName[a2], stringArrayTemp[a2]));
            return tempMap;
        }).collect(Collectors.toList());
    }