Как создать универсальный процесс, который читает в файле с разделителями табуляции и возвращает из него универсальную карту - PullRequest
1 голос
/ 10 ноября 2011

Почти у каждого проекта, который я работаю, будет какой-то файл с разделителями табуляции, который мне нужно прочитать и вернуть карту поиска. Я снова и снова переписываю один и тот же метод. Я хочу создать что-то более общее, поэтому мне не нужно постоянно копировать и вставлять код. Из приведенного ниже кода я меняю только строку 9 и 16-19 . Поэтому я изменяю только Map<key, value> и реализацию того, как я хочу вводить данные в карту. Есть ли способ сделать общий процесс из этого, поэтому каждый раз, когда я хочу вызвать этот метод, все, что мне нужно, это предоставить свою реализацию того, как я хочу вводить данные в Map, и каким-то образом изменить Map на более общий тип, как хорошо.

1. public Map<String, PackageLog> readAllLogsIntoMap(File file){
2.      if (!file.exists())
3.      {
4.          return new HashMap <String, PackageLog> ();
5.      }
6.      BufferedReader reader = null;
7.      FileReader fileReader = null;
8.      String data = null;
9.      Map <String, PackageLog> resultMap = new HashMap <String, PackageLog> ();
10.     try
11.     {
12.         fileReader = new FileReader(file);
13.         reader = new BufferedReader(fileReader);
14.         while ((data = reader.readLine()) != null)
15.         {
16.             PackageLog pl = new PackageLog(data);
17.             if(!pl.getPdfName().equals("")){
18.                 resultMap.put(pl.getPdfName(), pl);
19.             }
20.         }
21.     } catch(Exception e){
22.         
23.     }
24.     finally
25.     {
26.         try{
27.             if (reader != null) reader.close();
28.             if (fileReader != null) fileReader.close();
29.         }catch(IOException ioe){
30.             
31.         }
32.     }
33.     return resultMap;
34. }

Ответы [ 4 ]

3 голосов
/ 10 ноября 2011

Вы можете сделать следующее.

public interface LookupKey<K, T> {
    K keyFor(T t );
}

public <K, T> Map<K, T> readAllLogsIntoMap(File file, Class<T> tClass, LookupKey<K, T> lookupKey) {
    BufferedReader reader = null;
    Map<K, T> resultMap = new LinkedHashMap<K, T>();
    if (!file.exists())
        return resultMap;
    try {
        Constructor<T> tConstructor = tClass.getConstructor(String.class);
        reader = new BufferedReader(new FileReader(file));
        String data;
        while ((data = reader.readLine()) != null) {
            T t = tConstructor.newInstance(data);
            K key = lookupKey.keyFor(t);
            if (key != null)
                resultMap.put(key, t);
        }
    } catch (Exception e) {
        e.printStackTrace();

    } finally {
        try {
            if (reader != null) reader.close();
        } catch (IOException ignored) {
        }
    }
    return resultMap;
}
3 голосов
/ 10 ноября 2011
  1. Поместите этот метод в абстрактный класс Util. Используйте дженерики.
  2. Передать абстрактным методам логику для выполнения в строках 9 и 16-19.
  3. Определите эти абстрактные методы при использовании этого класса

Например:

public abstract class ReaderUtil<K, V> {

 protected abstract Map<K, V> newMap(); 
 protected abstract void doThings(String data, Map<K, V> resultMap);

 public Map<K, V> readAllLogsIntoMap(File file){
      if (!file.exists()){
          return newMap();
      }
      BufferedReader reader = null;
      FileReader fileReader = null;
      String data = null;
      Map <K, V> resultMap = newMap();
      try {
         fileReader = new FileReader(file);
         reader = new BufferedReader(fileReader);
         while ((data = reader.readLine()) != null){
             doThings(data, resultMap);
         }
     } catch(Exception e){

     }
     finally{
         try{
             if (reader != null) reader.close();
             if (fileReader != null) fileReader.close();
         } catch(IOException ioe){

         }
     }
     return resultMap;
 }
}

И возможное использование:

ReaderUtil<String, PackageLog> reader = new ReaderUtil<String, PackageLog>(){
    protected Map<String, PackageLog> newMap() { 
        return new HashMap<String, PackageLog>(); 
    }
    protected void doThings(String data, Map<String, PackageLog> resultmap){
        PackageLog pl = new PackageLog(data);
        if(!pl.getPdfName().equals("")){
            resultMap.put(pl.getPdfName(), pl);
        }
    }
};
Map<String, PackageLog> myMap = reader.readAllLogsIntoMap();

Учтите, что вам нужен только метод newMap(), если вы хотите предоставить различные реализации карт. Вы могли бы сделать new HashMap<K, V>() внутри обобщенного класса.

Возможно, вы также захотите определить подключаемые методы (переопределяемые, возможно, пустые методы) для обработки исключений.

1 голос
/ 10 ноября 2011

Гарри, учитывая, что Java не имеет хорошей поддержки для типов типов, таких как, скажем, язык программирования D, вы должны реорганизовать свой метод, чтобы иметь сигнатуру типа: public Map<String, Object[]> csvToMap(File argFile, char argSeparator, Class[]) {}.Затем вы бы вызвали его как: mymap = csvToMap("/tmp/some.log", ';', { Date.class, String.class, Double.class});.Этот вызов может использоваться для анализа файла CSV, содержащего строки, такие как 2011-11-23;Some Name;232.22

1 голос
/ 10 ноября 2011

Я думаю, что вы должны использовать парсер CSV, например http://opencsv.sourceforge.net/

...