Java和C之间的Base64和二进制流#

Java和C之间的Base64和二进制流#,java,c#,scala,base64,Java,C#,Scala,Base64,我觉得答案很明显,但假设我有以下C# Java中的以下内容(好的,是Scala,但使用Java库): 我得到了完全不同的64进制字符串。他们在这里有什么不同?我需要Java输出与.NET输出匹配。我假设这是某种字节排序问题,但我没有运气使用ByteBuffer来纠正这个问题 爪哇: PczMzT3MzM0/GaAACZMZMQAAAAD3MZM0/GaAAQAAABRN8XZAAAAAAAAAAAAAAAAAAAAAAAAAQ== C#(带有未知=符号,因为我们出于某种原因将其切掉): zczM

我觉得答案很明显,但假设我有以下C#

Java中的以下内容(好的,是Scala,但使用Java库):

我得到了完全不同的64进制字符串。他们在这里有什么不同?我需要Java输出与.NET输出匹配。我假设这是某种字节排序问题,但我没有运气使用
ByteBuffer
来纠正这个问题

爪哇:

PczMzT3MzM0/GaAACZMZMQAAAAD3MZM0/GaAAQAAABRN8XZAAAAAAAAAAAAAAAAAAAAAAAAAQ==

C#(带有未知=符号,因为我们出于某种原因将其切掉):

zczMPc3MzD0AAIA/ZCZMPQAAAAAAAAAM3MZD0AAIA/AFPFN1EBAAAAAAAAAAAAAAAAAA

我真的觉得好像是字节排序,这就是为什么我尝试在Java代码order方法中使用
ByteBuffer
来更改排序,但没有成功

为了进一步澄清,Java代码在x86_64 CentOS Java 7上运行,.NET在x86_64 Windows Server 2008.NET 4上运行。这些值来自Protobuf对象,因此我认为它们应该是非常跨平台的。从数字上讲,无论我输入了什么,数据都是相同和一致的,至少当我至少写这三种数据类型时。唯一显著的区别是Java中缺少无符号类型,可能存在二进制表示的差异,这是我最初试图解决的问题,但我似乎无法解决


正如我所说。使用其他格式不是一个选项。我需要从java编写二进制数据,然后对base 64进行编码,以得到与.NET相同的结果。序列化选项不是选项。一定是这样。我需要一个资源,将有助于把这一切结合起来,无论这意味着字节数据的二进制操作与否。我需要对数据类型进行一些解释,因为我已经进行了大量搜索,但没有找到一个资源来解释如何做到这一点或真正的区别是什么,因此我可以实现我决定在这里提出的解决方案。

不同的平台有不同的二进制表示。如果要匹配base64字符串,应该使用json或xml序列化。提供跨平台的Json或xml


编辑:别误会我:Base64是标准的编码算法。它为相同的数据提供相同的输出。我的意思是字节数组可能不同。

不同的平台有不同的二进制表示。如果要匹配base64字符串,应该使用json或xml序列化。提供跨平台的Json或xml


编辑:别误会我:Base64是标准的编码算法。它为相同的数据提供相同的输出。我的意思是字节数组可能不同。

如何实现跨平台二进制通信:

  • 定义精确的字节格式
  • 在每个平台上实现
通常,您可以使用现成的协议来简化这两个步骤,该协议接近您的需要(如),并且在您感兴趣的一个或所有平台上都受支持

请注意,给定语言/框架中的基本二进制序列化类型通常严格以该语言/框架(通常是特定版本)为目标,因为它经常提供速度/大小优势,并且没有关于“二进制对象表示”的公认标准

另一种方法是使用定义良好的文本格式,如其他答案中建议的JSON/XML

二进制格式之间可能存在的一些技术差异:

  • 整数类型的序列化可能因字节顺序/可能的替代表示(如.Net中的压缩int)而不同
  • 布尔类型和枚举类型的大小可能不同
  • 数组/字符串可以使用不同的类型来表示长度
  • 填充可以由一些二进制表示添加
  • 字符串可以是Utf8、Utf-16或任何其他指定/未指定的编码(带或不带尾随0)

如何实现跨平台二进制通信:

  • 定义精确的字节格式
  • 在每个平台上实现
通常,您可以使用现成的协议来简化这两个步骤,该协议接近您的需要(如),并且在您感兴趣的一个或所有平台上都受支持

请注意,给定语言/框架中的基本二进制序列化类型通常严格以该语言/框架(通常是特定版本)为目标,因为它经常提供速度/大小优势,并且没有关于“二进制对象表示”的公认标准

另一种方法是使用定义良好的文本格式,如其他答案中建议的JSON/XML

二进制格式之间可能存在的一些技术差异:

  • 整数类型的序列化可能因字节顺序/可能的替代表示(如.Net中的压缩int)而不同
  • 布尔类型和枚举类型的大小可能不同
  • 数组/字符串可以使用不同的类型来表示长度
  • 填充可以由一些二进制表示添加
  • 字符串可以是Utf8、Utf-16或任何其他指定/未指定的编码(带或不带尾随0)
主要问题是C#的
BinaryWriter
首先写入数据类型的低字节,而Java的
DataOutputStream
首先写入高字节

此外,当您写入.NET无符号整数时,它会写入4个字节。但是当你写一个Java
长的
时,它会写8个字节。这就是另一个区别

但是,一旦你理解了它们之间的差异,将它们匹配起来其实并不难。这里有两个代码片段,一个在C#中,另一个在Java中,它们编码相同的信息并输出相同的
Base64
-编码字符串。在我的例子中,我选择重写Java编写
float
s和
long
s的方式

.NET代码示例

static void Main(字符串[]args)
{
使用(MemoryStream ms=新MemoryStrea
using (MemoryStream ms = new MemoryStream())
{
    using (BinaryWriter bw = new BinaryWriter(ms))
    {
        // Write some floats, bytes, and uints
        // Convert.ToBase64String this stuff from ms.ToArray
    }
}
val byteStream = new ByteArrayOutputStream()
val outStream = new DataOutputStream(byteStream)
// Write some floats, bytes, and longs where the uints were using 
// writeFloat, writeByte, and writeLong. .NET has an overloaded 
// function that takes whatever. 
// Base64.getEncoder.encodeToString byteStream.toByteArray