lris.commons文件读取器FileContentGetter的实现

Posted callmegaga

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的实现的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中,如何将文件上传到 PubNub 频道?

Python将大(10GB).csv转换为.tsv

如何在不设置 Content-Disposition 标签的情况下从控制器返回图像?

nacos 读取配置文件占位符读取不出来

java文件如何读取

python读取ini配置文件+Scala读取配置文件