【问题标题】:ReadInt16 in C# returns something different than what writeShort in Java wroteC# 中的 ReadInt16 返回的内容与 Java 中的 writeShort 不同
【发布时间】:2012-08-18 08:50:55
【问题描述】:

我正在使用 Java 中的以下代码编写文件的简短内容:

RandomAccessFile file = new RandomAccessFile("C:\\Users\\PC\\Desktop\\myFile.bin", "rw");
file.writeShort(11734);
file.close();

当我用 Java 读回它时,我得到了相同的 (11734) 数字。但是,当我使用以下代码读取 C# 中的数字时:

string p = "C:\\Users\\PC\\Desktop\\myFile.bin";
short s = new BinaryReader(File.OpenRead(p)).ReadInt16();

变量s包含-10707

这怎么会发生,有没有办法检索我在 Java 中用 C# 写入文件的数字?

【问题讨论】:

    标签: c# java short


    【解决方案1】:

    BigEndian/LittleEndian 问题。见下文

    byte[] b = BitConverter.GetBytes((short)11734);
    var s = BitConverter.ToInt16(new byte[] {b[1],b[0] }, 0);
    

    s 将是 -10707

    您可以使用IPAddress.HostToNetworkOrder 将一种形式转换为另一种形式。

    var sh1 = IPAddress.HostToNetworkOrder((short)11734); //-10707
    var sh2 = IPAddress.HostToNetworkOrder((short)-10707); //11734
    

    你也可以创建你自己的 BinaryReader

    public class MyBinaryReader : BinaryReader
    {
        public MyBinaryReader(Stream s)  : base(s)
        {
        }
    
        public override short ReadInt16()
        {
            return IPAddress.HostToNetworkOrder(base.ReadInt16());
        }
    }
    

    【讨论】:

    • 感谢您的回答,我将创建自己的 BinaryReader!
    【解决方案2】:

    正如其他人所说,这是一个字节顺序问题。

    我的MiscUtil 库包括EndianBinaryReaderEndianBitConverter,它们让您可以使用熟悉的API,但可以灵活地指定字节序:

    using System;
    using System.IO;
    using MiscUtil.Conversion;
    using MiscUtil.IO;
    
    static class Test
    {
        static void Main()
        {
            using (var stream = File.OpenRead("myfile.bin"))
            {
                var converter = new BigEndianBitConverter();
                var reader = new EndianBinaryReader(converter, stream);
                Console.WriteLine(reader.ReadInt16());
            }
        } 
    }
    

    【讨论】:

    • 感谢您的图书馆建议和样本,非常有用!
    【解决方案3】:

    请注意,在 Java 中,您还可以选择使用 ByteBuffer.allocate(size).order(LITTLE_ENDIAN).asShortBuffer()

    【讨论】:

      【解决方案4】:

      您的字节顺序错误

       11734 = 2DD6
      -10707 = D62D
      

      http://en.wikipedia.org/wiki/Endianness

      【讨论】:

        【解决方案5】:

        Java 在写出 short、int 和 long 时总是使用网络顺序(又名 big-endian)。我的猜测是 C# 读取它是 little-endian。

        【讨论】:

        • “默认情况下?”的答案不,没有办法覆盖该行为,尽管在每次调用时都翻转读取器和写入器可能是个好主意。
        • @JonHanna 最大的问题是:C#(或 CLR)是否指定它应该是 little-endian,还是依赖于平台(例如,当 Mono 实现在 big-字节序平台)?在 Java 规范中,他们明确选择了网络顺序。
        • 它被指定为 little-endian。是的,被指定为依赖于实现的事情是可怕的,尤其是当一个 impl 可能会在 BE 上使用 LE 以接近人们除了,另一个不会,而且更难知道什么是正确的;如果我不是那么低,以至于我自己构建 IP 数据包,我希望规范选择一个订单并记录它,所以虽然在这种情况下必须翻转对 OP 来说是一个麻烦,至少他们知道他们总是有翻转。
        猜你喜欢
        • 2017-09-14
        • 2017-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-07
        • 2015-09-06
        • 1970-01-01
        相关资源
        最近更新 更多