【问题标题】:Strange behaviour of String.length()String.length() 的奇怪行为
【发布时间】:2015-07-06 15:35:57
【问题描述】:

我有主课:

public class Main {

// args[0] - is path to file with first and last words
// args[1] - is path to file with dictionary 
public static void main(String[] args) {
    try {
        List<String> firstLastWords = FileParser.getWords(args[0]);
            System.out.println(firstLastWords);
        System.out.println(firstLastWords.get(0).length());

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

我有 FileParser:

public class FileParser {

    public FileParser() {
    }

    final static Charset ENCODING = StandardCharsets.UTF_8;


    public static List<String> getWords(String filePath) throws IOException {
        List<String> list = new ArrayList<String>();
        Path path = Paths.get(filePath);

        try (BufferedReader reader = Files.newBufferedReader(path, ENCODING)) {
            String line = null;
            while ((line = reader.readLine()) != null) {

                String line1 = line.replaceAll("\\s+","");
                if (!line1.equals("") && !line1.equals(" ") ){
                    list.add(line1);
                }
            }
            reader.close();
        }
        return list;
    }   
}

args[0] 是 txt 文件的路径,只有 2 个单词。所以如果文件包含:

тор
кит

程序返回:

[тор, кит]
4

如果文件包含:

т
тор
кит

程序返回:

[т, тор, кит]
2


即使文件包含:
//跳到下一行
回复
ㄧㄧㄧ

程序返回:

[, тор, кит]
1

其中 digit - 是列表中第一个字符串的长度。

所以问题是为什么它要多计算一个符号?

【问题讨论】:

  • 来自String#length的文档-docs.oracle.com/javase/7/docs/api/java/lang/…“返回此字符串的长度。长度等于字符串中Unicode代码单元的数量。”
  • 那么 that 如何解释 OP 的问题?
  • 我不明白对这个问题的反对意见 - 这个人正确地包含了所有相关代码,描述了发生的事情,并描述了他的预期。这几乎是正确代码问题的典型代表。我每天都会看到数十个可怕的代码问题,但没有得到任何反对。请解释你自己,downvoters。
  • 您的文件中可能存在某种不可打印的字符。您可以尝试遍历字符串中的每个字符并单独打印出来吗?
  • @erwinbolwidt - 我完全同意;我实际上投了赞成票

标签: java string string-length


【解决方案1】:

谢谢大家。

@Bill 所说的这个符号是 BOM (http://en.wikipedia.org/wiki/Byte_order_mark),位于文本文件的开头。 所以我通过这一行找到了这个符号:

System.out.println(((int)firstLastWords.get(0).charAt(0)));

它给了我 65279

然后我刚刚更改了这一行:
String line1 = line.replaceAll("\\s+",""); 到这个

String line1 = line.replaceAll("\uFEFF","");

【讨论】:

    【解决方案2】:

    使用正则表达式很难捕获西里尔字符,例如\p{Graph} 不起作用,尽管它们是清晰可见的字符。无论如何,除了 OP 问题。

    实际问题可能是由于存在其他不可见字符,可能是控制字符。尝试按照正则表达式删除更多:replaceAll("(\\s|\\p{Cntrl})+","")。您可以使用 Regex 进一步将其扩展到其他情况。

    【讨论】:

    • 你可以试试这个:replaceAll("(\\s|\\p{Cntrl}|\\n|\\r)+","") - 让我知道结果。
    • 尝试同时输入此代码for (byte b:line1.getBytes()) {System.out.print(((long)b)&amp;0xFF);System.out.print("/");} System.out.println(); 以找出隐藏字符是什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 2015-07-20
    • 2010-10-03
    • 2021-07-12
    • 2013-10-04
    相关资源
    最近更新 更多