【问题标题】:Comparing Strings with different byte order masks in Java在Java中比较具有不同字节顺序掩码的字符串
【发布时间】:2018-12-22 08:59:55
【问题描述】:

在我的 Java 程序中,我有两个字符串 s1s2,当它们被打印出来时,它们看起来是一样的,但是,因为它们的编码不同,s1.equals(s2) 返回 false。我将如何比较这两个字符串,以便即使它们的编码不同,它们仍然是相等的?

看这个示例代码:

    s1 = s1.trim();
    s2 = s2.trim();
    byte[] s1bytes = s1.getBytes();
    byte[] s2bytes = s2.getBytes();
    System.out.println(s1+","+s2+","+s1.equals(s2));

    System.out.println("\ns1's bytes are:");
    for (int i = 0; i < s1bytes.length; i++) {
        System.out.println(s1bytes[i]);
    }

    System.out.println("\ns2's bytes are:");
    for (int i = 0; i < s2bytes.length; i++) {
        System.out.println(s2bytes[i]);
    }

打印出来:

SHEOGMIOF,SHEOGMIOF,false

s1's bytes are:
-17
-69
-65
83
72
69
79
71
77
73
79
70

s2's bytes are:
83
72
69
79
71
77
73
79
70

正如您在打印时看到的那样,s1s2 看起来相同,但在比较时它们并不相等并且它们的两个字节数组都不同。

编辑:我的问题与this question 不同,因为我不是从文件中读取数据,.java 文件中的源代码编码不同,而不是来自另一个文件的数据。

【问题讨论】:

  • “编码方式不同”是什么意思? Java 字符串始终以 UCS-2 编码。
  • 编码是指它们在写入磁盘或任何其他类型的“字节数组”时的表示。我的猜测是你的字符串有一些空格或其他不可见的字符,这使它们在屏幕上看起来相同但实际上不同。尝试将每个字符的值打印为整数,看看差异在哪里。
  • 例如俄语也有字母 a、o、c 和其他一些字母,可能您的某些字母使用不同的语言。
  • @Silvio Mayolo 我已经编辑了我的帖子以包含一个示例。这不是编码问题吗?如果不让我知道,我会更改标题。
  • 这可能是一个 解码 问题,在从您的外部表示到Strings 的步骤中。字符串本身没有不同的编码。

标签: java encoding


【解决方案1】:

问题中的样本实际上在编码方面并没有不同,但在字节顺序标记的存在/不存在方面。

下面的类演示了当字节序列确实代表不同的字符串编码时如何处理这种情况。在示例代码中,编码必须是已知的。请注意,一般来说,仅从字节序列中推断编码是一项非常重要的任务。

//  https://stackoverflow.com/questions/229015/encoding-conversion-in-java
//

import java.lang.*;
import java.io.*;
import java.nio.*;

public class encotest {
    public static void main(String[] args) {
        // German lowercase umlauted vowels (äöü) as octet sequences in 2 different encodings
        byte[]  raw_iso8859_15  = { (byte) 0xE4, (byte) 0xF6, (byte) 0xFC };
        byte[]  raw_utf8        = { (byte) 0xC3, (byte) 0xA4, (byte) 0xC3, (byte) 0xB6, (byte) 0xC3, (byte) 0xBC };

        try {
            String s_umlauts_from_iso   = new String(raw_iso8859_15 , "ISO-8859-15");
            String s_umlauts_from_utf8  = new String(raw_utf8       , "UTF-8");

            if (s_umlauts_from_iso.equals(s_umlauts_from_utf8)) {
                System.out.println("They are the same !");
            }
            else {
                System.out.println("They differ!");
            }
        } catch (UnsupportedEncodingException uee) {
            System.out.println("Error: cannot convert");
        }
    }
}

预期输出:

They are the same !

【讨论】:

  • @flakes 你是对的,在答案中添加了预期的程序输出。谢谢。
【解决方案2】:

从文件中读取字符串时,从字符串中删除字节顺序掩码 (BOM)。这个字符代码是"\uFEFF"

public class Foo {
    public static void main(final String[] args) {
        final byte[] b1 = {-17, -69, -65, 83, 72, 69, 79, 71, 77, 73, 79, 70};
        final byte[] b2 = {83, 72, 69, 79, 71, 77, 73, 79, 70};

        final String s1 = new String(b1).replace("\uFEFF", "");
        final String s2 = new String(b2).replace("\uFEFF", "");

        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1.equals(s2));
    }
}

打印:

SHEOGMIOF
SHEOGMIOF
true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-18
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 2020-03-22
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多