Java 在不知道字符集的情况下,泛型函数如何处理字符?

Java 在不知道字符集的情况下,泛型函数如何处理字符?,java,hash,encoding,character-encoding,Java,Hash,Encoding,Character Encoding,我将以sha-1为例回答我的问题。据我所知,sha1是一个函数,它将一些数字作为输入,并生成另一个数字作为输出 假设我们找到字符的sha1值。这不是ASCII集合中的字符。有更多关于它的信息。告诉我此字符的sha1值是:94a759fd37735430753c7b6b80684306d80ea16e 字符u,在UTF-8中用C3 BC表示,在UTF-16中用00FC表示。那么,我们真的可以在不使用文本字符编码的情况下讨论sha1吗?以什么值为例?字符编码不会有很大的不同吗 据我所知,在Java中

我将以sha-1为例回答我的问题。据我所知,sha1是一个函数,它将一些数字作为输入,并生成另一个数字作为输出

假设我们找到字符
的sha1值。这不是ASCII集合中的字符。有更多关于它的信息。告诉我此字符的sha1值是:
94a759fd37735430753c7b6b80684306d80ea16e

字符
u
,在UTF-8中用
C3 BC
表示,在UTF-16中用
00FC
表示。那么,我们真的可以在不使用文本字符编码的情况下讨论sha1吗?以什么值为例?字符编码不会有很大的不同吗

据我所知,在Java中,所有字符都由UTF-16表示。当我用Java计算sha-1时,例如上面的例子,函数是否会在输入
00FC
上工作


让我们看另一种编程语言,其中所有字符都由UTF-8表示。sha1的结果会与Java完全不同吗

哈希函数将字节数组作为输入。将字符或字符串转换为字节数组,并在转换中显式或隐式指定字符集。字节值不一定与字符数值相同,这取决于字符集。
一般来说,泛型函数需要知道字符集,但可以隐式提供此信息

您可以使用不同的字符集编码器进行实验,看看它们有什么不同

import javax.xml.bind.DatatypeConverter;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        String s = "ü";
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        for (Map.Entry<String, Charset> entry : Charset.availableCharsets().entrySet()) {
            try {
                byte[] encoded = s.getBytes(entry.getValue());
                byte[] digest = sha1.digest(encoded);
                System.out.printf("For encoding %s, SHA1 hash is %s%n",
                        entry.getKey(), DatatypeConverter.printHexBinary(digest));
            } catch (UnsupportedOperationException e) {
                System.out.printf("Cant make it work for %s%n", entry.getKey());
            }
        }
    }

}

正如前面提到的其他答案一样,SHA-1校验和是从字节计算出来的。但是,当您使用Java或Java之类的实用程序时,字符编码起作用,因为不同的字符集用于表示文本。上面提到的在线实用程序混淆了这个问题,因为它没有指定用于计算值的字符集

通常,当您使用内置系统实用程序(如shasum(UNIX)或certutil(Windows))在文件上计算SHA-1时,它只读取文件的字节。如果要使用文本编辑器保存文件,您会注意到它允许您选择编码。记事本有ANSI和UTF-8作为选项。如果在一个文件中将文本另存为ANSI,而在另一个文件中将同一文本另存为UTF-8,则它们将生成不同的SHA-1校验和,因为用于表示字符的字节不同

据我所知,在Java中,所有字符都由UTF-16表示。 Java中的字符串是代表UTF-16代码单元的16位数字序列

哈希函数处理字节序列。Java中的字符串不是字节序列。因此,要将字符串传递给哈希函数,必须首先将其转换为字节序列。有些语言可能允许您隐式地将16位数字序列重新解释为字节序列,但Java并没有那么草率

当我在Java中计算sha-1时,例如上面的例子,函数是否会在输入00FC上工作

如果您使用的是链接的Java示例代码,那么几乎肯定不会

链接到的java示例使用String.getBytes()执行此转换。getBytes()不会简单地将单词序列重新解释为字节序列。相反,它根据“平台的默认字符集”将UTF-16代码单元的序列转换为字节序列


“平台的默认字符集”的内容将因平台和设置平台的人员选择的语言设置而异,但它将是基于字节的ASCII字符集,而不是UTF-16。

哈希函数通常在字节上运行,而不是在字符上。@OliverCharlesworth好吧,我的问题仍然有效。字节是这些数字以二进制而不是十六进制表示的方式。我想说的是,哈希函数不知道或不关心您使用的字符集。@OliverCharlesworth是的,但当我们对
u
进行哈希运算时,我们向其提供的输入是什么?@OliverCharlesworth如果您能告诉我输入(以二进制形式)的话这将输出sha-1值
94a759fd37735430753c7b6b80684306d80ea16e
这将帮助我理解。它一定是一个数字,但它是什么?我认为这很大程度上取决于字符编码,因为
ü
不是一个数字?