2010-11-04 41 views
0
ID Name Department Salary Designation 
--------------------------------------- 
1 Kent Engineering 100000$ senior-engineer 
2 Smith null  50,000$ administrator 

這些是我有一個大文件的記錄。我需要解析這個文件來檢索工資和指定。關鍵必須是ID,名稱,部門,如果失敗,然後使用ID,名稱.. 我只能使用Java/groovy來做到這一點......我怎麼得到<Salary,Designation>回來......?解析文件以獲取List的有效方法...?

什麼是最有效的方式用grep顯示它給我只能使用的Java/Groovy的

+0

我很好奇,是在該文件中選擇一個分隔符還是比這更「髒」?在提出可能存在缺陷的解決方案之前,瞭解有關格式的更多信息會非常有幫助。 – xlson 2010-11-05 07:45:15

+0

@潘 - 我回答了你的問題嗎?如果是這樣,接受答案 – 2010-12-23 16:59:34

回答

0

您可以將文件解析成一個HashMap只要你需要它保持它的周圍。

它有很高的前期成本,但如果你打算使用它很多,那麼它是有道理的。

然後創建您的鍵和值對象。一定要覆蓋您的密鑰equals

public class Key{ 
    int id; 
    String name; 

    @Override 
    public boolean equals(Object o){...} 
} 
1

創建一個BufferedReader,這將允許您一次讀取一行文件。然後在每行上調用split("[\\\s]"),這將以空格分隔。

您可能還得按摩salary字段,以便將其解析爲數字。

0

我假設你知道如何使用BufferedReader逐行讀取文件,因爲這是這類事情的一個顯而易見的先決條件 - 如果不是這樣,喊叫。

關鍵是你沒有指定的東西。什麼,究竟是,是數據的格式 - 具體來說,確定一個字段結束和另一個字段開始的確切規則是什麼?

如果數據是由製表符分隔(和所述字符是從在數據中出現禁止,即使轉義)然後將溶液很簡單:

// Ignoring general error handling and EOF-checking here 
final String line = bufferedReader.readLine(); 
final String[] fields = line.split("\t"); 

現在你有包含上的字段的陣列該行,所以可以查找fields[3]fields[4]

如果分隔符是「任意數量的空格」,並且空格完全被禁止,那麼您的類似情況也很簡單,您的正則表達式爲line.split(" *")

在更復雜的情況下,包括分隔符在允許轉義或引用時允許出現的情況下,您最好是逐字地遍歷每行並根據分隔符規則手動構建字段集。

1

將每行按空白分隔。

scala> val a = "1 Kent Engineering 100000$ senior-engineer" 
a: java.lang.String = 1 Kent Engineering 100000$ senior-engineer 

scala> a.split("\\s+") 
res1: Array[java.lang.String] = Array(1, Kent, Engineering, 100000$, senior-engineer) 

然後取原始字符串值並解析它們。例如。轉換$ 50,000到數50000:

double salary = Double.parseDouble(array[SALARY_INDEX].replaceAll("[$,]","")) 


java.lang.Double.parseDouble("50,000$".replaceAll("[$,]","")) 
res6: Double = 50000.0 
+0

是的,例子是scala,但是應該很清楚如何使用Java代替。它的工作方式完全相同,只是其中一些語法略有不同。 – I82Much 2010-11-04 17:15:39

0

隨着Guava library捏,解決辦法很簡單,優雅。我們可以通過客觀化的關鍵提高了下面的代碼,處理錯誤等等等等,但你可以做你自己

import java.io.File; 
import java.io.IOException; 
import java.util.Iterator; 
import java.util.Map; 

import com.google.common.base.CharMatcher; 
import com.google.common.base.Charsets; 
import com.google.common.base.Joiner; 
import com.google.common.base.Splitter; 
import com.google.common.collect.Maps; 
import com.google.common.io.Files; 
import com.google.common.io.LineProcessor; 

public class FileProcessor 
{ 

    private static final Splitter SPLITTER = Splitter.on(CharMatcher.WHITESPACE); 

    private static final Joiner KEY_BUILDER = Joiner.on("_").skipNulls(); 

    @SuppressWarnings("unchecked") 
    public static void main(final String[] args) throws IOException 
    { 
     Map<String, SalaryAndDesignation> result = Files.readLines(new File("c:/1.txt"), Charsets.ISO_8859_1, new LineProcessor() { 

      private final Map<String, SalaryAndDesignation> result = Maps.newHashMap(); 

      public Object getResult() 
      { 
       return result; 
      } 

      public boolean processLine(final String line) throws IOException 
      { 
       Iterator<String> columns = SPLITTER.split(line).iterator(); 
       String id = columns.next(); 
       String name = columns.next(); 
       String dept = columns.next(); 

       String key = KEY_BUILDER.join(id, name, "null".equals(dept) ? null : dept); 

       result.put(key, new SalaryAndDesignation(columns.next(), columns.next())); 
       return true; 
      } 
     }); 
     System.out.println(result.size()); 
    } 

    final static class SalaryAndDesignation 
    { 
     String salary; 

     String designation; 

     public SalaryAndDesignation(final String salary, final String designation) 
     { 
      super(); 
      this.salary = salary; 
      this.designation = designation; 
     } 

    } 
} 

我看到使用Groovy導致較小的代碼如下(copy/pasted from here)樣本,但從未使用過它自己

new File("simple.tab").withReader{r-> 
    line = r.readLine(); 
    println "first line: $line" 
    r.splitEachLine("\t"){fields-> 
      println "fields on line: $fields" 
    } 
} 
相關問題