CSV 文件的读写练习

#include <stdafx.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <atlstr.h>
#include <string> // for string and wstring
using namespace std;

#define MAX_ASSIGN_ITEMS	4
#define MAX_FAXDESC		254
#define ABECFG_ENABLE_CJK_INPUT // 能够处理 中日韩文


#pragma region Write-CsvFile

// 初始化写入CSV文件的数据(在这里Demo 就随便写了,实际中一般从其他地方得到)
CString strTextArray[][5] = {
	(_T("2")), _T("111"), (_T("424")), _T("dgdfg"), _T("dgdfg"),
	(_T("3")), _T("111"), (_T("2")), _T("111"), _T("dgdfg"),
	(_T("4")), _T("111"), (_T("2")), _T("111"), _T("dgdfg"),
	(_T("5")), _T("111"), (_T("2")), _T("3553"), _T("dgdfg"),
	(_T("6")), _T("111"), (_T("2")), _T("111"), _T("dgdfg"),
};

BOOL GetListSeparator(char szSeparator[5])
{
	TCHAR szTemp[5];

	if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, szTemp, 5) > 0)
	{
#ifdef _UNICODE
		WideCharToMultiByte(CP_ACP, 0, (WCHAR*)szTemp, -1,
			szSeparator, 5, NULL, NULL );
#else
		strcpy_s(szSeparator, 5, szTemp);
#endif
	}
	else
	{
		strcpy(szSeparator, ",");
	}

	return TRUE;
}


bool WriteCsvFileContent(ofstream *pStream)
{
	if (pStream == NULL)
	{
		return FALSE;
	}

	//char comma = ',';
	char szSeparator[5];

	GetListSeparator(szSeparator);

	char splitchar=szSeparator[0];	

	char szText[MAX_FAXDESC];

	std::wostringstream oss;

	TCHAR szTemp[5];
	wstring strSplitW;
	if(GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, szTemp, 5)>0)
	{
		strSplitW=szTemp;
	}
	else
	{
		strSplitW=L",";
	}

	strSplitW=L"\t";

	for (int i = 0; i < sizeof(strTextArray)/sizeof(strTextArray[0]); ++i)
	{

		for (int j = 0; j < sizeof(strTextArray[0])/sizeof(strTextArray[0][0]); ++j)
		{
			CString strText = strTextArray[i][j];

			oss.str(L"");
			oss<<strText.GetBuffer();
			strText.ReleaseBuffer();
			std::wstring wstr=oss.str().c_str();


			//#if defined(CM215F) || defined(CM215FW) || defined(FX_M218FW) || defined(FX_M215FW)
#if defined(ABECFG_ENABLE_CJK_INPUT)
			WideCharToMultiByte(/*932*/CP_UTF8, 0, strText.GetBuffer(), -1, szText, MAX_FAXDESC, NULL, NULL); // Enforce Japanese Codepage
			strText.ReleaseBuffer();
#else
#ifdef _UNICODE
			WideCharToMultiByte(CP_ACP, 0, strText.GetBuffer(), -1, szText, MAX_FAXDESC, NULL, NULL);
			strText.ReleaseBuffer();
#else
			strcpy(szText, strText);
#endif
#endif

			if (strlen(szText) > 0)
			{
				//pStream->write(szText, strlen(szText));
				pStream->write((char*)oss.str().c_str(),oss.str().length()*sizeof(wchar_t));
			}
			else
			{
				//pStream->write("", 1);
			}

			pStream->write((char*)strSplitW.c_str(),sizeof(wchar_t)*strSplitW.length());
		}

		// 写完一行,进行回车换行
		pStream->write((char*)L"\r\n",4);
		pStream->flush();
	}

	pStream->write((char*)L"\r\n",4); 

	pStream->flush();

	return TRUE;

}

// 写 CSV 文件
bool WriteCsvFile(CString _strDstPath)
{
	ofstream file;
	file.open(_strDstPath,std::ios::out|std::ios::binary);
	if (file.fail())
	{
		return false;
	}

	// 写CSV 文件头
	char bom[2]={0xFF,0xFE};
	file.write(bom,2);

	WriteCsvFileContent(&file);


	// 注意这行别忘了,如果写入的行数为0时(在这里你可以注释掉即文件内容为空),
	// 不加这句用EXCEL 打开会出现有乱码的数据显示
	// "\r\n" 也相当于文件结束标记(行结束标记)
	// By Ben 2014-10-14 11:55:16
	file.write((char*)L"\r\n",4);

	file.close();

	return true;
}
#pragma endregion Write-CsvFile


/
/

#pragma region Read_CsvFile

