C++ファイル読み書き

4246 ワード

最近、異なるフォーマットのファイルを読み取ることに遭遇しました.C++はunicodeをサポートしていないので、読むのが面倒です.このブログでは、異なる符号化フォーマットの違いを詳しく紹介しています.
一般的なタイプは、ANSI、utf-8 bomフォーマットなし、utf-8、usc 2 little end、usc 2 big endです.ここでutf 8はunicodeの最も一般的な実装方法である.Windowsのワイド文字列サポート:USC-2 Little End.BOM: Byte Order Mark.UTF-8 BOMはUTF-8署名とも呼ばれていますが、実際にはUTF-8のBOMはUFT-8には役に立たず、UTF-16、UTF-32を支援するために付けられたBOMです.BOM署名とは、現在のファイルがどのような符号化を採用しているかをエディタに伝えることを意味します.エディタで識別しやすいですが、BOMはエディタに表示されませんが、coutで直接出力すると文字化けが発生します.Notepad++で開くと黒い0 xffなどのバイトが表示されます.そのため、3バイトをスキップします.
Windowsの下のwchar_t読み出しはUCS 2 Little Endであり、一般的にUnicode符号化とは、UCS-2 little endianフォーマット符号化方式、すなわち文字を直接2バイトで格納するUnicode符号を指す.WindowsのC++には3種類の文字タイプがあります.char,wchar_t,TCHAR,最もよく知られているcharは単バイト文字で,ANSI符号化に適している.wchar_tは2バイトの広い文字タイプであり、unicode符号化に適している.TCHARは1つのマクロで、ANSIの悪い境の下でcharと定義して、unicodeの悪い境の下でwchar_と定義しますt.
ファイル形式:
テキストファイルのヘッダー(Bom)でファイルフォーマットを識別します.
ANSIファイルのファイルヘッダは空で、処理する必要はありません.
UNICodeファイルのファイルヘッダは0 xFF、0 xFEの合計2バイトであり、読み込み時に2バイトオフセットしてから読み取る必要がある.
UTF-8ファイルのファイルヘッダは0 xEF、0 xBB、0 xBFの合計3バイトであり、読み取り時に3バイトオフセットしてから読み取る必要がある.
#include 
#include 
#include 
using namespace std;

enum FileType
{
	ansi = 0,
	unicode,
	utf8
};

FileType GetFileType(ifstream& infile)
{
	
	FileType type = ansi;
	if (!infile) {
		return ansi;
	}
	if (infile.good()){
		char head[3];
		infile.read(head,sizeof head);

		//utf-8 bom            
		cout<

(注:この方法ではutf-8のbomなしフォーマットは認識できません.)
C++入出力ストリームを使用して、異なる形式のファイルを作成します.
通常のファイルを直接作成すると、ファイル形式はANSIになります.
バイナリファイルを作成する場合:最初の3バイトを設定してファイルフォーマットを設定できます(設定しない場合:utf-8 bomフォーマットなし).
//-----------------------------------------------
//         
//-----------------------------------------------
void CreateFileTest(FileType type,const char* filename)
{
	ofstream out;
	out.open(filename,ios::binary);
	if (!out) {
		return;
	}
	char head[3];
	if (type == utf8) { //utf8 bom
		head[0] = 0xef;
		head[1] = 0xbb;
		head[2] = 0xbf;
		out.write(head,sizeof(head));
		out<

異なる文字フォーマット間の変換:
windowsでhのWideCharToMultiByteとMultiByteToWideChar関数.使用CP_ACPコードページはANSIとUnicodeの間の変換を実現し、CP_を使用する.UTF 8コードページでは、UTF-8とUnicodeの変換が実現されます.
Windowsコンソールでは、coutでANSI文字しか出力できず、wcoutではUCS 2(unicode)文字しか出力できないことが実験で分かった.utf 8はコンソールに直接出力する方法がしばらく見つからず、バイナリで直接ファイルに書き込むことでutf 8のbomなしフォーマットに保存するしかなかった(3バイトヘッダを自分で追加して、普通のutf 8フォーマットにすることもできる).
ANIS文字とutf-8はmultiBytes、unicode文字はワイド文字列(windowsではucs 2 little end).
//-----------------------------------------------
//C++           
//-----------------------------------------------
#include 
#include 

//ANSI     unicode
bool ANSIToUnicode(const char* inStr,wchar_t* outDest,int MaxLen)
{
	int len = 0;
	if (MaxLen <= 0) {
		return false;
	}
	len = ::MultiByteToWideChar(CP_ACP,0,inStr,-1,outDest,MaxLen);
	if (len < 0) {
		len = 0;
	}
	if (len < MaxLen) {
		outDest[len] = 0;
	} else {
		outDest[MaxLen - 1] = 0;
		return false;//  
	}
	return true;
}

//unicode  utf-8 bom  
bool UnicodeToUtf8(const wchar_t* inDest,char* outStr,int MaxLen)
{
	
	int len = ::WideCharToMultiByte(CP_UTF8,0,inDest,-1,NULL,0,NULL,NULL);//    
	if (len > MaxLen) {
		return false;
	}
	WideCharToMultiByte(CP_UTF8,0,inDest,-1,outStr,len,NULL,NULL);
	outStr[len - 1] = 0;
	return true;
}

//utf-8   unicode
bool Utf8ToUnicode(const char* inStr,wchar_t* outDest,int MaxLen)
{
	int len = ::MultiByteToWideChar(CP_UTF8,0,inStr,-1,NULL,NULL);
	if (len > MaxLen) {
		return false;
	}
	::MultiByteToWideChar(CP_UTF8,0,inStr,-1,outDest,len);
	outDest[len - 1] = 0;
	return true;
}

bool UnicodeToANSI(const wchar_t* inStr,char* outDest,int MAxLen)
{
	int len = ::WideCharToMultiByte(CP_ACP,0,inStr,-1,NULL,0,NULL,NULL);
	if (len > MAxLen) {
		return false;
	}
	::WideCharToMultiByte(CP_ACP,0,inStr,-1,outDest,len,NULL,NULL);
	outDest[len - 1] = 0;
	return true;
}

void testANSIUNICODE()
{
	// ansi   unicode
	locale::global(locale("chs"));
	wchar_t unicodebuf[1024];
	memset(unicodebuf,0,sizeof(unicodebuf));
	char* ansibuf = "       ,              ";
	cout<

C++UTF-8ファイルの読み書き方法:
http://henry8088.iteye.com/blog/780743