テキストファイルの文字コードを一括変換するアプリケーションをつくります。ダウンロードしたcsvファイルをExcelで開いたら文字化けしていたというときにも対応できます。
まずはデザイナで以下のようなものをつくります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.AllowDrop = true; } protected override void OnDragOver(DragEventArgs e) { if(e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.All; } base.OnDragOver(e); } protected override void OnDragDrop(DragEventArgs e) { if(e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); foreach(string path in files) ConvertFiles(path); } base.OnDragDrop(e); } bool ConvertFiles(string filePath) { Encoding encoding1 = null; if(radioButtonFromShiftJis.Checked) encoding1 = Encoding.Default; if(radioButtonFromUTF8.Checked) encoding1 = Encoding.UTF8; if(radioButtonFromUTF16LE.Checked) encoding1 = Encoding.Unicode; if(radioButtonFromUTF16BE.Checked) encoding1 = Encoding.BigEndianUnicode; if(radioButtonFromJIS.Checked) encoding1 = Encoding.GetEncoding("iso-2022-jp"); if(radioButtonFromEUC.Checked) encoding1 = Encoding.GetEncoding("euc-jp"); Encoding encoding2 = null; if(radioButtonToShiftJis.Checked) encoding2 = Encoding.Default; if(radioButtonToUTF8.Checked) encoding2 = Encoding.UTF8; if(radioButtonToUTF16LE.Checked) encoding2 = Encoding.Unicode; if(radioButtonToUTF16BE.Checked) encoding2 = Encoding.BigEndianUnicode; if(radioButtonToJIS.Checked) encoding2 = Encoding.GetEncoding("iso-2022-jp"); if(radioButtonToEUC.Checked) encoding2 = Encoding.GetEncoding("euc-jp"); StreamReader sr = new StreamReader(filePath, encoding1); string str = sr.ReadToEnd(); sr.Close(); string outFilePath = GetOutputPath(filePath); StreamWriter sw = new StreamWriter(outFilePath, false, encoding2); sw.Write(str); sw.Close(); return true; } string GetOutputPath(string filePath) { FileInfo fileInfo = new FileInfo(filePath); return GetOutputFolder(filePath) + "\\" + fileInfo.Name; } string GetOutputFolder(string filePath) { FileInfo fileInfo = new FileInfo(filePath); string outputFolderPath = fileInfo.DirectoryName + "\\output"; if(!Directory.Exists(outputFolderPath)) Directory.CreateDirectory(outputFolderPath); return outputFolderPath; } } |
ところで元のファイルの文字コードが分かっているのであればこれで充分使えるのですが、文字コードがわからない場合もあるかもしれません。そんなときでも指定した文字コードに変換するためには元のファイルの文字コードを推測する必要があります。
この場合はこれを使います。
実行ファイルと同じフォルダにnkf32.dllをコピーしておきます。nkf32.dllはここから入手できます。
ネットワーク用漢字コード変換フィルタ シフトJIS,EUC-JP,ISO-2022-JP,UTF-8,UTF-16
下記以外は対応できませんが、これだけあれば充分と思います。
Shift_JIS
EUC-JP
ISO-2022-JP
UTF-8
UTF-16LE
UTF-16BE
変換元に「不明」を追加しました。「不明」のときはnkfで調べます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
public partial class Form1 : Form { [System.Runtime.InteropServices.DllImport("nkf32.dll")] static extern int SetNkfOption(string optStr); [System.Runtime.InteropServices.DllImport("nkf32.dll")] unsafe static extern void NkfConvert(StringBuilder outStr, char* inStr); [System.Runtime.InteropServices.DllImport("nkf32.dll")] static extern int NkfGetKanjiCode(); public Encoding DetectEncoding(string path) { SetNkfOption("-gt"); byte[] bytes; using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { bytes = new byte[fs.Length]; fs.Read(bytes, 0, bytes.Length); } unsafe { fixed(byte* pbs = bytes) { StringBuilder strBldr = new StringBuilder(1); NkfConvert(strBldr, (char*)pbs); } } int nEnc = NkfGetKanjiCode(); const int SJIS = 0; const int EUC = 1; const int JIS = 2; const int UTF8 = 3; const int UTF16LE = 4; const int UTF16BE = 5; const int ASCII = 1001; if(nEnc == JIS) { nEnc = ASCII; // US-ASCII と仮定する for(int i = 0; i < bytes.Length; i++) { if(bytes[i] == 0x1b) { nEnc = JIS; break; } } } switch(nEnc) { case SJIS: return Encoding.GetEncoding("shift_jis"); case EUC: return Encoding.GetEncoding("euc-jp"); case JIS: return Encoding.GetEncoding("iso-2022-jp"); case UTF8: return Encoding.UTF8; case UTF16LE: return Encoding.GetEncoding("utf-16"); case UTF16BE: return Encoding.GetEncoding("utf-16BE"); case ASCII: return Encoding.ASCII; default: return null; } } bool ConvertFiles(string filePath) { Encoding encoding1 = null; if(radioButtonFromShiftJis.Checked) encoding1 = Encoding.Default; if(radioButtonFromUTF8.Checked) encoding1 = Encoding.UTF8; if(radioButtonFromUTF16LE.Checked) encoding1 = Encoding.Unicode; if(radioButtonFromUTF16BE.Checked) encoding1 = Encoding.BigEndianUnicode; if(radioButtonFromJIS.Checked) encoding1 = Encoding.GetEncoding("iso-2022-jp"); if(radioButtonFromEUC.Checked) encoding1 = Encoding.GetEncoding("euc-jp"); // 「不明」のとき if(radioButtonFromUnknown.Checked) encoding1 = DetectEncoding(filePath); Encoding encoding2 = null; if(radioButtonToShiftJis.Checked) encoding2 = Encoding.Default; if(radioButtonToUTF8.Checked) encoding2 = Encoding.UTF8; if(radioButtonToUTF16LE.Checked) encoding2 = Encoding.Unicode; if(radioButtonToUTF16BE.Checked) encoding2 = Encoding.BigEndianUnicode; if(radioButtonToJIS.Checked) encoding2 = Encoding.GetEncoding("iso-2022-jp"); if(radioButtonToEUC.Checked) encoding2 = Encoding.GetEncoding("euc-jp"); // Nkfでは判断できないときは変換しない if(encoding2 == null) return false; StreamReader sr = new StreamReader(filePath, encoding1); string str = sr.ReadToEnd(); sr.Close(); string outFilePath = GetOutputPath(filePath); StreamWriter sw = new StreamWriter(outFilePath, false, encoding2); sw.Write(str); sw.Close(); return true; } protected override void OnDragDrop(DragEventArgs e) { List<string> failures = new List<string>(); if(e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); foreach(string path in files) { bool ret = ConvertFiles(path); // 変換できなかった場合、そのファイルパスを記録する if(!ret) { failures.Add(path); } } } // 変換できなかったファイルパスをファイルとして出力する if(failures.Count>0) { DateTime dt = DateTime.Now; string name = "failures-" + dt.ToString("yyyy-MM-dd-HH-mm-ss") + ".txt"; string filePath = GetOutputFolder(failures[0]) + "\\" + name; StreamWriter sw = new StreamWriter(filePath); string str = "文字コードがわからなかったため、処理できませんでした。\n"; str += String.Join("\n", failures.ToArray()); sw.Write(str); sw.Close(); } base.OnDragDrop(e); } } |