1

I've got a function that makes something equivalent to a web request, and it returns a formatted CSV. My goal is to now import this data into CsvHelper. However, I can't seem to get CSVParser to read from static text, only from a stream.

I could write the output to a file then read it back, but I feel that doesn't make much sense here.

I'm not tied down at all to CsvHelper, however I can't seem to find a CSV library that supports this behavior. How should I do this?

var csvString = functionThatReturnsCsv()
/* as string:
columnA,columnB
dataA,dataB
*/

// my goal
???.parse(csvString)
1
  • Note (to anyone visiting this question and looking at the answers) that using a StringReader (as shown by David Specht's answer) is the approach that is more convenient, and leads to simpler and ultimately more readable code compared to converting the string to a byte array to a MemoryStream. After all, any CSV parser would need to translate the byte stream back into text characters anyway. (A CSV parser not accepting a text source in some form - for example, a TextReader - is not really worth considering, imo) Commented Jun 6, 2019 at 19:24

2 Answers 2

5

You can convert the string to a Stream in-memory and then use that as the source for your CSV reader:

public static Stream StringAsStream(string value)
{
    return StringAsStream(value, System.Text.Encoding.UTF8);
}

public static Stream StringAsStream(string value, System.Text.Encoding encoding)
{
    var bytes = encoding.GetBytes(value);
    return new MemoryStream(bytes);
}

Usage:

using (var stream = StringAsStream("hello"))
{
    // csv reading code here
}

or

using (var stream = StringAsStream("hello", Encoding.Ascii))
{
    // csv reading code here
}

Try it online

Note If you are reading from a source that can return a Stream (like a web request), you should use that Stream rather than doing this.

Sign up to request clarification or add additional context in comments.

4 Comments

Can I ask why you're using a using directive here rather than just using the var in the code?
While you don't need to use Dispose with MemoryStream, it's good practice for any Stream you consume since they typically represent unmanaged resources (the garbage collector can't collect these). using will automatically clal Dispose once the using block completes - even in the event of an exception. See here for more info on what using does.
Ok. So if I wanted to make a function that would return the stdout of another program, I would return the standard output from the using definition, correct? (like this rextester.com/VII34075)
That's what I ended up doing and it worked. Thanks for your help!
4

You could use StringReader. The CsvReader constructor takes a TextReader argument rather than a Stream. If you did have a stream instead of a string, just replace StringReader with StreamReader.

public static void Main(string[] args)
{    
    using (var reader = new StringReader(FunctionThatReturnsCsv()))
    using (var csv = new CsvReader(reader))
    {
        var results = csv.GetRecords<Foo>().ToList();
    }            
}

public static string FunctionThatReturnsCsv()
{
    return "columnA,columnB\ndataA,dataB";
}

public class Foo
{
    public string columnA { get; set; }
    public string columnB { get; set; }
}          

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.