1

メソッドからコピー/貼り付けする次のコードがあります。

String harmonicFile;
...
...
harmonicFile = String.format("%04d%s",this.number, this.suffix.toUpperCase()) + ".tch";

結果は問題ないように見えますが、ファンキーな部分がいくつかあります:

この文字列を、これを含む別のメソッドに渡します。

if(filename.equals(file)){
   return file;
}

fileName は渡された値であり、file はアセット ファイル システムからの一致です。ファイルが「0062.tch」であるとします。Intellij IDEA デバッガーでファイル名を検査すると、「0062.tch」と等しいことが示されますが、return ステートメントはヒットしません。よく調べてみると、ファイル名に 8 個のヌル文字 (\u0000) が埋め込まれていることがわかります。

2 つの質問があります。

  1. 文字列がパディングされているのはなぜですか?

  2. IDEA では、if ステートメントを中断して式エバリュエーター (Alt-F8) を使用すると、filename.equals(file) が true であることが示されますが、実行時にコードをステップ実行すると、そうではないことが示されます。これは、IDEA が式を評価する方法と Dalvik VM の低レベルの違いだと思いますか? ファイル名は実際にはファイルと等しくないため、VM は正しいと思います。

洞察をありがとう。

サイモン

[編集] コードの残りの部分は関係ないと確信していますが、スペースを節約するためにコメントを削除しました。

public String filePathForHarmonicFile(){

    String harmonicFile;
    int number = this.number;

    if(this.number < 0){ return "";}

    if(number<10000 && this.suffix.length()<=1){
        harmonicFile = String.format("%04d%s",this.number, this.suffix.toUpperCase()) + ".tch";
    }else{
        harmonicFile = String.format("%s%s",this.number,this.suffix.toUpperCase()) + ".tch";
    }

    return SCFileManager.getAssetFilePath("",harmonicFile);
}

public static String getAssetFilePath(String rootOfSearch, String filename){

    try {

        // get a list of all file entries in the search root
        String[] files = ThisApplication.getContext().getAssets().list(rootOfSearch);

        for (String file:files){

            String newRoot;
            if (rootOfSearch.equals("")){
                newRoot = file;
            } else {
                newRoot = rootOfSearch + File.separator + file;
            }

            if (TidesPlannerApplication.getContext().getAssets().list(newRoot).length>0){

                String thisFile = getAssetFilePath(newRoot,filename);

                if (!thisFile.equals("")){
                    return thisFile;
                }
            } else {
                if(file.equals(filename)){
                    return file;
                }
            }
        }

    } catch (IOException e) {
        e.printStackTrace();  
    }

    return "";

}

この最後の方法が醜いことはわかっていますが、資産のサブフォルダーにある 7.5k ファイルを処理するためのより良い方法を誰かが知っているなら、私はすべて耳を傾けます - AssetManager は $%^&* 脳死です!

4

3 に答える 3

1

コメントでこれを書きます。

正しい。バッキング char 配列を調べると、次のようになります。[0] [0] [6] [2] [.] [t] [c] [h] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000]

これは必ずしも String が NUL で渡されることを意味するわけではありません。

String の状態は からvalue[offset]までの文字で構成されvalue[offset + count - 1]ます。はゼロでなければならないと推測しoffsetますが、 の値が何であるかについての実際の証拠はありませんcount...

これらの NUL は String 状態の終わりを超えている可能性があるため、問題の原因ではありません。

于 2012-08-19T15:18:06.863 に答える
1

1)何かが欠けていない限り、あなたの文字列は"%04d%s"4桁になるようにゼロで埋められるフォーマットステートメントのためにパディングされているため、「0062.tch」になります。何か不足していますか?

ヌル文字の右パディングについては、いくつかの注意事項があります。まず、各 16 進文字は半バイトであるため、(\u0000) は 2 バイト、つまり 1 文字です。また、IDE は に割り当てられたすべてのバイトを表示しますStringが、出力、比較などを行うと、最初のヌル文字で停止します。

于 2012-08-19T14:49:54.277 に答える
0

ド、ド、ド、ド、ド。問題を見て 3 時間以上費やし、SO で助けを求めて叫び、5 分後に愚かさを見つけることができるのはどうしてですか? 返信に時間を割いてくださったすべての方々に感謝し、スペースと時間を無駄にしてしまったことをお詫びします。

2 番目の方法は、assets フォルダーの再帰的な検索です。再帰呼び出しの結果が thisFile に格納されていることがわかります。したがって、if ステートメントは次のようになります。

if(thisFile.equals(filename)){}

そうは言っても、 file と thisFile がそうではないのに、 filename が null で埋められている理由についてはまだ興味があります。ただし、コードが機能するようになっただけの難解な関心...

于 2012-08-19T15:23:18.693 に答える