Click here to Skip to main content
12,349,884 members (22,787 online)
Click here to Skip to main content
Add your own
alternative version

Stats

53.9K views
2.2K downloads
92 bookmarked
Posted

C++: Minimalistic CSV Streams

, 5 May 2016 MIT
Rate this:
Please Sign up or sign in to vote.
Read/write CSV in few lines of code!

Introduction

MiniCSV is a small, single header library which is based on C++ file streams and is comparatively easy to use. Without further ado, let us see some code in action.

Writing

We see an example of writing tab-separated values to file using csv::ofstream class. Now you can specify the escape string when calling set_delimiter in version 1.7

#include "minicsv.h"

struct Product
{
    Product() : name(""), qty(0), price(0.0f) {}
    Product(std::string name_, int qty_, float price_) 
        : name(name_), qty(qty_), price(price_) {}
    std::string name;
    int qty;
    float price;
};

int main()
{
    csv::ofstream os("products.txt", std::ios_base::out);
    os.set_delimiter('\t', "##");
    if(os.is_open())
    {
        Product product("Shampoo", 200, 15.0f);
        os << product.name << product.qty << product.price << NEWLINE;
        Product product2("Soap", 300, 6.0f);
        os << product2.name << product2.qty << product2.price << NEWLINE;
    }
    os.flush();
    return 0;
}

NEWLINE is defined as '\n'. We cannot use std::endl here because csv::ofstream is not derived from the std::ofstream.

Reading

To read back the same file, csv::ifstream is used and std::cout is for displaying the read items on the console.

#include "minicsv.h"
#include <iostream>

int main()
{
    csv::ifstream is("products.txt", std::ios_base::in);
    is.set_delimiter('\t', "##");
    if(is.is_open())
    {
        Product temp;
        while(is.read_line())
        {
            is >> temp.name >> temp.qty >> temp.price;
            // display the read items
            std::cout << temp.name << "," << temp.qty << "," << temp.price << std::endl;
        }
    }
    return 0;
}

The output in console is as follows.

Shampoo,200,15
Soap,300,6

Overloaded stream operators

String stream has been introduced in v1.6. Let me show you an example on how to overload string stream operators for the Product class. The concept is the same for file streams.

#include "minicsv.h"
#include <iostream>

struct Product
{
    Product() : name(""), qty(0), price(0.0f) {}
    Product(std::string name_, int qty_, float price_) : name(name_), qty(qty_), price(price_) {}
    std::string name;
    int qty;
    float price;
};

template<>
inline csv::istringstream& operator >> (csv::istringstream& istm, Product& val)
{
    return istm >> val.name >> val.qty >> val.price;
}

template<>
inline csv::ostringstream& operator << (csv::ostringstream& ostm, const Product& val)
{
    return ostm << val.name << val.qty << val.price;
}

int main()
{
    // test string streams using overloaded stream operators for Product
    {
        csv::ostringstream os;
        os.set_delimiter(',', "$$");
        Product product("Shampoo", 200, 15.0f);
        os << product << NEWLINE;
        Product product2("Towel, Soap, Shower Foam", 300, 6.0f);
        os << product2 << NEWLINE;

        csv::istringstream is(os.get_text().c_str());
        is.set_delimiter(',', "$$");
        Product prod;
        while (is.read_line())
        {
            is >> prod;
            // display the read items
            std::cout << prod.name << "|" << prod.qty << "|" << prod.price << std::endl;
        }
    }
    return 0;
}

This is what is displayed on the console.

Shampoo|200|15
Towel, Soap, Shower Foam|300|6

What if the type has private members? Create a member function that takes in the stream object.

class Product
{
public:
    void read(csv::istringstream& istm)
    {
        istm >> this->name >> this->qty >> this->price;
    }
};

template<>
inline csv::istringstream& operator >> (csv::istringstream& istm, Product& prod)
{
    prod.read(istm);
    return istm;
}

Conclusion

MiniCSV is a small CSV library that is based on C++ file streams. Because delimiter can be changed on the fly, I have used this library to write file parser for MTL and Wavefront OBJ format in a relatively short time compared to handwritten with no library help. MiniCSV is now hosted at Github. Thank you for reading!

History

  • 2014-03-09: Initial Release
  • 2014-08-20: Remove the use of smart ptr
  • 2015-03-23: 75% perf increase on writing by removing the flush on every line, fixed the lnk2005 error of multiple redefinition. read_line replace eof on ifstream.
  • 2015-09-22: v1.7: Escape/unescape and surround/trim quotes on text
  • 2015-09-24: Added overloaded stringstream operators example.
  • 2015-09-27: Stream operator overload for const char* in v1.7.2.
  • 2015-10-04: Fixed G++ and Clang++ compilation errors in v1.7.3.
  • 2015-10-20: Ignore delimiters within quotes during reading when enable_trim_quote_on_str is enabled in v1.7.6. Example: 10.0,"Bottle,Cup,Teaspoon",123.0 will be read as as 3 tokens : <10.0><Bottle,Cup,Teaspoon><123.0>
  • 2016-05-05: Now the quote inside your quoted string are escaped now. Default escape string is "&quot;" which can be changed through os.enable_surround_quote_on_str() and is.enable_trim_quote_on_str()