BOOL DecodeLineString(wstring str, BOOL bWideCharToMultiByte, char **ppData, int &nDataSize)
{
	if (str.empty() || ppData == NULL)
	{
		return FALSE;
	}
	*ppData = NULL;

	int linepos=0;
	bool inquotes=false;
	int linemax=str.length();
	wchar_t c;
	int nDstDataSize=linemax+2;

	wchar_t* pDstData = new wchar_t[nDstDataSize];
	if (pDstData == NULL)
	{
		return FALSE;
	}
	ZeroMemory(pDstData,sizeof(wchar_t)*nDstDataSize);

	wchar_t szSeparator[5];
	ZeroMemory(&szSeparator,sizeof(szSeparator));

	int nSepLen;

	//GetListSeparator(szSeparator);
	//nSepLen = strlen(szSeparator);
	//char splitchar=szSeparator[0];
	wchar_t szTemp[5];
	wstring strSplitW;
	if(GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SLIST, szTemp, 5)>0)
	{
		strSplitW=szTemp;
	}
	else
	{
		strSplitW=L",";
	}
	//wchar_t splitchar=szTemp[0];
	wchar_t splitchar=L'\t';


	nDataSize=0;
	while(str[linepos]!=0 && linepos < linemax)
	{
		c = str[linepos];

		// Fix 43560
		if (!inquotes && c==L'"')
		{
			if(linepos==0)
			{
				//beginquotechar
				inquotes=true;
			}
			else if(str[linepos-1]==splitchar)
			{
				//beginquotechar
				inquotes=true;
			}
			else
			{
				pDstData[nDataSize]=c;
				nDataSize++;
			}
			// End Fix 43560  //The (") and (,) are specified char in the csv file, and the csv parse function is not good when the strings has the specfied chars.
		}
		else if (inquotes && c==L'"')
		{
			//quotechar
			if ( (linepos+1 <linemax) && (str[linepos+1]==_T('"')) )
			{
				//encountered 2 double quotes in a row (resolves to 1 double quote)
				pDstData[nDataSize]=c;
				nDataSize++;
				linepos++;
			}
			else
			{
				//endquotechar
				inquotes=false;
			}
		}
		else if (!inquotes && c==splitchar)
		{
			//end of field
			pDstData[nDataSize]=L'\0';
			nDataSize++;
		}
		else if (!inquotes && (c==L'\r') )
		{
		}
		else if (!inquotes && (c==L'\n') )
		{
			//record.push_back( curstring );
			pDstData[nDataSize]=L'\0';
			nDataSize++;
			break;
		}
		else if( c==0xFEFF)
		{
		}
		else
		{
			//curstring.push_back(c);
			pDstData[nDataSize]=c;
			nDataSize++;
		}
		linepos++;
	}

	*ppData=(char*)pDstData;
	nDataSize=(nDataSize+1)*sizeof(wchar_t);	// Fix 43163
	return TRUE;

}

BOOL DecodeLineString(string str, BOOL bWideCharToMultiByte, char **ppData, int &nDataSize)
{
	if (str.empty() || ppData == NULL)
	{
		return FALSE;
	}
	*ppData = NULL;

	int linepos=0;
	bool inquotes=false;
	int linemax=str.length();
	char c;
	int nDstDataSize=linemax+2;

	char* pDstData = new char[nDstDataSize];
	if (pDstData == NULL)
	{
		return FALSE;
	}
	ZeroMemory(pDstData,sizeof(char)*nDstDataSize);

	char szSeparator[5];
	ZeroMemory(&szSeparator,sizeof(szSeparator));

	int nSepLen;

	GetListSeparator(szSeparator);
	nSepLen = strlen(szSeparator);
	char splitchar=szSeparator[0];


	nDataSize=0;
	while(str[linepos]!=0 && linepos < linemax)
	{
		c = str[linepos];

		// Fix 43560
		if (!inquotes && c=='"')
		{
			if(linepos==0)
			{
				//beginquotechar
				inquotes=true;
			}
			else if(str[linepos-1]==splitchar)
			{
				//beginquotechar
				inquotes=true;
			}
			else
			{
				pDstData[nDataSize]=c;
				nDataSize++;
			}
			// End Fix 43560
		}
		else if (inquotes && c=='"')
		{
			//quotechar
			if ( (linepos+1 <linemax) && (str[linepos+1]==_T('"')) )
			{
				//encountered 2 double quotes in a row (resolves to 1 double quote)
				pDstData[nDataSize]=c;
				nDataSize++;
				linepos++;
			}
			else
			{
				//endquotechar
				inquotes=false;
			}
		}
		else if (!inquotes && c==splitchar)
		{
			//end of field
			pDstData[nDataSize]='\0';
			nDataSize++;
		}
		else if (!inquotes && (c=='\r' || c=='\n') )
		{
			//record.push_back( curstring );
			pDstData[nDataSize]='\0';
			nDataSize++;
			break;
		}
		else
		{
			//curstring.push_back(c);
			pDstData[nDataSize]=c;
			nDataSize++;
		}
		linepos++;
	}

	*ppData=pDstData;
	nDataSize=nDataSize+1;	// Fix 43163
	return TRUE;
}


ifstream& getlineW(ifstream& pStream, wstring& str)
{
	wchar_t wch;
	str.assign(L"");

	while(!pStream.eof())
	{
		pStream.read((char*)&wch,sizeof(wchar_t));
		if(wch==L'\n')
		{
			break;
		}
		else if(wch==0xFEFF)
		{
			continue;
		}
		str.push_back(wch);

	}
	return pStream;
}

ifstream& getlineA(ifstream& pStream, string& str)
{
	return (ifstream&)getline(pStream,str);

	char ch;
	str.assign("");

	while(!pStream.eof())
	{
		pStream.read((char*)&ch,sizeof(char));
		if(ch=='\n')
		{
			break;
		}
		str.push_back(ch);

	}
	return pStream;
}


// 读取文件文件的第一行
HRESULT ReadCsvFileFirstLine(CString _strDstPath, char **ppData, int &nDataSize, BOOL& bUnicode)
{
	*ppData = NULL;
	nDataSize = 0;

	ifstream file(_strDstPath,ios::binary);
	if (file.bad())
	{
		return E_FAIL;
	}

	string str;

	// Check if it is unicode file
	if (!file.eof())
	{
	// 读取 CSV 文件的BOM (头部两个字节)
		char szText[2] = {0};
		file.read(szText, 2);
		if (!file.fail())
		{
			bUnicode = (0xFF == (BYTE)szText[0] && 0xFE == (BYTE)szText[1]);
		}

		if (!bUnicode)
		{
			// reset file position
			file.seekg(0, ios_base::beg);
		}
	}

#if 1
	wstring lineW;
	string lineA;
	if(bUnicode)
	{
		while(!file.eof())
		{
			getlineW(file, lineW);
			if (!lineW.empty())
			{
				if (DecodeLineString(lineW, FALSE, ppData, nDataSize))
				{
					file.close();
					return S_OK;
				}
			}
		}
	}
	else
	{
		while(!file.eof())
		{
			getlineA(file, lineA);
			if (!lineA.empty())
			{
				if (DecodeLineString(lineA, FALSE, ppData, nDataSize))
				{
					file.close();
					return S_OK;
				}
			}
		}
	}

#else
	while(!file.eof())
	{
		getline(file, str);
		if (!str.empty())
		{
			if (DecodeLineString(str, FALSE, ppData, nDataSize))
			{
				file.close();
				return S_OK;
			}
		}
	}
#endif
	file.close();

	return E_FAIL;
}


// 显示CSV 文件的第一行内容
void ShowCsvFirstLine(CString& _strDstPath)
{
	BOOL bUnicode = FALSE;

	char *pData = NULL;
	int nDataSize = 0;

	if (S_OK == ReadCsvFileFirstLine(_strDstPath, &pData, nDataSize, bUnicode))
	{
		int offset = 0;

		CString strText;

		//#if defined(CM215F) || defined(CM215FW) || defined(FX_M218FW) || defined(FX_M215FW)
#if defined(ABECFG_ENABLE_CJK_INPUT)
		WCHAR wszStr[254]={0};
#endif
		while (offset < nDataSize)
		{
			if (bUnicode)
			{
				strText = (WCHAR*)(pData + offset);

				offset += (wcslen((WCHAR*)(pData + offset)) + 1) * sizeof(WCHAR);
			}
			else
			{
				//#if defined(CM215F) || defined(CM215FW) || defined(FX_M218FW) || defined(FX_M215FW)
#if defined(ABECFG_ENABLE_CJK_INPUT)
				memset(wszStr,00,sizeof(WCHAR)*254);
				MultiByteToWideChar(/*932*/CP_UTF8,0,(pData + offset),-1,wszStr,254); // Japanese Codepage
				strText=wszStr;
#else
				strText = (pData + offset);
#endif

				offset += (1 + strlen(pData + offset)) * sizeof(char);
			}

			wcout << strText.GetString() << " ";

		}

		wcout << endl << endl << endl;

	}

	if (pData != NULL)
	{
		delete []pData;
		pData = NULL;
	}
}

#pragma endregion Read_CsvFile



//#define WRITE_CSV  // 注意:这个定义,在第一次运行时打开,让它生成CSV文件,然后再注释掉看读取的结果
void main()
{
	CString strDstPath(_T("d:\\ben.csv"));

#ifdef WRITE_CSV
	WriteCsvFile(strDstPath);
#else
 
	ShowCsvFirstLine(strDstPath);

#endif
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值