6

我知道有很多相关的问题,我已经阅读了它们,但仍然没有对如何读取-处理-写入有一些基本的了解。以下面的函数为例,它使用clojure-csv库来解析一行

(defn take-csv
  "Takes file name and reads data."
  [fname]
  (with-open [file (reader fname)]
    (doseq [line (line-seq file)]
      (let [record (parse-csv line)]))))

我想获得的是作为结果读入某个集合的数据,(def data (take-csv "file.csv"))然后再对其进行处理。所以基本上我的问题是我如何返回record或者更确切地说是一个记录列表。

4

3 回答 3

10

“doseq”通常用于有副作用的操作。在您创建记录集合的情况下,您可以使用“map”:

(defn take-csv
  "Takes file name and reads data."
  [fname]
  (with-open [file (reader fname)]
    (doall (map (comp first csv/parse-csv) (line-seq file)))))

更好地解析整个文件以减少代码:

(defn take-csv
  "Takes file name and reads data."
  [fname]
  (with-open [file (reader fname)]
    (csv/parse-csv (slurp file))))

您也可以使用 clojure.data.csv 代替 clojure-csv.core。只应在之前的函数中将 parse-csv 重命名为 take-csv。

(defn put-csv [fname table]
  (with-open [file (writer fname)]
    (csv/write-csv file table)))
于 2012-11-30T09:20:14.040 回答
3

对于 .csv 文件可以做的所有事情,我建议使用 clojure-csv 或 clojure.data.csv。我主要使用 clojure-csv 读取 .csv 文件。

以下是我在大多数 Clojure 程序中使用的实用程序库中的一些代码片段。

from util.core

    (ns util.core
      ^{:author "Charles M. Norton",
        :doc "util is a Clojure utilities directory"}

      (:require [clojure.string :as cstr])
      (:import java.util.Date)
      (:import java.io.File)
      (:use clojure-csv.core))

(defn open-file
"Attempts to open a file and complains if the file is not present."

[file-name]
(let [file-data (try 
               (slurp file-name)
               (catch Exception e (println (.getMessage e))))]
  file-data))

(defn ret-csv-data
"Returns a lazy sequence generated by parse-csv.
 Uses open-file which will return a nil, if
 there is an exception in opening fnam.

 parse-csv called on non-nil file, and that
 data is returned."

[fnam]
(let [csv-file (open-file fnam)
      inter-csv-data (if-not (nil? csv-file)
                       (parse-csv csv-file)
                        nil)

      csv-data 
        (vec (filter #(and pos? (count %) 
           (not (nil? (rest %)))) inter-csv-data))]

    (if-not (empty? csv-data)
      (pop csv-data)
       nil)))

(defn fetch-csv-data
    "This function accepts a csv file name, and returns parsed csv data,
     or returns nil if file is not present."

    [csv-file]
        (let [csv-data (ret-csv-data csv-file)]
            csv-data))

读入 .csv 文件后,如何处理其内容是另一回事。通常,我从一个金融系统(如财产评估)获取 .csv“报告”,并将数据格式化以上传到另一个金融系统的数据库中,如计费。

我经常会使用zipmap每个 .csv 行,这样我就可以按列名提取数据(已读取列名),甚至可以制作一系列zipmap'ped .csv 行。

于 2012-11-30T13:44:15.750 回答
2

只是为了添加这个好的答案,这里是一个完整的例子

首先,将clojure-csv添加到您的依赖项中

(ns scripts.csvreader
  (:require [clojure-csv.core :as csv]
            [clojure.java.io :as io]))

(defn take-csv
 "Takes file name and reads data."
 [fname]
 (with-open [file (io/reader fname)]
  (-> file
      (slurp)
      (csv/parse-csv))))

用法 (take-csv "/path/youfile.csv")

于 2019-11-27T12:00:58.343 回答