加载中…
个人资料
了凡春秋
了凡春秋
  • 博客等级:
  • 博客积分:0
  • 博客访问:19,299
  • 关注人气:2,078
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

读取Csv文件(c实现)

(2011-04-26 22:32:38)
标签:

csv文件

读取

c实现

动态二维数组

分配

释放

分类: VC

最近有个项目要读取Csv文件的内容,Csv文件还是蛮常用,所以想封装好,便于以后使用。

使用方法可以从下面的main函数看出来,首先用ReadCsvData读取Csv文件到一个数组中,然后就可以使用GetCsvData读取想要的某行的数据了,最后结束时要用FreeCsvData释放空间。

#include <stdio.h>
#include <stdlib.h> // For system("pause");

#include "ReadCsvFile.h"

void main(){
    char filename[] = "REF.csv";
    double ddata[7];
    int i;

    // 读文件
    if (!ReadCsvData(filename))
        printf_s("The file %s was not opened\n", filename);
    else
        printf_s("The file %s was read successfully\n", filename);

    // 显示部分数据
    for (i = 1; i < 10 ; i++ )
    {
        GetCsvData(i, ddata);

        printf_s("%.0lf\t%.0lf\t%.0lf\t%.0lf\t%.0lf\t%.0lf\t%.0lf\n",
            ddata[0],ddata[1],ddata[2],ddata[3],ddata[4],ddata[5],ddata[6]);
     

    // 释放Csv空间
    FreeCsvData();


    system("pause");
}

运行结果如下

The file REF.csv was read successfully
-30894  25745   15447   36043   -56639       0
-30876  25756   15449   36030   -56629       0
-30858  25768   15451   36017   -56618       0
-30804  25802   15456   35978   -56587       0
-30749  25837   15462   35940   -56555       0
-30568  25951   15481   35811   -56450       0
-30314  26111   15508   35631   -56303       0
-29988  26317   15542   35399   -56115       0
-29590  26569   15584   35116   -55884       0
请按任意键继续. . .

封装文件如下:

ReadCsvFile.h
void FreeCsvData();
int ReadCsvData(char* csvFilePath);
void GetCsvData(int iIndex, double* dAimPos);

ReadCsvFile.c

//////////////////////////////////////////////////////////////////////////
// Read csv file data
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <memory.h> // for memset
#include <stdlib.h> // For malloc, free

#define MAX_LINE_SIZE 256
#define GET_DATA(row, col) gdCsvData[(row - 1)*giNumCol + col - 1] // row为1到giNumRow,col为1到giNumCol 使用一维数组,动态分配、释放更方便

double* gdCsvData = NULL;
int giNumData = 0;
int giNumRow = 0;
int giNumCol = 7; // 文件中一行有多少数据,这个要根据实际文件定,还要相应改ReadCsvData函数中sscanf_s的读取个数

// get total lines of file 此函数可以单独拿来用,可以获取文本文件的有效行数
int GetTotalLineCount(FILE* fp)
  
    int i = 0;
    char strLine[MAX_LINE_SIZE];

    fseek(fp,0,SEEK_SET);
    while (fgets(strLine, MAX_LINE_SIZE, fp))
        i++;
    fseek(fp,0,SEEK_SET);
    return i;
}

// assign space for gdCsvData
int AssignSpaceForData(int inumdata){
    gdCsvData = (double*)malloc(sizeof(double)*inumdata); 
    if (gdCsvData == NULL)
        return 0;

    memset(gdCsvData, 0, sizeof(double)*inumdata);

    return 1;
}

// free space for dCsvDate
void FreeCsvData(){
    free(gdCsvData);
    gdCsvData = NULL;
}

// read data from csv file
int ReadCsvData(char* csvFilePath)
{
    FILE* fCsv;
    char strLine[MAX_LINE_SIZE];
    int ierr;
    int iloop;

    // 已经有了数据,则先删除
    if (gdCsvData != NULL)
        FreeCsvData();

    // 打开文件
    if( fopen_s( &fCsv, csvFilePath, "r" ) != 0 )
        return 0;
    else
    {
        // 确定动态数组的大小,然后开辟空间
        giNumRow = GetTotalLineCount(fCsv);
        giNumData = giNumRow*giNumCol;
        AssignSpaceForData(giNumData);

        // 读取数据
        for (iloop = 1; iloop <= giNumRow; iloop++)
        {
            if (fgets(strLine, MAX_LINE_SIZE, fCsv))
            {
                ierr = sscanf_s(strLine, "%lf,%lf,%lf,%lf,%lf,%lf,%lf",
                    &GET_DATA(iloop, 1),
                    &GET_DATA(iloop, 2),
                    &GET_DATA(iloop, 3),
                    &GET_DATA(iloop, 4),
                    &GET_DATA(iloop, 5),
                    &GET_DATA(iloop, 6),
                    &GET_DATA(iloop, 7)); // 要根据情况修改,比如一行不是7个数据

                // 如果某行没有读取全数据,则读取结束
                if (ierr != giNumCol)
                    break;
                             
        }

        // 关闭文件
        fclose(fCsv);
    }
    return 1;
}

// get csv data according to row(from 1 to giNumRow)
void GetCsvData(int irow, double* dAimPos){
    int i;

    // 修正行数
    if (irow < 1)
        irow = 1;
    if (irow > giNumRow)
        irow = giNumRow;   

    // 读取数据
    for (i = 1; i <= giNumCol; i++)
        dAimPos[i-1] = GET_DATA(irow, i);
}

 

By the way,刚开始是用二维数组动态开辟空间的,开辟和释放都很麻烦,如下

// assign space for gdCsvData

void AssignSpaceForData(int irow, int icolumn){
    int i;      

   gdCsvData = (double**)malloc(sizeof(double*)*irow); 
    if (gdCsvData == NULL)
    {
        printf_s("out of memory\n");
        exit(0);
    }
    for (i = 0; i < irow; i++) 
    {
        gdCsvData[i] = (double*)malloc(sizeof(double)*icolumn);
        if (gdCsvData == NULL)
        {
            printf_s("out of memory\n");
            exit(0);
        }
    }
}

 

// free space for dCsvDate
void FreeSpaceOfData(int irow, int icolumn){
    int i;
    for (i=0; i<irow; i++)  
        free(gdCsvData[i]);  
    free(gdCsvData);
}

所以对于动态分配二维数组最好还是用一维数据加宏的方式代替。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有