code: private <T> List<T> readCSVByMapHandler(InputStream is, Class<T> clazz)
              throws IOException, Excel4JException {
  
          List<T> records = new ArrayList<>();
  
          List<ExcelHeader> headers = Utils.getHeaderList(clazz);
          if (null == headers || headers.size() <= 0) {
              throw new Excel4jReadException("[" + clazz + "] must configuration @ExcelFiled");
          }
          String[] csvHeaders = new String[headers.size()];
          for (int i = 0; i < headers.size(); i++) {
              csvHeaders[i] = headers.get(i).getTitle();
          }
          CSVFormat format = CSVFormat.EXCEL.withHeader(csvHeaders).withSkipHeaderRecord(true);
          try (Reader read = new InputStreamReader(is, StandardCharsets.UTF_8);
               CSVParser parser = new CSVParser(read, format)) {
              for (CSVRecord _parser : parser) {
                  T obj;
                  try {
                      obj = clazz.newInstance();
                  } catch (InstantiationException | IllegalAccessException e) {
                      throw new Excel4jReadException(e);
                  }
                  for (ExcelHeader header : headers) {
                      String value = _parser.get(header.getTitle());
                      Object objectVal;
                      String filed = header.getFiled();
                      // 读取转换器
                      if (null != header.getReadConverter() &&
                              header.getReadConverter().getClass() != DefaultConvertible.class) {
                          objectVal = header.getReadConverter().execRead(value);
                      } else {
                          // 默认转换
                          objectVal = Utils.str2TargetClass(value, header.getFiledClazz());
                      }
                      Utils.copyProperty(obj, filed, objectVal);
                  }
                  records.add(obj);
              }
          }
          return records;
      }
docs: 读取csv