タブレット用プログラムの書き止め

android OS & iPadOS の記録。

ArrayList<>へフォルダー内のファイル名をリストアップしてソートする

2021-06-11 17:33:18 | Android studio 日記

 デバイスにインストールしてからでないと内部外部ストレージの操作確認ができません。とりあえず、assetsフォルダーでサブのimageフォルダーを作り画像ファイルを操作をしました。assetManagerでサブフォルダーのファイル名のリストアップができるので予行演習です。

1.jpg、33.png、183.jpg

 ArrayListでソートをしたら、この並びになると思っていたら

1.jpg、183.jpg、33.png

 数値 判断でなく、1文字1文字の並びの判断だから予想通りにならない。ファイル名が数字のみなら整数に変換して順番を判断。あるいは、

001.jpg、033.png、183.jpg

 桁数を揃えてしまうとか。とにかく、ファイル名変更もプログラムでの判断条件も文字と文字数字の混在があると面倒くさい。仕方ないので、実ファイル名と判断用修整ファイル名の2つの文字列を持つ構造体を作る。数字の塊りが合ったら”0”を前に付加して桁数を8桁に揃える。処理を間違えるとリークしそうだなぁ。解放に気を付けよう。

 

//////////////////////////////////////////////////////////////////////////////////////

public class MyFilename {
    private String name1 = ""; // 元のファイル名
    private String name2 = ""; // 漢字、数字混在のとき、半角数字の前方を"0"で埋めた8桁に修正したもの


   //     ArrayList<> で、ファイル名をソートするための準備。name2を判定条件に使う

    public MyFilename( String name ) {
        this.name1 = name;

        StringBuilder sb = new StringBuilder( name );
        String[] msplit1 = sb.toString().split( "[^\\d]" ); // 数字以外で分割
        String[] msplit2 = sb.toString().split( "\\d" ); // 数字で分割

        boolean mFlag = true;
        sb = new StringBuilder();

        // 1つの文字列を同条件反転分割しているので配列先頭[0]のみ、どちらか必ず文字が入っている

        if ( msplit1[0].length() == 0 ) {
            mFlag = true;
        } else {
            sb.append( zeroCompensation( msplit1[0]) ); // 0補填をして数字を積む
        }
        if ( msplit2[0].length() == 0 ) {
            mFlag = false;
        } else {
            sb.append( msplit2[0] ); // 文字を積む
        }

       /*
       数字の次は文字、文字の次は数字、フラグで切り替え積んでいく。数字は0補填。
       数字分割の場合は数字の塊りではなく、「0-9」の1文字が出た時点でバッファに
       溜まっている文字を配列に書き込みます。多分。
       「a123bc.jpg」
       "1"が分割タイミング、バッファに"a"が入ってるので List[0]= "a"となります。
       "2"も分割タイミング、バッファは空なので List[1]= "" 空文字が入ります。
       "3"も空文字、文字列最後で List[3]= "bc.jpg"と状況判断できます。文字抽出、文字以外は空。
       数字以外の分割は逆処理、数字以外は空、数字の塊りが抽出され"123"を"00000123"に変更。
       文字と数字をフラグで組み立てれば完了。
       */

        int i = 0, j = 0, len;
        while ( ( i < msplit1.length ) && ( j < msplit2.length ) ) {
            if ( mFlag ) { // 直前が数字でなかった
                if ( ++i < msplit1.length ) {
                    if ( msplit1[i].length() != 0 ) { // 数字が現れた
                        sb.append( zeroCompensation( msplit1[i] ) );
                        mFlag = false;
                    }
                }
            } else { // 直前が文字でなかった
                if ( ++j < msplit2.length ) {
                    if ( msplit2[j].length() != 0 ) {  // 文字が現れた
                        sb.append( msplit2[j] );
                        mFlag = true;
                    }
                }
            }
        }

        this.name2 = sb.toString();
    }
    public String getName() {  // 実ファイル名
        return this.name1;
    }
    public String getName2() {  // 判断用文字列
        return this.name2;
    }

    private String zeroCompensation( String text ) {
        StringBuilder sb = new StringBuilder();
        int len = text.length(); // 桁数
        if ( len < 8 ) { // 8桁未満なら0を前に付けて8桁に合わせる
            len = 8 - len;
            for ( int c = 0; c < len; c++ ) {
                sb.append( "0" );
            }
        }
        sb.append( text );
        return sb.toString();
    }
}

//////////////////////////////////////////////////////////////////////////////////////

 

 このクラスを ArrayList<> で配列とします。

    ArrayList mFileNameList = new ArrayList<>();

 と、実装して、

 

 

      String fName;
      String[] mList = assetManager.list( "image" );
      for ( String s : mList ) {
           fName = s.toLowerCase(); // 小文字に変換
           if ( fName.endsWith( ".jpg" ) || fName.endsWith( ".png" ) ) { // 画像ファイルを拡張子で判別
                mFileNameList.add( new MyFilename( s ) ); // ファイル名を配列に加える
            }
        }

 ファイル名リストからソート用配列を作る。

 

 

    Collections.sort(  mFileNameList, new Comparator() {
            @Override
            public int compare( MyFilename mf1, MyFilename mf2 ) {
                 return mf1.getName2().compareTo( mf2.getName2() );
            }
     } );

 ファイルの実名は変えずに含まれる数字の数や桁数に関係なく数値の順番でソートできたと思う。

 

 

    int index = 0;
    String fName;
    fName = mFileNameList.get( index ).getName();

 ソート後は、こんな感じで index を変えてファイル名を読み出す。

 

 次は、画面をタップした時にリスト順に画像を切り替える。スワイプで切り替える。かな。