root/Csv.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CCsv
  2. CCsv
  3. GetValue
  4. GetRowSize
  5. GetColumnSize
  6. RemoveAll
  7. AddRow
  8. Save
  9. CountDQuotation
  10. StripQuotation
  11. AddQuotation

/*
 * Copyright (C) 2002-2003 chik, s.hiranaka
 * For license terms, see the file COPYING in this directory.
 */

// Csv.cpp:
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "pochy.h"
#include "Csv.h"
#include "StrTok.h"
#include "lib.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////

CCsv::CCsv(LPCTSTR path)
{
        if(path == NULL)
                return;
        CString buf;
        CString message;
        CStdioFile read_file;
        if(!read_file.Open(path, CFile::modeRead | CFile::typeText)){
                message.Format("%sが開けません", path);
                AfxMessageBox(message);
                return;
        }

        CStringArray tmp_array;
        buf.Empty();
        while(read_file.ReadString(buf)){
                tmp_array.Add(buf);
                buf.Empty();
        }

        m_data.RemoveAll();
        m_data.SetSize(tmp_array.GetSize());

        int start;
        int start2;
        int end;
        for(int n=0; n<tmp_array.GetSize(); n++){
                buf = tmp_array.GetAt(n);
                start=0;
                while((end = buf.Find(",", start)) != -1){
                        // if buf include (") or (,)
                        if(buf[start] == '"'){
                                while(1){
                                        int i = CountDQuotation(buf, start, end);
                                        if(i%2 == 1 || i == 1){
                                                break;
                                        }else{
                                                start2 = end+1;
                                                end = buf.Find(",", start2);
                                                if(end == -1){
                                                        end = buf.GetLength()-1;
                                                        break;
                                                }
                                                continue;
                                        }
                                }
                        }
                        if(buf[start] == '"'){
                                CString tmp = buf.Mid(start+1, end-start-1);
                                this->StripQuotation(tmp);
                                m_data[n].Add(tmp);
                        }else{
                                m_data[n].Add(buf.Mid(start, end-start));
                        }
                        start = end+1;
                }
                buf = buf.Mid(start);
                buf.TrimRight();
                m_data[n].Add(buf);
        }
}

CCsv::~CCsv()
{

}

CString CCsv::GetValue(int row, int column)
{
        CString buf;
        buf.Empty();

        if(row >= GetRowSize())
                return buf;
        else if(column >= GetColumnSize(row))
                return buf;

        return m_data[row].GetAt(column);
}

int CCsv::GetRowSize()
{
        return m_data.GetSize();
}

int CCsv::GetColumnSize(int row)
{
        return m_data[row].GetSize();
}

void CCsv::RemoveAll()
{
        m_data.RemoveAll();
}

void CCsv::AddRow(CStringArray *new_row)
{
        int size = m_data.GetSize();
        m_data.SetSize(size+1);
        for(int i=0; i<new_row->GetSize(); i++)
                m_data[size].Add(new_row->GetAt(i));
}

void CCsv::Save(LPCTSTR path)
{
        CString buf;
        CString data;
        CString tmp;
        data.Empty();
        buf.Empty();
        for(int i=0; i<m_data.GetSize(); i++){
                for(int j=0; j<m_data[i].GetSize(); j++){
                        tmp = m_data[i].GetAt(j);
                        if(tmp.Find("\"") != -1 || tmp.Find(",") != -1)
                                this->AddQuotation(tmp);
                        if(j==0){
                                buf += tmp;
                        }else{
                                buf += ","+tmp;
                        }
                }
                data += buf+"\r\n";
                buf.Empty();
        }
        FILE* file = fopen(path, "wb");
        fwrite(data, sizeof(char), data.GetLength(), file);
        fclose(file);
}

// count number of double-quotation(") just before single-quotation(').
// end must be position of single-quotation(') in buf.
// if return of this function is odd, here mean this single quotation(') is separation mark of csv.
int CCsv::CountDQuotation(CString buf, int start, int end)
{
        int n=1;
        while(buf[end-n] == '"' && end-n > start){
                n++;
        }
        return n-1;
}

void CCsv::StripQuotation(CString &buf)
{
        int p=0;
        while((p = buf.Find('"', p)) != -1){
                buf.Delete(p);
                p=p+1;
        }
}

void CCsv::AddQuotation(CString &buf)
{
        BOOL flag = FALSE;
        CString tmp;
        for(int i=0; i<buf.GetLength(); i++){
                if(buf[i] == '"'){
                        flag |= TRUE;
                        tmp += "\"\"";
                }else if(buf[i] == ','){
                        flag |= TRUE;
                        tmp += buf[i];
                }else{
                        tmp += buf[i];
                }
        }
        if(flag)
                buf = "\""+tmp+"\"";
}

/* [<][>][^][v][top][bottom][index][help] */