解释
您的代码存在两个问题。更大的问题是DataInputStream
不会像您想象的那样读取,另一个问题是您将两个资源连接到System.in
,即DataInputStream
和Scanner
。您应该只使用Scanner
来读取所有数据。
连接两者的问题在于DataInputStream
也会解释先前输入的4
,因为它仅由Scanner
消耗,但不由DataInputStream
消耗。也就是说,我无法复制您的确切值。如果我输入4
,然后是a
、b
、c
,那么我将无法输入d
,因为DataInputStream
也读取了4
(我认为原因是您的计算机使用\n
作为换行符,而我的计算机使用\r\n
)。所以最终的输入是
4
a
b
c
如果我调整您的循环,使其还显示打印出来的内容(作为字符):
for (int i = 0; i < character.length; i++) {
int ascii = (int) character[i];
System.out.println(character[i] + " -> " + ascii);
}
我得到了这个:
? -> 24845
? -> 2658
? -> 3338
? -> 25357
好的,那么为什么要使用?
代替正确的输入?因此我们需要看一下DataInputStream#readChar
的工作原理。根据其文档:
返回:此输入流的下两个字节,解释为字符。
然而,为了获得ASCII值,我们需要以类似ASCII的字节流进行解释。 ASCII也有固定的长度,但每个字符只有一个字节而不是两个字节。 但是,如果您还想读取不同的字符,例如ä
、é
或甚至我
,则需要使用某些编码方案(如UTF-16)而不是固定长度来解释字节流。现在请注意,UTF-16不是固定长度的。
为了理解这些值,让我们看一下确切的字节流:
01100001 00001101 // ? -> 24845
00001010 01100010 // ? -> 2658
00001101 00001010 // ? -> 3338
01100011 00001101 // ? -> 25357
正如您所看到的,如果我们像这样排列字节(总是两个字节),我们就可以得到相应的十进制格式值。对于ASCII码,我们需要重新排列字节并以此方式读取:
01100001 // a -> 97
00001101 // \r -> 13
00001010 // \n -> 10
01100010 // b -> 98
00001101 // \r -> 13
00001010 // \n -> 10
01100011 // c -> 99
00001101 // \r -> 13
正如您所看到的,字节流中包含的字符不仅仅是
a
、
b
和
c
,还有
\r
和
\n
。这两个字符被解释为
换行符命令,因此请参见
维基百科。
解决方案
最简单的解决方法是使用Scanner
及其next
方法(文档)。此方法会自动阻塞,直到输入下一个完整的令牌。这是由分隔符模式确定的。为了设置一个UTF-16字符,我们只需用空的String
作为分隔符(因此请参考从Scanner获取char输入):
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("");
之后你可以读取4个String
值。然而我们仍然面临\r\n
被输入到Scanner
的问题。
消除这个问题最简单的方法是使用Scanner#nextLine
(文档)。因此,我们不仅仅读取一个字符,而是读取整行。该方法会自动为我们舍弃\r\n
:
Scanner scanner = new Scanner(System.in);
System.out.println("Enter number of Characters you want to insert : ");
int n = Integer.parseInt(scanner.nextLine());
char[] character = new char[n];
System.out.println("Enter Characters : ");
for (int i = 0; i < n; i++) {
character[i] = scanner.nextLine().charAt(0);
}
for (int i = 0; i < character.length; i++) {
int ascii = (int) character[i];
System.out.println(character[i] + " -> " + ascii);
}
现在已经正确地打印了ASCII值
a -> 97
b -> 98
c -> 99
d -> 100
准确地说,它打印出UTF-16值,但ASCII包含在UTF-16中。
char
强制转换为int
时,您会得到 Unicode。请注意,Unicode 包括 ASCII,因此像(int) 'a'
这样的代码会正确地给出97
(ASCII 中的 a)。检查您要转换的内容,将System.out.println(character[i]);
添加到您的循环中。 - ZabuzardDataInputStream
总是读取两个字节,但Unicode的长度是可变的。特别是像ASCII值这样的小值只由一个字节表示。 - Zabuzard