| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3243 人关注过本帖, 1 人收藏
标题:CSV合并的问题
只看楼主 加入收藏
wube
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:23
帖 子:1820
专家分:3681
注 册:2011-3-24
收藏
得分:0 
會嗎?轉成這樣不是比較好看?
111.rar (3.1 MB)

不要選我當版主
2015-03-12 15:56
wube
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:23
帖 子:1820
专家分:3681
注 册:2011-3-24
收藏
得分:0 
再說原檔長這樣...
图片附件: 游客没有浏览图片的权限,请 登录注册

不要選我當版主
2015-03-12 15:57
AleTiff
Rank: 3Rank: 3
等 级:论坛游侠
威 望:4
帖 子:64
专家分:157
注 册:2015-3-30
收藏
得分:0 
呼,我看完了。感觉很棒。

由于是解决实际问题,在最开始 wube 自己写的 MergeCSV() 函数里,已经达成了目的。但没想到后面越来越精彩。

TonyDeng 贡献的代码非常强悍,在只做一遍遍历下,直接利用 strcat() 函数把存在于不同文件里的相同行拼接完成,最后利用 fprintf()函数直接格式化输出到目标文件,干净利落。

下面我也贴一下我对这个问题的实现,算是我对解决这个问题的一点思考,不过我是向来不做验证的,万一代码有错误的话,权当看一种思路吧。

首先,因为需要做行与行的拼接,针对这么多文件,做一次遍历,确定文件最大行数是有好处的,以此保证所有文件都是规则地一行行拼接。
之后,我希望这些文件,都纳入我设计好的某种数据结构里,当然,我不需要真的去声明一种特殊的数据结构,只是要让它便于我处理就可以。
所以我选择 0x0D0A 和 0x0000 做为未处理文件的行分割和文件分割。于是我就可以把这许多文件统统收纳到一个文件或者内存块中,为下一
步处理提供方便。

由于我已经在第一次遍历的时候知道了最大行数(开始我不知道这么多文件,其实每个文件的行数都不一定相同),所以我在收纳成一个文件的
过程中,有意对未满足行数的单个文件增加了 0x0D0A,补足不足的行数,使得每个文件行数都相同,同时我记录下了每个文件放入一整个文件
时,它们各自在整合文件里的位置,这样在后续的步骤里,我可以直接移动指针来逐一访问原来每个文件的对应行。

经过以上处理后,最后的合并就变得很容易了:不断移动指针,取出对应的一行一行,放入到结果文件就完成了。

代码没有做优化,后来发现这几百个文件全合起来也就 8M 不到,可以直接开一个 8M 的内存来存放,效率肯定会高不少。

为什么 TonyDeng 和 wube 都已经解决掉的代码我还去自己实现一遍?首先是因为好玩,其次这个代码还很容易加入数据分析,再次,就是,如
果把这个有点像乱数拼接的东西放到网络组包里不知道会不会有点更实用的意图?

最后就是向为此问题做出贡献的大神们致敬,我来过、我思考过、我也努力过了,不管它是不是还有用。


程序代码:
// http://bbs.bccn.net/viewthread.php?tid=44246
// 让分布在几百个 csv 文件中各行连接成单一行

#include "stdafx.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>


#ifdef _WIN32
    #include<direct.h>
    #define getcurrentdir _getcwd
#else
    #include <unistd.h>
    #define getcurrentdir getcwd
#endif

char* getInputfile(char* dir, char* buffer, int i)
{
    char currDir[80];
    if( !dir ){
        getcurrentdir(currDir,sizeof(currDir));
        sprintf( buffer, "%s\\datafile\\%04d.csv", currDir, i);
    }else
        sprintf( buffer, "%s\\datafile\\%04d.csv", dir, i);
    return buffer;
}

int lineScan(FILE* f, char* buffer, int Size)
{
    int lines = 0;    
    while(!feof(f)) { fgets(buffer, Size, f); lines++;}
    rewind(f);
    return lines;
}

int maxLine(int start, int end)
{
    const int bufferCount = 1024 * 4;
    FILE* f = NULL;
    char fullname[260];
    int counter = 0;
    int result = 0;

    char* line = (char*)malloc( bufferCount );
    for(int i = start; i <= end; ++i){
        memset( fullname, 0, sizeof(fullname)/sizeof(fullname[0]) );
        getInputfile(NULL, fullname, i);
        f = fopen(fullname, "r");
        if( !ferror(f) ) counter = lineScan(f, line, bufferCount);
        else counter = 0;
        fclose(f);
        result = counter > result ? counter:result;
    }
    free(line);
    return result;
}

void preCompile(long* headRec, FILE* destFile, int start, int end)
{
    const short empty = 0;
    const short feed = 0x0a0d;
    const int buffercount = 1024 * 100;

    FILE* inputfile = NULL;
    char fullname[260];
    
    short two = 0;
    size_t byteRead = 0;
    size_t byteWrite = 0;

    int fileLine = 0;
    int maxline = maxLine(start, end);
    char* buffer = (char*)malloc( buffercount );

    for(int i = start; i <= end; ++i){
        memset( fullname, 0, sizeof(fullname)/sizeof(fullname[0]) );
        getInputfile(NULL, fullname, i);

        memset( buffer, 0, buffercount );
        inputfile = fopen( fullname, "rb");
        if( !ferror(inputfile) ){
            headRec[i] = ftell(destFile);
            fileLine = lineScan(inputfile, buffer, buffercount);
            byteRead = fread(buffer, sizeof(char), buffercount, inputfile);
            while( byteRead && !ferror(inputfile) ){
                byteWrite = fwrite(buffer, sizeof(char), byteRead, destFile);
                byteRead = fread(buffer, sizeof(char), buffercount, inputfile);
            }
            fclose(inputfile);

            fileLine = maxline - fileLine;
            while( fileLine >= 0 ){
                fwrite(&feed, sizeof(short), 1, destFile);
                fileLine--;
            }

            fseek(destFile, -((int)sizeof(short)), SEEK_CUR);
            fread(&two, sizeof(short), 1, destFile);
            if(two == feed){
                fseek(destFile, -((int)sizeof(short)), SEEK_CUR);
                fwrite(&empty, sizeof(short), 1, destFile);
            }else if( two != 0 ){
                fseek(destFile, 0, SEEK_END);
                fwrite(&empty, sizeof(short), 1, destFile);
            }
        }
    }
    free(buffer);
}

int lineCheck(char* buffer, int* len, int isLF)
{
    const short empty = 0;
    const short feed = 0x0a0d;
    short* two = NULL;
    char* one = buffer;
    int result = 0;

    while( (int)one < (int)(buffer + *len) ){
        two = (short*)one;
        result = *two;
        if(*two == feed || *two == empty){
            if(!isLF){
                *two = feed;
                *len = (int)one - (int)buffer + 2;
                return result == empty ? 4:2;
            }else{
                *two = empty;
                *len = (int)one - (int)buffer;
                return result == empty ? 3:1;
            }
        }
        one++;
    }

    return 0;
}

void fileAssemble(long* headRec, int fileNum, FILE* dest, FILE* src)
{
    const int bufferCount = 1024;
    int byteRead = 0;
    size_t byteWrite = 0;
    char* buffer = (char*)malloc( bufferCount );
    int index = 0;
    int len = 0;
    int loop = 0;
    int over = fileNum;

    do 
    {
        fseek(src, headRec[index], SEEK_SET);
        loop++;
        byteRead = fread(buffer, 1, bufferCount, src);

        while( byteRead && !ferror(src) ){
            int inner = byteRead;
            len = lineCheck(buffer, &inner, fileNum - loop);
            byteWrite = fwrite(buffer, sizeof(char), inner, dest);

            if( len != 0 ){
                if( len == 2 || len == 4){
                    headRec[index] = headRec[index] + inner;
                    if( len == 4 ) over--;
                }
                else{
                    headRec[index] = headRec[index] + inner + sizeof(short);
                    if( len == 3 ) over--;
                }
                index++;
                break;
            }
            byteRead = fread(buffer, sizeof(char), bufferCount, src);
        }
        if( loop == fileNum ){
            index = 0; loop = 0;
        }
        if(!over)break;
    } while ( byteRead != 0 );

    free(buffer);    
}

void fileMerge(char* resultName, int start, int end)
{
    FILE* result = fopen(resultName, "wb");
    FILE* temp = tmpfile();
    long* headRec = (long*)malloc( (end - start + 1) * sizeof(long) );
    memset( headRec, 0, (end - start + 1) * sizeof(long) );
    preCompile(headRec, temp, start, end);
    fileAssemble(headRec, end - start + 1, result, temp);
    fclose(temp);
    fclose(result);
    free(headRec);
}

int _tmain(int argc, _TCHAR* argv[])
{
    // 需要把 0000.csv - 0824.csv 存放在当前目录下的 datafile 目录里
    // 输出的 result.csv 文件在当前目录
    fileMerge("result.csv", 0, 284);
    return 0;
}
2015-05-07 21:17
快速回复:CSV合并的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.035843 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved