【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()); }
【lris.commons】文件讀取器FileContentGetter的實現