【问题标题】:Representing signed byte in an unsigned byte variable在无符号字节变量中表示有符号字节
【发布时间】:2014-12-06 18:37:43
【问题描述】:

如果这个问题的标题不清楚,我深表歉意,但我想不出用这么几句话来描述我的困境的最佳方式。

我正在编写一个 java 和 C# 之间的通信框架,使用套接字和逐字节传输信息。

我遇到了一个困扰我好几个小时的问题。正如你希望知道的那样。 java的字节基类型是有符号的,这意味着如果你用整数形式表示它,它可以存储-128到+127。然而,C# 使用无符号字节,这意味着它以整数形式存储 0-255。

这是我遇到问题的地方。如果需要将一些字节的信息从我的 c# 客户端发送到我的 java 服务器,我使用以下代码:

C#:

MemoryStream stream;

public void write(byte[] b, int off, int len) {
    stream.Write(b, off, len);
}

Java:

DataInputStream in;

public int read(byte[] b, int off, int len) throws IOException{
    in.read(b, off, len));
}

如您所见,这些代码段非常相似,在它们自己的语言中使用时会产生可预测的结果。但是,由于签名的不同,这些会产生不可用的数据。

也就是说,如果我从我的 c# 客户端向 java 服务器发送 255,我将在 java 服务器上收到 -1 的值。这是因为这两个值都由这 8 位表示:11111111

最好为了解决这个问题,我需要使用以下代码,使用sbyte,c# 的有符号字节。

C#:

MemoryStream stream;

public void write(sbyte[] b, int off, int len) {

    //Code to change sbyte into a byte but keeping it in the form in which java will understand

    stream.Write(b, off, len);
}

我基本上需要将 java 的有符号字节表示形式存储在无符号 C# 字节中,以便将该字节发送到服务器。我还需要反向执行此操作,以从我的 java 服务器接收到的字节中获取一个 sbyte。

我尝试了很多方法来做到这一点,但都没有成功。如果有人知道我该如何解决这个问题,我将不胜感激。

【问题讨论】:

    标签: java c# sockets byte


    【解决方案1】:

    除了停止将字节视为数字之外,您基本上不需要做任何事情。将它们视为 8 位,Java 和 C# 是相同的。您很少真的想将字节视为量级 - 它通常只是像图像这样的二进制数据,或者可能是编码文本。

    如果您想将字节 10100011 从 Java 发送到 C#,反之亦然,只需以最自然的方式进行即可。这些位将是正确的,即使当您将它们视为数字时字节值会有所不同。

    目前尚不完全清楚您实际尝试传播的数据是什么,但在 99.9% 的情况下,您可以将 byte[] 视为不透明的二进制数据,无需担心即可传输。

    如果您确实需要将字节视为量级,则需要计算出您想要的范围。处理 Java 范围更容易,因为 C# 可以通过 sbyte[]... @ 在 Java 端并用底部 8 位屏蔽它:

    byte b = ...;
    int unsigned = b & 0xff;
    

    如果您确实需要在 C# 上将 byte[] 视为 sbyte[] 或反之亦然,您可以使用一个小秘密:尽管 C# 不允许您在两者之间进行转换,但 CLR 可以。您需要做的就是通过转换对object 的引用来欺骗C# 编译器,使其认为它可能 是有效的——否则它认为它最清楚。所以这会毫无例外地执行:

    byte[] x = new byte[] { 255 };
    sbyte[] y = (sbyte[]) (object) x;
    Console.WriteLine(y[0]); // -1
    

    您可以以完全相同的方式向另一个方向转换。

    【讨论】:

    • 问题是我需要它们作为两端的正确数字,因为我使用这些数组来存储诸如整数之类的东西。
    • @LexWebb:除非这些实际上是 1 字节整数,否则您会使用 BinaryReaderDataInputStream 之类的东西——此时这些字节不再被视为有符号字节.请在有关您实际在做什么的问题中提供更多背景信息 - 因为我仍然怀疑您不需要担心签名。您更有可能需要担心多字节整数的字节顺序。我已经编辑了我的答案,以向您展示如何使用 sbyte[],如果您真的想要的话。
    • 我实际上是在尝试通过使用这些类的 Java 源代码的修改版本来复制 C# 中 DataInputStream 和输出流的行为。我这样做是因为我之前尝试将这两种语言的读者和作者结合起来并没有成功。
    • @LexWebb:我怀疑我的EndianBinaryReader 会免费为您提供DataInputStream 互操作性的很多行为——不可否认,不是修改后的UTF-8 部分。见pobox.com/~skeet/csharp/miscutil。但即使你想移植DataInputStream,我仍然会使用byte,但只需弄清楚DataInputStream 中的代码试图实现什么。我建议您尝试一下,如果这不起作用,请提出一个新问题,显示您的移植代码和一个简短但完整的程序来演示该问题。 byte/sbyte 这件事只是分散注意力,IMO。
    • 谢谢,我去看看。并感谢您的建议。
    猜你喜欢
    • 2014-06-22
    • 2011-10-21
    • 2017-10-01
    • 1970-01-01
    • 2015-01-12
    • 2013-07-19
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    相关资源
    最近更新 更多