Related Articles

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

Shao Voon Wong
Software Developer (Senior)
United States United States
IT Certifications

  • IT Infrastructure Library Foundational (ITIL v3)
  • Scrum Alliance Certified Scrum Master (CSM)
  • EC-Council Certified Secure Programmer (ECSP) .NET
  • EC-Council Certified Ethical Hacker (CEH)
  • EC-Council Certified Security Analyst (ECSA)
  • Certified Secure Software Lifecycle Professional (CSSLP)

You may also be interested in...

Comments and Discussions

 
QuestionUnicode? Pin
Tom Tom16-May-16 13:32
memberTom Tom16-May-16 13:32 
AnswerRe: Unicode? Pin
Shao Voon Wong16-May-16 16:02
professionalShao Voon Wong16-May-16 16:02 
GeneralMy vote of 5 Pin
Alexander Navalov7-May-16 0:45
professionalAlexander Navalov7-May-16 0:45 
GeneralMy vote of 5 Pin
Alexander Navalov7-May-16 0:36
professionalAlexander Navalov7-May-16 0:36 
GeneralGreat WorkShao! Pin
david2174222-Oct-15 4:08
memberdavid2174222-Oct-15 4:08 
QuestionUse in many classes of project Pin
vasvladal21-Oct-15 2:32
membervasvladal21-Oct-15 2:32 
AnswerRe: Use in many classes of project Pin
Shao Voon Wong21-Oct-15 2:50
professionalShao Voon Wong21-Oct-15 2:50 
GeneralRe: Use in many classes of project Pin
vasvladal21-Oct-15 18:13
membervasvladal21-Oct-15 18:13 
SuggestionDesign flaws Pin
Rado_28-Sep-15 2:15
memberRado_28-Sep-15 2:15 
GeneralRe: Design flaws Pin
Shao Voon Wong28-Sep-15 3:08
professionalShao Voon Wong28-Sep-15 3:08 
GeneralMy vote of 5 Pin
gordon8825-Sep-15 8:37
membergordon8825-Sep-15 8:37 
QuestionVery useful ! Pin
Member 94147403-Jun-15 1:40
memberMember 94147403-Jun-15 1:40 
AnswerRe: Very useful ! Pin
Shao Voon Wong8-Jun-15 23:55
professionalShao Voon Wong8-Jun-15 23:55 
SuggestionRe: Very useful ! Pin
Shao Voon Wong21-Oct-15 18:50
professionalShao Voon Wong21-Oct-15 18:50 
GeneralRe: Very useful ! Pin
Member 941474021-Oct-15 20:53
memberMember 941474021-Oct-15 20:53 
QuestionImproper string initialization Pin
Andrew Komiagin22-Mar-15 22:58
memberAndrew Komiagin22-Mar-15 22:58 
AnswerRe: Improper string initialization Pin
Shao Voon Wong24-Mar-15 19:17
professionalShao Voon Wong24-Mar-15 19:17 
QuestionWhat should the separator character be? Pin
Roger Bamforth21-Aug-14 3:08
memberRoger Bamforth21-Aug-14 3:08 
AnswerRe: What should the separator character be? Pin
Shao Voon Wong25-Aug-14 18:51
professionalShao Voon Wong25-Aug-14 18:51 
QuestionCSV Data Pin
WintonRoseland21-Aug-14 2:02
memberWintonRoseland21-Aug-14 2:02 
QuestionSeparator character Pin
Wombaticus20-Aug-14 1:25
memberWombaticus20-Aug-14 1:25 
AnswerRe: Separator character Pin
Shao Voon Wong24-Sep-15 2:30
professionalShao Voon Wong24-Sep-15 2:30 
QuestionSome thoughts on how to improve the lib Pin
Member 102726144-Apr-14 0:58
memberMember 102726144-Apr-14 0:58 
AnswerRe: Some thoughts on how to improve the lib Pin
Wong Shao Voon7-Apr-14 19:41
professionalWong Shao Voon7-Apr-14 19:41 
Questiongreat article! Pin
Frank Reidar Haugen2-Apr-14 6:26
memberFrank Reidar Haugen2-Apr-14 6:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160621.1 | Last Updated 5 May 2016
Article Copyright 2016 by Shao Voon Wong
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid