1. 程式人生 > >在Mac系統下Excel轉csv檔案中文亂碼問題解決

在Mac系統下Excel轉csv檔案中文亂碼問題解決

匯出方式

問題的原因是編碼方式不同造成的,解決問題需要藉助一個工具

Numbers,

下載地址: http://soft.macx.cn/5144.htm

安裝完成後用Numbers開啟Excel文件;

在最上方點選:共享->匯出

出現

在這裡選擇csv,編碼格式一定要選擇UTF-8,然後點選下一步匯出;

解析方式

在Mac下匯出的csv是以逗號分割的;

下面是封裝的解析類

CSVParse.h

#include <stdio.h>
#include <vector>

using namespace std;

class CSVParse {
    
public:
    int row;
    int col;
    
public:
    //呼叫解析
    CSVParse(const char* fileName, string sep = ",");
    ~CSVParse();
    
private:
    /**
     *  分隔符
     */
    string m_fieldsep;
    
    /**
     *  容器,儲存從CSV裡讀取出來的資料
     */
    vector<vector<string> > m_data;
    
private:
    void split(vector<string>& field,string line);
    int advplain(const string& line, string& fld, int);
    int advquoted(const string& line, string& fld, int);
    
    /**
     *  刪除替換特定字元
     */
    void deleteChar(std::string* str);
    
public:
    /**
     *  開啟檔案
     */
    bool openFile(const char* fileName);
    
    /**
     *  取資料
     */
    const char* getData(int m,int n);
};

CSVParse.cpp
#include "cocos2d.h"
#include "CSVParse.h"

CSVParse::CSVParse(const char* fileName, string sep)
:m_fieldsep(sep)
{
    openFile(fileName);
}

CSVParse::~CSVParse()
{
    for (int i=0; i<m_data.size(); i++) {
        m_data[i].clear();
    }
    m_data.clear();
}

void CSVParse::split(vector<string>& field,string line)
{
    string fld;
    int i, j;
    
    if (line.length() == 0)
        return ;
    i = 0;
    
    do {
        if (i < line.length() && line[i] == '"')
            j = advquoted(line, fld, ++i);
        else
            j = advplain(line, fld, i);
        
        field.push_back(fld);
        i = j + 1;
    } while (j < line.length());
    
}

int CSVParse::advquoted(const string& s, string& fld, int i)
{
    int j;
    
    fld = "";
    for (j = i; j < s.length(); j++)
    {
        if (s[j] == '"' && s[++j] != '"')
        {
            int k = s.find_first_of(m_fieldsep, j);
            if (k > s.length())
                k = s.length();
            for (k -= j; k-- > 0; )
                fld += s[j++];
            break;
        }
        fld += s[j];
    }
    return j;
}

int CSVParse::advplain(const string& s, string& fld, int i)
{
    int j;
    
    j = s.find_first_of(m_fieldsep, i);
    if (j > s.length()) 
        j = s.length();
    fld = string(s, i, j-i);
    return j;
}


const char* CSVParse::getData(int m,int n)
{
    if ( m<0 || m>=m_data.size() || n<0 || n>=m_data[m].size() ) {
        return "";
    }
    
    //printf("%d,%d,%s\n", m, n, m_data[m][n].c_str());
    
    return m_data[m][n].c_str();
}

bool CSVParse::openFile(const char* fileName)
{
    //獲取全路徑
    string pathKey = cocos2d::CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(fileName);
    
    //開啟檔案
    //    size_t size = 0;
    FILE *fp = fopen(pathKey.c_str(), "r");
    if( !fp ) {
        CCLOG("開啟檔案%s失敗", pathKey.c_str());
        return false;
    }
    
    //獲取檔案位元組數
    //    fseek(fp, 0, SEEK_END);
    //    size = ftell(fp);
    //    fseek(fp, 0, SEEK_SET);
    
    //讀取內容
    //    unsigned char* out = (unsigned char*)malloc(size);
    //    size_t read = fread(out, 1, size, fp);
    //    if( read != size ) {
    //        CCLOG("讀取檔案%s失敗", pathKey.c_str());
    //        free(out);
    //        *out = NULL;
    //        return false;
    //    }
    
    char tmpChar[2048] = {0};
    string s;
    
    //去掉\r
    int lineIndex = 0;
    
    //讀取第一行
    fgets(tmpChar, 2048, fp);
    while( strlen(tmpChar) > 0 )
    {
        s = tmpChar;
        //printf("%d = %s", lineIndex, tmpChar);
        
        //刪除和替換掉多餘字元
        deleteChar(&s);
        
        //拆分掉文字
        std::vector<string> field;
        split(field, s);
        
        //第一行和第一列是無用資料,所以不存.
        if(lineIndex > 0){
            field.erase(field.begin());
            m_data.push_back(field);
        }
        lineIndex++;
        
        //讀取下一行
        tmpChar[0] = '\0';
        fgets(tmpChar, 2048, fp);
    }
    
    row = m_data.size();
    col = m_data[0].size();
    
    //測試,輸出內容
//    for (int i=0; i<m_data.size(); i++) {
//        for (int k=0; k<m_data[i].size(); k++) {
//            CCLOG("--------->%s",getData(i, k));
//        }
//    }
    
    fclose(fp);
    
    return true;
}


void CSVParse::deleteChar(std::string* str){
    string::iterator it;
    int index = 0;
    for (; index < str->size(); )
    {
        it = str->begin()+index;
        if ( *it == '\r' || *it == '\n' )
        {
            str->erase(it);
        } 
        else{
            index++;
        }
    }    
}


解析類的用法

langFile為要解析的檔名

    CSVParse* csv = newCSVParse(langFile);

得到CSVParse物件後可以呼叫

const char* getData(int m,int n);

傳入行和列可以得到想要的資料

程式碼下載:

http://download.csdn.net/detail/dingkun520wy/5263136