ここには非常に良い答えがいくつかありますが、Windows / Visual Studioに関していくつか追加できることがあると思います。Tisは、VS2015での私の経験に基づいています。Linuxでは、基本的に答えはstd::string
どこでもエンコードされたUTF-8を使用することです。Windows / VSではさらに複雑になります。これが理由です。Windowsは、char
sを使用して格納された文字列がロケールコードページを使用してエンコードされることを想定しています。これは、ほとんどの場合、場所に応じて、ASCII文字セットの後に128個の他の特殊文字が続きます。Windows APIを使用するときだけでなく、これらの文字列が標準のC ++と相互作用する他の3つの主要な場所があることを述べさせてください。これらは文字列リテラルであり、ファイル名をstd::cout
使用<<
してファイル名をに渡すと出力されますstd::fstream
。
私はプログラマーであり、言語の専門家ではないことをここで前に示します。USC2とUTF-16は同じではないことを感謝しますが、私の目的のために、それらは交換可能であるように十分に近く、ここではそれらをそのまま使用します。どのWindowsを使用しているのか実際にはわかりませんが、通常はどちらも知る必要はありません。私はこの回答でUCS2について述べましたので、この問題を知らない人を動揺させてしまった場合は事前に申し訳ありません。問題があった場合は変更させていただきます。
文字列リテラル
コードページで表現できる文字のみを含む文字列リテラルを入力すると、VSは、コードページに基づいて、文字エンコーディングあたり1バイトでファイルに保存します。コードページを変更したり、別のコードページを使用して別の開発者にソースを提供したりした場合、(テストされていませんが)文字は異なるものになると思います。別のコードページを使用してコンピューターでコードを実行する場合、文字も変更されるかどうかはわかりません。
コードページで表現できない文字列リテラルを入力すると、VSはファイルをUnicodeとして保存するように要求します。その後、ファイルはUTF-8としてエンコードされます。これは、すべての非ASCII文字(コードページにあるものを含む)が2バイト以上で表されることを意味します。つまり、ソースを他の人に渡した場合、ソースは同じに見えます。ただし、ソースをコンパイラに渡す前に、VSはUTF-8でエンコードされたテキストをコードページでエンコードされたテキストに変換し、コードページで欠落している文字はすべてに置き換えられ?
ます。
VSでUnicode文字列リテラルを正しく表すことを保証する唯一の方法は、文字列リテラルの前にL
ワイド文字列リテラルにすることです。この場合、VSはUTF-8でエンコードされたテキストをファイルからUCS2に変換します。次に、この文字列リテラルをstd::wstring
コンストラクタに渡すか、それをutf-8に変換してに配置する必要がありますstd::string
。または、Windows API関数を使用して、コードページを使用してエンコードし、それをに配置std::string
できますが、ワイド文字列リテラルを使用していない場合もあります。
std :: cout
使用してコンソールに出力するとき<<
だけ使用することができstd::string
ない、std::wstring
そしてテキストがロケールのコードページを使用してエンコードする必要があります。がある場合std::wstring
は、Windows API関数のいずれかを使用して変換する必要があり、コードページにない文字は置き換えられます?
(多分、文字を変更できるので、覚えていません)。
std :: fstreamファイル名
Windows OSはファイル名にUCS2 / UTF-16を使用するため、コードページが何であれ、任意のUnicode文字のファイルを作成できます。ただし、これは、コードページにない文字でファイルにアクセスまたは作成するには、を使用する必要があることを意味しますstd::wstring
。他に方法はありません。これはMicrosoft固有の拡張機能であるstd::fstream
ため、おそらく他のシステムではコンパイルできません。std :: stringを使用する場合、コードページに文字のみを含むファイル名のみを使用できます。
あなたのオプション
Linuxで作業しているだけなら、おそらくここまで来ていません。std::string
どこでもUTF-8を使用するだけです。
Windowsだけで作業している場合は、std::wstring
どこでもUCS2を使用してください。一部の純粋主義者は、UTF8を使用し、必要に応じて変換すると言うかもしれません。
あなたがクロスプラットフォームであるなら、それは率直に言うと混乱です。Windowsのあらゆる場所でUTF-8を使用する場合は、文字列リテラルとコンソールへの出力に十分注意する必要があります。そこの文字列は簡単に破損する可能性があります。std::wstring
Linuxのどこでも使用している場合は、ワイドバージョンのにアクセスできない可能性があるstd::fstream
ため、変換を行う必要がありますが、破損のリスクはありません。個人的には、これがより良いオプションだと思います。多くの人が反対するでしょうが、私は一人ではありません-それは、たとえばwxWidgetsがたどる経路です。
別のオプションは、LinuxとWindowsの場合とunicodestring
同様std::string
にtypedef std::wstring
であり、UNI()と呼ばれるマクロをWindowsでLの接頭辞付きにし、Linuxで何もない場合、次にコード
#include <fstream>
#include <string>
#include <iostream>
#include <Windows.h>
#ifdef _WIN32
typedef std::wstring unicodestring;
#define UNI(text) L ## text
std::string formatForConsole(const unicodestring &str)
{
std::string result;
//Call WideCharToMultiByte to do the conversion
return result;
}
#else
typedef std::string unicodestring;
#define UNI(text) text
std::string formatForConsole(const unicodestring &str)
{
return str;
}
#endif
int main()
{
unicodestring fileName(UNI("fileName"));
std::ofstream fout;
fout.open(fileName);
std::cout << formatForConsole(fileName) << std::endl;
return 0;
}
どちらのプラットフォームでも問題ないと思います。
答え
だからあなたの質問に答えるために
1)Windows用にプログラミングしている場合、Windowsで起こり得る破損の問題に対処したり#ifdefs
、違いを回避するためにプラットフォーム固有のコードを記述したりしない限り、常に、クロスプラットフォームの場合はおそらく常にLinuxはそれから決して。
2)はい。さらにLinuxでは、すべてのUnicodeにも使用できます。Windowsでは、UTF-8を使用して手動でエンコードすることを選択した場合にのみ、すべてのUnicodeに使用できます。ただし、Windows APIと標準C ++クラスはstd::string
、がロケールコードページを使用してエンコードされることを想定しています。これには、すべてのASCIIと、コンピュータが使用するように設定されているコードページに応じて変わる128文字が含まれます。
3)私はそう信じていますが、そうでない場合は、wchar_t
代わりに使用する 'std :: basic_string'の単純なtypedef ですchar
4)ワイド文字は、1バイトの標準char
タイプよりも大きい文字タイプです。Windowsでは2バイト、Linuxでは4バイトです。