【问题标题】:Need help parsing a File in Java需要帮助在 Java 中解析文件
【发布时间】:2011-04-06 15:14:49
【问题描述】:

我目前正在做一个小型数据结构项目,我正在尝试获取全国大学的数据;然后对它们进行一些数据操作。我在这里找到了这个数据:http://archive.ics.uci.edu/ml/machine-learning-databases/university/university.data

但是,这个数据的问题是(我从网站上引用):“它是一个 LISP 可读文件,在数据文件的末尾有一些相关的功能。”我计划获取这些数据并将其保存为 .txt 文件。

文件看起来有点像:

(def-instance Adelphi
      (state newyork)
      (control private)
      (no-of-students thous:5-10)
      (male:female ratio:30:70)
      (student:faculty ratio:15:1)
      (sat verbal 500)
      (sat math 475)
      (expenses thous$:7-10)
      (percent-financial-aid 60)
      (no-applicants thous:4-7)
      (percent-admittance 70)
      (percent-enrolled 40)
      (academics scale:1-5 2)
      (social scale:1-5 2)
      (quality-of-life scale:1-5 2)
      (academic-emphasis business-administration)
      (academic-emphasis biology))
(def-instance Arizona-State
      (state arizona)
      (control state)
      (no-of-students thous:20+)
      (male:female ratio:50:50)
      (student:faculty ratio:20:1)
      (sat verbal 450)
      (sat math 500)
      (expenses thous$:4-7)
      (percent-financial-aid 50)
      (no-applicants thous:17+)
      (percent-admittance 80)
      (percent-enrolled 60)
      (academics scale:1-5 3)
      (social scale:1-5 4)
      (quality-of-life scale:1-5 5)
      (academic-emphasis business-education)
      (academic-emphasis engineering)
      (academic-emphasis accounting)
      (academic-emphasis fine-arts))

      ......

The End Of the File:

(dfx def-instance (l)
  (tlet (instance (car l) f-list (cdr l))
    (cond ((or (null instance) (consp instance))
           (msg t instance " is not a valid instance name (must be an atom)"))
          (t (make:event instance)
             (push instance !instances)
             (:= (get instance 'features)
                 (tfor (f in f-list)
                   (when (cond ((or (atom f) (null (cdr f)))
                                (msg t f " is not a valid feature "
                                       "(must be a 2 or 3 item list)") nil)
                               ((consp (car f))
                                (msg t (car f) " is not a valid feature "
                                     "name (must be an atom)") nil)
                               ((and (cddr f) (consp (cadr f)))
                                (msg t (cadr f) " is not a valid feature "
                                     "role (must be an atom)") nil)
                               (t t)))
                   (save (cond ((equal (length f) 3)
                                (make:feature (car f) (cadr f) (caddr f)))
                               (t (make:feature (car f) 'value (cadr f)))))))
             instance))))

(set-if !instances nil)



(dex run-uniq-colleges (l n)
  (tfor (sc in l)
    (when (cond ((ge (length *events-added*) n))
                ((not (get sc 'duplicate))
                 (run-instance sc)
~                 (remprop sc 'features)
                 nil)
                (t (remprop sc 'features) nil)))
    (stop)))

我最感兴趣的数据是学生人数、学术重点和学校名称。

非常感谢任何帮助。

【问题讨论】:

    标签: java parsing file lisp project


    【解决方案1】:

    您可以处理/使用 Lisp 文件解析器,或者您可以忽略它所使用的语言并专注于数据。你提到你需要:

    • 学校名称
    • 学生人数
    • 学术重点

    您可以grep 相关关键字(def-instance、no-of-students、academic-emphasis),这将使您获得(基于您的示例):

    (def-instance Adelphi
          (no-of-students thous:5-10)
          (academic-emphasis business-administration)
          (academic-emphasis biology))
    (def-instance Arizona-State
          (no-of-students thous:20+)
          (academic-emphasis business-education)
          (academic-emphasis engineering)
          (academic-emphasis accounting)
          (academic-emphasis fine-arts))
    

    这简化了特定解析器的编写(def-instance 后跟名称,然后下一个 def-instance 之前的所有学术重点和 no-of-students 都引用之前定义的名称)

    【讨论】:

      【解决方案2】:

      您是否考虑过在 Java VM 的 Lips 解释器中运行该 Lisp 文件?

      例如,与 JSR-223 兼容的 Armed Bear Common Lisp 会很乐意解析您的文件。

      使用 JSR-233,您将能够访问脚本定义的变量(如 Adephi 和其他变量),如 examples 显示。

      编辑来自评论请求,一些补充解释(尽管对我来说似乎很简单)。

      所以,假设你的类路径中有 Armed Bear Common Lisp,file 是你的脚本的绝对文件名(这个例子很大程度上是受JSR-223 example 启发/借用的)。

      首先,安装脚本引擎

      ScriptEngineManager scriptManager = new ScriptEngineManager();
      scriptManager.registerEngineExtension("lisp", new AbclScriptEngineFactory());
      ScriptEngine lispEngine = scriptManager.getEngineByExtension("lisp");
      

      然后,在脚本引擎中加载您的脚本

      Object eval = lispEngine.eval(new FileReader(file));
      

      现在,带着一个小调试器,去看看里面有什么(我没有勇气安装所有的环境来为你完成这项工作)

      【讨论】:

      • 我该怎么做呢?
      【解决方案3】:

      如果您要解析 lisp,则需要注意“堆栈”。

      当您遇到( 时,您会压入堆栈。您现在处于一个新的范围内,比以前高一级。

      类似地,当您遇到) 时,您会从堆栈中弹出 - 完成该层并下一层。

      所以在这种情况下,您处于空状态开始。您遇到的第一件事是(,所以现在您处于“定义”状态。 (我只是编出来的。随便你怎么称呼它。)你遇到了 def-instance 标记,然后是大学的名称。您继续阅读并遇到另一个((忽略空格,只解析标记。)这使您处于属性状态。 (我也编造了。)既然你是从定义跳到属性,现在就可以创建你的对象了。 UnivData data = new UnivData(parsedToken) 之类的东西(其中 parsedToken 的计算结果为“Adelphi”。

      好的,回到属性 - 您首先阅读了 (,然后阅读了“state”和“newyork”,然后是另一个 )。因此,您可以将当前 UnivData 的状态变量分配给 newyork。

      您对所有属性重复此行为,但在学术强调之后您会遇到额外的)。这是您关闭当前对象并开始寻找另一个对象的提示。

      起初,我很想说使用地图。有多个学术重点标记的事实表明您应该使用更好的数据结构,也许是 Map>。滚动您自己的具有 String 的 Property 类可能会更好,或者如果它获取多个值,它会切换到字符串列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-06
        • 1970-01-01
        • 2010-12-31
        • 2011-08-15
        相关资源
        最近更新 更多