2010-11-04 19 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" 
    } 
} 
相关问题