2

我在解释文件时遇到问题。该文件的构建如下:

“姓名”-@-“日期”-@-“作者”-@-“签名”

签名是一个字节数组。当我读回文件时,我将其解析为 String 并拆分它:

myFileInpuStream.read(fileContent);    
String[] data = new String(fileContent).split("-@-");

如果我查看 var fileContent,我发现字节都很好。但是当我尝试获取签名字节数组时:

byte[] signature=  data[3].getBytes();

有时我会得到错误的 63 值。我尝试了一些解决方案:

new String(fileContent, "UTF-8")

但没有运气。有人可以帮忙吗?签名不是固定长度,因此我无法对其进行硬编码...

一些额外的信息:

原始签名:

[48、45、2、21、0、-123、-3、-5、-115、84、-86、26、-124、-112、75、-10、-1、-56、40、13 , -46, 6, 120, -56, 100, 2, 20, 66, -92, -8, 48, -88, 101, 57, 56, 20, 125, -32, -49, -123, 73 , 96, 76, -82, 81, 51, 69]

文件内容(阅读后的变量):

... 48、45、2、21、0、-123、-3、-5、-115、84、-86、26、-124、-112、75、-10、-1、-56、40 , 13, -46, 6, 120, -56, 100, 2, 20, 66, -92, -8, 48, -88, 101, 57, 56, 20, 125, -32, -49, -123 , 73, 96, 76, -82, 81, 51, 69]

签名(拆分和getBytes()之后):

[48、45、2、21、0、-123、-3、-5、63、84、-86、26 -124、63、75、-10、-1、-56、40、13、- 46、6、120、-56、100、2、20、66、-92、-8、48、-88、101、57、56、20、125、-32、-49、-123、73、96 , 76, -82, 81, 51, 69]

4

4 回答 4

3

您无法访问data[4],因为您String的桌子上有 4 个。所以你可以data从0访问到3。

data[0] = name

data[1] = date

data[2] = author

data[3] = signature

解决方案 :

byte[] signature = data[3].getBytes();
于 2013-03-19T13:21:07.987 回答
1

编辑:我想我终于明白你在做什么了。

您有四个部分:姓名、日期、作者、签名。姓名和作者是字符串,日期是日期,签名是散列或加密的字节数组。您希望将它们作为文本存储在文件中,以 . 分隔-@-。为此,您首先需要将每个字符串转换为有效的字符串。姓名和作者已经是字符串。将日期转换为字符串很容易。将字节数组转换为字符串并不容易。

您可以使用base64编码将字节数组转换为字符串。用于javax.xml.bind.DatatypeConverter printBase64Binary()编码和javax.xml.bind.DatatypeConverter parseBase64Binary()解码。

例如,如果您有 name denBelg、 date 2013-03-19、 authorVirtlink和此签名:

30 2D 02 15 00 85 FD FB 8D 54 AA 1A 84 90 4B F6 FF C8 28 0D D2 06 78 C8 64 02 14
 42 A4 F8 30 A8 65 39 38 14 7D E0 CF 85 49 60 4C AE 51 33 45

然后,在签名的连接和base64编码之后,生成的字符串变成了,例如:

denBelg-@-20130319-@-Virtlink-@-MC0CFQCF/fuNVKoahJBL9v/IKA3SBnjIZAIUQqT4MKhlOTgUfeDPhUlgTK5RM0U=

稍后,当您拆分字符串时,-@-您可以解码 base64 签名部分并取回一个字节数组。

请注意,当姓名作者可以包含-@-在他们的姓名中时,他们可能会弄乱您的代码。例如,如果我将 name 设置为,den-@-Belg那么您的代码将失败。


原帖:

JavaString.getBytes()对字符串使用平台默认编码。编码是将字符串字符映射到字节值的方式。因此,根据平台的不同,生成的字节可能会有所不同。

修复编码UTF-8并使用相同的编码读取它,您的问题就会消失。

byte[] signature = data[3].getBytes("UTF-8");

String sigdata = new String(signature, "UTF-8");

0-???����T�?��K���(�?x�d??B��0�e98?}�υI`L�Q3E

您的示例代表了一些乱码(是加密的还是什么?),但是您突出显示的字节显示了问题:

您从-115的字节值开始。减号表示它是高于 0x7F 的字节值,其字符表示高度依赖于使用的编码。让我们假设扩展的 US-ASCII,然后您的字节代表(根据此表)字符ì(带有重音符号)。现在,当您对其进行解码时,解码器(取决于您使用的编码)可能无法理解字节值 0x8D 而是用问号表示它?。请注意,问号是 US-ASCII 字符63,这就是您的 63 的来源。

因此,请确保您始终如一地使用您的编码,并且不要依赖系统的默认值。


此外,切勿使用字符串编码来解码不代表字符串的字节数组(例如散列或其他加密内容)。

根据您的评论,您正在尝试读取加密数据(即字节)并使用解码器将它们转换为字符串?永远不会以您期望的任何方式起作用。在你加密了一些东西之后,你有一个字节数组,你应该按原样存储。当您读回它们时,您必须将字节放入解密器以重新获得未加密的字节。只有当这些解密的字节表示一个字符串时,您才能使用编码来解码该字符串。

于 2013-03-19T13:46:31.247 回答
0

对我来说听起来像是一个编码问题。

首先,您需要知道文件使用的是什么编码,并在读取文件时使用它。

其次,你说你的签名是一个字节数组,但java字符串总是unicode。如果你想要不同的编码(我猜你想要 ASCII),你需要做getBytes("US-ASCII").

当然,如果您的输入是 ascii,那么这可能会导致编码问题,这很奇怪。

于 2013-03-19T13:44:16.953 回答
0

通过手动将这些字节转换为字符串,您正在为自己做额外的工作。你为什么不使用为此而设计的类呢?

// get the file /logs/access.log
Path path = FileSystems.getRoot().getPath("logs", "access.log");
// open it, decoding UTF-8
BufferReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
// read a line of text, properly decoded
String line = reader.readLine();

或者,如果您使用的是 Java 6:

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("/logs/access.log"), "UTF-8"));
String line = reader.readLine();

链接:

于 2013-03-19T13:40:18.280 回答