为什么我的Java字符串用空值填充?

时间:2012-08-19 14:46:13

标签: java android

我有以下代码,从方法复制/粘贴:

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”,但返回语句从未被命中。仔细检查,我可以看到文件名用8个空字符填充(\ u0000)。

我有两个问题:

  1. 为什么字符串填充?

  2. 在IDEA中,打破if语句然后使用表达式计算器(Alt-F8)显示filename.equals(file)为true,但在运行时单步调试我的代码表明它不是。我认为这是IDEA评估表达式和Dalvik VM的方式的一些低级差异?我假设VM是正确的,因为文件名确实不等于文件。

  3. 感谢您的任何见解。

    西蒙

    [编辑]我确信其余代码不相关,但无论如何,删除注释以节省空间。

    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是$%^&amp; *脑死!

3 个答案:

答案 0 :(得分:1)

1)除非我遗漏了某些内容,否则你的字符串是填充的,因为格式语句"%04d%s"将使用零填充来获得4位数,因此为“0062.tch”。我错过了什么吗?

对于空字符的右边填充,有两个注释。首先,每个十六进制字符是半个字节,因此(\ u0000)是两个字节,因此是一个字符。此外,IDE将显示String中分配的所有字节,但是当它打印,比较等时,它将停在第一个空字符处。

答案 1 :(得分:1)

在评论中你写这个。

  

正确。如果我检查后备字符数组,它看起来像这样:[0] [0] [6] [2] [.] [t] [c] [h] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000] [\u0000]

这并不一定意味着String与NUL一起传递。

字符串的状态由value[offset]value[offset + count - 1]的字符组成。我猜测offset必须为零,但没有真实的证据证明count的价值是什么......

那些NUL很可能超出String状态的结束,因此不是你问题的原因。

答案 2 :(得分:0)

Doh,doh,doh,doh,doh。怎么可能花3个小时看问题,在SO上求助,然后在5分钟后发现愚蠢?感谢所有花时间回应的人,并为浪费时间和空间而道歉。

第二种方法是对assets文件夹进行递归搜索。您可以看到递归调用的结果存储在thisFile中。因此,if语句应为:

if(thisFile.equals(filename)){}

那就是说,我仍然很好奇为什么用空格填充文件名,而文件和thisFile则没有。然而,只有当代码现在有效时,才会产生深奥的兴趣...