C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: リストビューの並びをシフトJIS順にしたい


(過去ログ 164 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■94871 / inTopicNo.1)  リストビューの並びをシフトJIS順にしたい
  
□投稿者/ Tom (25回)-(2020/05/29(Fri) 07:36:25)

分類:[C#] 

リストビューに全角文字を表示しているのですが、並びがUTF8になっているようです。
これをシフトJISの並びにしたいのですが、どこで設定すればよいのでしょうか?

 現在の並び   希望の並び
   世       亜
   亜       世

賢者の方、お知恵をお貸しくださいませんでしょうか?

引用返信 編集キー/
■94873 / inTopicNo.2)  Re[1]: リストビューの並びをシフトJIS順にしたい
□投稿者/ KOZ (122回)-(2020/05/29(Fri) 09:33:48)
No94871 (Tom さん) に返信
>  現在の並び   希望の並び
>    世       亜
>    亜       世

日本語 Windows だと希望の並びになると思うんですが、カルチャを変更していないですか?
引用返信 編集キー/
■94874 / inTopicNo.3)  Re[1]: リストビューの並びをシフトJIS順にしたい
□投稿者/ 魔界の仮面弁士 (2731回)-(2020/05/29(Fri) 09:33:55)
No94871 (Tom さん) に返信
> リストビューに全角文字を表示しているのですが、並びがUTF8になっているようです。

ja-JP カルチャでのテキスト比較や、UTF-16 でのバイナリ比較でも無く、
UTF-8 出の並びだったのですね? (自分は確認していません)
https://dobon.net/vb/dotnet/string/stringequals.html#compareinfo


ちなみに Explorer だと自然ソートが採用されていたはずです。
そのため、OS によって並びが多少変わってくるという…。
https://qiita.com/tomochan154/items/1a3048f2cd9755233b4f
https://blog.ver001.com/kansuji/



> これをシフトJISの並びにしたいのですが、どこで設定すればよいのでしょうか?

ListView でカスタムソートを行うには、こんな感じでできるはず。
https://dobon.net/vb/dotnet/control/lvitemsort.html

System.Text.Encoding.GetEncoding(932).GetBytes でテキストをバイナリ化してから
比較すれば良いとは思いますが、「Shift_JIS の文字集合に無い文字」が
含まれていた場合にどう扱うのかは、あらかじめ考えておく必要があるでしょう。
引用返信 編集キー/
■94885 / inTopicNo.4)  Re[2]: リストビューの並びをシフトJIS順にしたい
□投稿者/ Tom (26回)-(2020/05/30(Sat) 07:01:52)
KOZ さま
魔界の仮面弁士 さま
アドバイスありがとうございます。

>日本語 Windows だと希望の並びになると思うんですが、カルチャを変更していないですか?
Windowsエクスプローラの表示順をみるとわかるのですが、カルチャを使用すると「同じ音の文字をまずまとめる」方法をとっています。
こんな感じになります。 
 ア
 あ
 イ
 い
シフトJISの並びにしたい以上、もうこんなのは論外なので、ソートの判定ではstring.CompareOrdinal()を使用していました。
これだとカルチャは使用せずに純粋にコード順で判定してくれるのですが、コード順の文字並び自体がシフトJISとUTFでは
違っていたため困っております。


>a-JP カルチャでのテキスト比較や、UTF-16 でのバイナリ比較でも無く、UTF-8 出の並びだったのですね? (自分は確認していません)
もしかしたらUTF8ではないのかもしれません。
が、シフトJISではないことは確実でした。
コード値でみると、
   シフトJIS  UTF
 亜  889F U+4E9C
 世  90A2 U+4E16
と若い値がシフトJISとUTFとで逆転しています。


>ListView でカスタムソートを行うには、こんな感じでできるはず。
カスタムソート自体は既に実装済みで問題なく動作しているのですが、肝心の比較結果が上記の問題で逆転してしまっており、
期待順と違ってしまっているのです。


>System.Text.Encoding.GetEncoding(932).GetBytes でテキストをバイナリ化してから
サンプルコードをいろんなサイトを参考にしたのですが、肝心のバイナリ化した値を比較する方法がわかりません。
こんなコードを書いて確認してみたのですが、
System.Text.Encoding src = System.Text.Encoding.ASCII;
System.Text.Encoding dest = System.Text.Encoding.GetEncoding("Shift_JIS");
string str1 = "亜";
string str2 = "世";
byte[] temp1 = src.GetBytes(str1);
byte[] temp2 = src.GetBytes(str2);
byte[] sjis_temp1 = System.Text.Encoding.Convert(src, dest, temp1);
byte[] sjis_temp2 = System.Text.Encoding.Convert(src, dest, temp2);
string sjis_str1 = dest.GetString(sjis_temp1);
string sjis_str2 = dest.GetString(sjis_temp2);

Debug.WriteLine("UTF :" + string.CompareOrdinal(str1, str2));
Debug.WriteLine("SJIS:" + string.CompareOrdinal(sjis_str1, sjis_str2));
結果は
UTF :134
SJIS:0
でした。
バイナリ化したのだから文字列比較すること自体おかしい気がするのですが、バイナリでは一致不一致を返す関数しかないみたいです。
(それに並び替えにしようするのでカスタムソート関数内にこんな重そうな処理を書いちゃよくない気も致します…)

