How can I use read-csv-file to read from a string instead?

135 Views Asked by At

The 2htdp/batch-io library contains the useful read-csv-file procedure for reading a CSV file into a list. It takes a filename as its argument. Unfortunately, it does not take a string containing CSV as its argument. Suppose I have a CSV in a string variable and I want to use read-csv-file to parse it. Is there a way to avoid saving the CSV to a file just to be able to parse the CSV?

The documentation says:

reads the standard input device (until closed) or the content of file f and produces it as a list of lists of comma-separated values.

The standard input feature could probably be exploited to achieve this, but I don't know how to proceed with this idea.

2

There are 2 best solutions below

1
Flux On BEST ANSWER

I found a way to make read-csv-file read from a string instead:

> (require 2htdp/batch-io)
> (define csv-string "one,one,one\ntwo,two,two")
> (parameterize ([current-input-port (open-input-string csv-string)])
    (read-csv-file 'stdin))
'(("one" "one" "one") ("two" "two" "two"))

This works by changing the standard input to be the CSV string.

@Ryan Schaefer's answer about simulate-file is great, but I feel a bit uncomfortable with using functionality that is still "under development" and not properly documented. As simulate-file's documentation says:

Note: this form is under development and will be documented in a precise manner after it is finalized and useful for a wide audience.

1
Ryan Schaefer On

The 2htdp libraries are meant for beginners are thus are less flexible than other csv libraries. Therefore, you have two options:

  1. batch-io provides simulate-file which is something similar to what you want, but nothing as clean as wrapping your string in a function which makes it into a file like object:
> (simulate-file read-csv-file "test,test,test")
(list (list "test" "test" "test"))
  1. Use csv-reading (csv-reading must be downloaded but just (require csv-reading) and continue through the errors it gives you):
#lang racket
(require csv-reading)
> (csv->list "test,test,test")
(list (list "test" "test" "test"))

If batch-io were more general it would be take in a string? or an input-port? but it does not.