唯一の実用的な方法は、コードページごとにある種の「マスク」を手動で定義することだと思います。各コードページで有効と見なされるすべての文字値を定義する構造。
次に、このマスクに含まれていない文字値がページに含まれているかどうかを確認できます。
マスクの作成には、かなりの手作業が必要になります。すべての文字を含むページを作成し、適切なコードページを使用してそれを表示してから、どれが「うまく」レンダリングされていないかを確認します。これはコードページごとに1回限りのアクティビティなので、おそらく努力する価値があります。
もちろん、コードページを解析する方法があれば、このマスクを自動的に生成できます...うーん...少し戻ってください。
このコードフラグメントを試してください。既知の各コードページに対して32〜255文字をテストします。
StringBuilder source = new StringBuilder();
for (int ix = 0; ix < 224; ix++)
{
source.Append((char)(ix + 32));
}
EncodingInfo[] encs = Encoding.GetEncodings();
foreach (var encInfo in encs)
{
System.Console.WriteLine(encInfo.DisplayName);
Encoding enc = Encoding.GetEncoding(encInfo.CodePage);
var result = enc.GetBytes(source.ToString().ToCharArray());
for (int ix = 0; ix < 224; ix++)
{
if (result[ix] == 63 && source[ix] != 63)
{
// Code page translated character to '?'
System.Console.Write("{0:d}", source[ix]);
}
}
System.Console.WriteLine();
}
デバッガーを見て回っていたところ、「?」に気づきました。ソース文字がコードページに含まれていない場合、フォールバック文字として使用されます。'?'をチェックすることによって (そして、そもそも「?」ではなかったことを確認して)、コードはコードページがそれを処理できなかったと想定します。
DBCSコードページにはもう少し注意が必要かもしれませんが、私は調べていません。しかし、これを出発点として試してください。
前に説明したように、このようなコードを使用して最初の「マスク」を作成し、次に、見栄えの良いものとそうでないものに基づいてそのマスクを手動で調整します。