なにかよい方法をご存じないでしょうか?
引用返信 編集キー/
■94886 / inTopicNo.5)  Re[3]: リストビューの並びをシフトJIS順にしたい
□投稿者/ KOZ (123回)-(2020/05/30(Sat) 12:31:51)
2020/05/30(Sat) 12:36:13 編集(投稿者)
No94885 (Tom さん) に返信
> バイナリ化したのだから文字列比較すること自体おかしい気がするのですが、バイナリでは一致不一致を返す関数しかないみたいです。

BitConverter.ToString でOKかと。
https://docs.microsoft.com/ja-jp/dotnet/api/system.bitconverter.tostring

class ListViewItemComparer : IComparer
{
    static Encoding encoding = Encoding.GetEncoding("Shift_JIS");
    int Column;
    public ListViewItemComparer(int column)
    {
        Column = column;
    }
    public int Compare(object x, object y)
    {
        var itemx = (ListViewItem)x;
        var itemy = (ListViewItem)y;
        var strx = ToShiftJisCode(itemx.SubItems[Column].Text);
        var stry = ToShiftJisCode(itemy.SubItems[Column].Text);
        return string.Compare(strx, stry); 
    }

    static string ToShiftJisCode(string value)
    {
        var bytes = encoding.GetBytes(value);
        return BitConverter.ToString(bytes);
    }
}

引用返信 編集キー/
■94887 / inTopicNo.6)  Re[4]: リストビューの並びをシフトJIS順にしたい
□投稿者/ KOZ (124回)-(2020/05/30(Sat) 13:14:40)
速度が気になるようであれば

WideCharToMultiByte
https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte

CompareStringOrdinal
https://docs.microsoft.com/ja-jp/windows/win32/api/stringapiset/nf-stringapiset-comparestringordinal

を使ってみるとか。
引用返信 編集キー/
■94889 / inTopicNo.7)  Re[4]: リストビューの並びをシフトJIS順にしたい
□投稿者/ Tom (27回)-(2020/05/30(Sat) 20:13:49)
KOZ さま
更なるアドバイス、ありがとうございます! うまくいきました!!

まずご教授くださった方法をそのままCompare関数に組み入れたのですが、やっぱりかなり遅くなりました。
そのため、ListViewの元データの作成時に項目を1つ追加して、そこにSJIS文字列を作成しました
そしてCompare関数ではその文字列でソートするようにした結果、速度低下も発生しませんでした。

無事解決しました。
あらためて、ありがとうございました。
解決済み
引用返信 編集キー/
■94890 / inTopicNo.8)  Re[3]: リストビューの並びをシフトJIS順にしたい
□投稿者/ とっちゃん (684回)-(2020/05/30(Sat) 20:31:26)
No94885 (Tom さん) に返信
> >System.Text.Encoding.GetEncoding(932).GetBytes でテキストをバイナリ化してから
> サンプルコードをいろんなサイトを参考にしたのですが、肝心のバイナリ化した値を比較する方法がわかりません。
> こんなコードを書いて確認してみたのですが、

Shift_JIS のデータは文字列ではなく、バイト配列になるので、バイト配列を比較すれば大小を判定できます。

Shift_JIS に変換できない場合は考慮しないという前提になっていますが、オーダーをShift_JIS にする時点で
表現できない文字とか考慮しなくていいと思うので、その辺はばっさり切り捨ててます。


int CompareStringSjisOrder( string str1, string str2 )
{
  var encoding = System.Text.Encoding.GetEncoding(932);
  var sjis1 = encoding.GetBytes( str1 );
  var sjis2 = encoding.GetBytes( str2 );

  int comp = 0;
  for( int index = 0 ; comp == 0 && index < sjis1.Length && index < sjis2.Length ; index++ )
  {
    comp = (int)sjis1[index] - (int)sjis2[index];
  }
  if( comp == 0 )
  {
    comp = sjis1.Length - sjis2.Length;
  }
  return comp;
}

引用返信 編集キー/
■94891 / inTopicNo.9)  Re[5]: リストビューの並びをシフトJIS順にしたい
□投稿者/ とっちゃん (685回)-(2020/05/30(Sat) 20:33:01)
No94889 (Tom さん) に返信
> KOZ さま
> 更なるアドバイス、ありがとうございます! うまくいきました!!
>
> まずご教授くださった方法をそのままCompare関数に組み入れたのですが、やっぱりかなり遅くなりました。
> そのため、ListViewの元データの作成時に項目を1つ追加して、そこにSJIS文字列を作成しました
> そしてCompare関数ではその文字列でソートするようにした結果、速度低下も発生しませんでした。
>
> 無事解決しました。
> あらためて、ありがとうございました。

あ、遅かった。

でも、解決してるならいいか。チェック入れておきます。
解決済み
引用返信 編集キー/
■94892 / inTopicNo.10)  Re[4]: リストビューの並びをシフトJIS順にしたい
□投稿者/ Tom (28回)-(2020/05/30(Sat) 23:17:17)
とっちゃん さま

アドバイス、ありがとうございます。

無事解決したのですが、また新しい問題発覚して頭かかえてる最中です。
もうほんと、プログラミングってもぐらたたき・・・

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -