【C#】制御文字を文字列から削除する
iPhoneなどのスマホで撮った画像や動画の撮影日時などには、日付文字列中に制御文字が含まれているため
//日時のプロパティは日付設定
DateTime dt;
//DateTimeに変換
if (DateTime.TryParse(shoot_date, out dt))
{
return dt.ToString("yyyyMMddHHmmss");
}
とやってもDateTime.TryParse関数で日付とみなされずfalseで帰ってきます。
なので関係ない文字列を除去する考えました。
文字列から数値と"/"と":"とスペースだけを取得する
欲しい文字以外は捨ててしまいます。ロジックは以下の通りです。
今回はこのロジックで対応しました。
StringBuilder sbDate = new StringBuilder();
//日付変更に失敗した場合、0-9, /, : spaceだけ抜き出す。
foreach (char c in shoot_date.ToCharArray())
{
if (Regex.IsMatch(c.ToString(), @"[0-9]|/|:|\s"))
{
sbDate.Append(c);
}
}
if (DateTime.TryParse(sbDate.ToString(), out dt))
{
return dt.ToString("yyyyMMddHHmmss");
}
正規表現で必要な文字(0-9、/、:、スペース)だけを抜き出しています。
replace関数で一気に置き換えてもいいですね。そうすれば1行で済みそうです。
iPhoneの画像の撮影日時には何の文字が入っているのか
最初は制御文字を除くLinQを使ったコードで不要な文字を取ってやればいいと思い、試してみましたがダメでした。
//制御文字を取り除く
shoot_date= new string(shoot_date.Where(c => !char.IsControl(c)).ToArray());
//DateTimeに変換
if (DateTime.TryParse(shoot_date, out dt))
{
//trueにならないのでここに入ってこない
return dt.ToString("yyyyMMddHHmmss");
}
というわけで調べてみました。
この画像はiPhone 5sで「2018/07/19 13:35」に取れたものです。
これを分解してみました。
文字 | ? | 2 | 0 | 1 | 8 | / | ? | 0 | 7 | / | ? | 1 | 9 | ? | ? | 1 | 3 | : | 3 | 5 | |
ASCII | 8206 | 50 | 48 | 49 | 56 | 57 | 8206 | 48 | 55 | 47 | 8206 | 49 | 57 | 32 | 8207 | 8206 | 49 | 51 | 58 | 51 | 53 |
この8206と8207を調べてみました。結果、
8206は左から文字を書き始める制御文字
8207は右から文字を書き始める制御文字
と出てきました。自信ががないので違う場合はご指摘頂ければと思います。
なんでこんなものが入っているかよくわかりませんがtryParse関数の邪魔をしています。
isContol関数で制御文字と判断されないのはASCIIコード(0~255)ではないからなのかなと思います。
ここまで読んで頂いてありがとうございます。