我在解释文件时遇到问题。该文件的构建如下:
“名称” - @ - “日期” - @ - “作者” - @ - “签名”
签名是一个字节数组。当我在i中读取文件时,我将其解析为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]
filecontent(读取后的var):
... 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]
签名(在split和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]
答案 0 :(得分:3)
您无法访问data[4]
,因为您的表格中有4 String
。因此,您可以从0到3访问data
。
data[0] = name
data[1] = date
data[2] = author
data[3] = signature
解决方案:
byte[] signature = data[3].getBytes();
答案 1 :(得分:1)
编辑:我想我终于明白你在做什么了。
您有四个部分:姓名,日期,作者,签名。名称和作者是字符串,日期是日期,签名是散列或加密的字节数组。您希望将它们作为文本存储在文件中,以-@-
分隔。要做到这一点,首先需要将每个转换为有效的字符串。名称和作者已经是字符串。将日期转换为字符串很容易。将字节数组转换为字符串并不容易。
您可以使用 base64 编码将字节数组转换为字符串。使用javax.xml.bind.DatatypeConverter printBase64Binary()
进行编码,使用javax.xml.bind.DatatypeConverter parseBase64Binary()
进行解码。
例如,如果您有一个名称denBelg
,日期2013-03-19
,作者Virtlink
以及此签名:
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签名部分并返回一个字节数组。
注意当名称或作者在其名称中包含-@-
时,他们可能会搞砸您的代码。例如,如果我将名称设置为den-@-Belg
,则代码将失败。
原帖:
Java的String.getBytes()
使用字符串的平台默认编码。编码是字符串字符映射到字节值的方式。因此,根据平台,结果字节可能不同。
将编码修复为UTF-8
并使用相同的编码进行阅读,您的问题就会消失。
byte[] signature = data[3].getBytes("UTF-8");
String sigdata = new String(signature, "UTF-8");
0? - ???ŤK( ?XD ?? B0e98?}υI`LQ3E
你的例子代表了一些混乱的字符(是加密的还是什么?),但你突出显示的字节显示了问题:
您从字节值 -115 开始。减号表示它是一个高于0x7F的字节值,其字符表示高度依赖于所使用的编码。让我们假设扩展US-ASCII,然后你的字节代表(根据this table)字符ì
(带重音)。现在解码时,解码器(取决于您使用的编码)可能无法理解字节值0x8D,而是用问号?
表示。请注意,问号是US-ASCII字符 63 ,这就是您的63来自的位置。
因此,确保确保一致地使用您的编码,而不是依赖于系统的默认编码。
此外,永远不要使用字符串编码来解码不代表字符串的字节数组(例如哈希或其他加密内容)。
根据您的评论,您试图读取加密数据(这些是字节)并使用解码器将它们转换为字符串? 永远不会以您期望的任何方式工作。在加密某些内容之后,您将拥有一个字节数组,您应该将存储为。当你读回它们时,你必须通过解密器放置字节以重新获得未加密的字节。只有当那些解密的字节表示字符串时,您才可以使用编码来解码字符串。
答案 2 :(得分: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();
链接:
答案 3 :(得分:0)
听起来像编码问题。
首先,您需要知道文件使用的编码,并在读取文件时使用它。
其次,你说签名是一个字节数组,但java字符串总是unicode。如果你想要一个不同的编码(我猜你想要ASCII),你需要做getBytes("US-ASCII")
。
当然,如果您的输入是ascii,那么这可能会导致编码问题,这很奇怪。