【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()); }