「NTS」を利用して、.shpファイル(属性がSJIS)を読み込むと文字化けが発生しました。
shpファイルのルールでは、.cpgファイルに文字コード指定すると、その文字コードで、
.dbfファイルが読み込まれるはずですが認識されていないようでした。
※以下、対策前のQGISでの属性確認
1.原因分析1
NTSでは、.dbfファイルを読み込む前に、ヘッダ情報を読み込んでいます。
その際、cpgファイルがあれば、cpgファイルの文字コードを利用するはずです。
ですが、デバッグしてみると、文字コードを取得する、以下DbaseFileHeaderクラス
のメソッドで、cpgファイルを読み込む前に、Encoding.UTF8を返していました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private static Encoding DetectEncodingFromMark(byte lcid, string cpgFileName) { Encoding enc; if (LdidToEncoding.TryGetValue(lcid, out enc)) return enc; enc = Encoding.UTF8; if (String.IsNullOrEmpty(cpgFileName)) return enc; cpgFileName = Path.ChangeExtension(cpgFileName, "cpg"); if (!File.Exists(cpgFileName)) cpgFileName = Path.ChangeExtension(cpgFileName, "cst"); if (!File.Exists(cpgFileName)) return enc; string encodingText = File.ReadAllText(cpgFileName).Trim(); try { return Encoding.GetEncoding(encodingText); } catch { } return enc; } |
2.対策1
DetectEncodingFromMark()メソッドでは、デフォルトではUTF8を返しているので、
以下のようにデフォルトの文字コードをSJISに設定すると、SJIS返却されます。
1 2 3 4 5 6 7 8 9 |
static DbaseFileHeader() { … // Add ANSI values 3 and 0x57 as system's default encoding, and 0 which means no encoding. AddLdidEncodingPair(0, Encoding.GetEncoding(932)); //AddLdidEncodingPair(0, Encoding.UTF8); AddLdidEncodingPair(0x03, Encoding.Default); AddLdidEncodingPair(0x57, Encoding.UTF8); } |
3.対策2
上記対策では、cpgファイルが無視されるので、
以下のように、デフォルト値の返却をコメント化すればcpgファイルの値が返却されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
private static Encoding DetectEncodingFromMark(byte lcid, string cpgFileName) { Encoding enc; if (LdidToEncoding.TryGetValue(lcid, out enc)) // return enc; enc = Encoding.UTF8; if (String.IsNullOrEmpty(cpgFileName)) return enc; cpgFileName = Path.ChangeExtension(cpgFileName, "cpg"); if (!File.Exists(cpgFileName)) cpgFileName = Path.ChangeExtension(cpgFileName, "cst"); if (!File.Exists(cpgFileName)) return enc; string encodingText = File.ReadAllText(cpgFileName).Trim(); try { return Encoding.GetEncoding(encodingText); } catch { } return enc; } |
※以下、対策後のQGISでの属性確認