【问题标题】:byte[] to string and back to byte[]byte[] 到字符串并返回到 byte[]
【发布时间】:2013-03-08 04:39:55
【问题描述】:

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

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

签名是一个字节数组。当我读回文件时,我将其解析为字符串并对其进行拆分:

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]

【问题讨论】:

  • 您正在对加密数据使用字符编码。请参阅我的帖子的编辑:您必须将加密数据视为 only 字节,并在将其视为字符串之前对其进行解密(通过使用解码器)。您不能将加密签名读取为字符串并将其拆分。

标签: java string byte


【解决方案1】:

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

data[0] = name

data[1] = date

data[2] = author

data[3] = signature

解决办法:

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

【讨论】:

  • 这不是问题,我只是在我的问题中忘记了一个属性。我调试了我的项目,我发现几乎所有字节都是正确的,除了少数......
  • @denBelg 也许文件有问题。您能否提供文件的内容或至少提供一个示例?
【解决方案2】:

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

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

您可以使用 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 签名部分并取回一个字节数组。

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


原帖:

Java 的String.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,那么您的字节代表(根据this table)字符ì(带有重音符号)。现在,当您对其进行解码时,解码器(取决于您使用的编码)可能无法理解字节值 0x8D,而是用问号 ? 表示它。请注意,问号是 US-ASCII 字符 63,这就是您的 63 的来源。

所以确保你始终使用你的编码,不要依赖系统的默认值。


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

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

【讨论】:

  • 好的,谢谢。我会寻找不同的解决方案,因为如果害怕,这将无济于事。就像你说的,我用加密内容制作了一个字符串,这不是要走的路。
  • @denBelg Java 使用 UTF-16(每个字符两个字节)编码。使用 UTF-8 将为 最常见的拉丁字符生成 一个字节 编码。那么原来的长度的两倍是什么意思?比字符多的字节还是什么?你想编码什么?文本、散列、加密或压缩内容,还是其他内容?
  • 某个日期的加密签名
  • @denBelg 我想我知道你在做什么。请重新阅读我的帖子。
  • 谢谢你的解释,现在我更好地理解了我的问题,我寻求一个解决方案,将签名的长度保存在文件中。所以我可以从文件中读取最后 x 个字节。这项工作就像一个魅力......而且我无法在我的编码文件中遇到 -@- 问题。
【解决方案3】:

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

// 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();

链接:

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 2013-02-18
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      相关资源
      最近更新 更多