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

【lris.commons】文件讀取器FileContentGetter的實現

each trac 問題 場景 應用 java 讀一行 添加 read

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的實現