2

私は、アイテムの検証を行うために C++ プログラムによって作成されたバイナリ ファイルからデータを読み取る C# CE アプリケーションを開発しています。

以下は、C++ プログラムのコーディングです。

 // File Name: Ean2an.bin which is created by struct 
    struct EAN2AN_TYPE 
    {
    __int64     ean:40;     // 5 bytes, up to 12 digits
    __int64     rec_no:24;  // 3 bytes rec no in the c_ItemMaster File, up to 16 million  records
    };

    // After bind data to struct, wil create the binary file
   bool CreateBin_EAN2AN_TYPE()
   {
    if(mn_RecordCount_EAN2AN_TYPE == 0) return false;

    FILE   *binfile;

    qsort(mc_EAN2AN_TYPE, mn_RecordCount_EAN2AN_TYPE, sizeof(struct EAN2AN_TYPE), qsort_EAN2AN_TYPE);
    try
    {
        binfile = fopen(ms_Path_EAN2AN_TYPE, "wb");
        fwrite(&mc_EAN2AN_TYPE, sizeof(struct EAN2AN_TYPE), mn_RecordCount_EAN2AN_TYPE, binfile);
    }
    catch(Exception ^ex)
    {
        TaskProgramLibrary::Message::ERR("Create EAN2AN_TYPE.bin fail!\r\n       " + ex->Message);
    }
    finally
    {
        fclose(binfile);

        mdw_FileSize_EAN2AN_TYPE = FileSize(ms_Path_EAN2AN_TYPE);
    }

    return true;
      }

バイナリ読み取り (位置に基づく) を使用してデータを読み取り、bitconverter を使用して int64 に変換するか、Marshal.PtrToStructure を使用してデータを読み取ろうとしましたが、返される値が正しくありません。次に、ファイルから 8 バイトではなく 5 バイトを読み取ろうとしましたが、値が正しく返されませんでした。

Below is the written C# coding
    //Struct created in C#
   [StructLayout(LayoutKind.Sequential)]
        public struct EAN2AN_TYPE
        {
            [MarshalAs(UnmanagedType.I8)]
            public Int64 ean;
            [MarshalAs(UnmanagedType.I8)]
            public Int64 rec_no;
        } 

    //The ways i tried to read in C#
    //1.Read Int64 by Binary 
    private void ReadByBinary()
         {
            using (BinaryReader b = new BinaryReader(_fs))
            {
                while (b.PeekChar() != 0)
                {
                    Int64 x = b.ReadInt64();
                    Console.WriteLine(x.ToString());

                }
            }

        }

   //2.Using Marshal to convert the Intptr to struct's field type
    private object ReadByMarshal(Type iType)
        {
            _oType = iType;// typeof(System.Int64);
            byte[] buffer = new byte[Marshal.SizeOf(_oType)];
            //byte[] buffer = new byte[5];

            object oReturn = null;

            try
            {
                _fs.Read(buffer, 0, buffer.Length);

                GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                oReturn = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), _oType);
                handle.Free();

                return oReturn;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


    //3. Use Binary and use bit converter to convert to Int64
     private void ReadByBinaryAndUseBitConverter()
        {
            using (BinaryReader b = new BinaryReader(_fs))
            {
                byte[] x = b.ReadBytes(8);
                Int64 y = BitConverter.ToInt64(x, 0);
                Console.WriteLine(y);

                byte[] x2 = b.ReadBytes(8);
                Int64 y2 = BitConverter.ToInt64(x2,0);
                Console.WriteLine(y2);
            }

        }


    //4. Use Marshal and convert to struct
    public EAN2AN_TYPE  GetStructValue()
        {

            byte[] buffer = new byte[Marshal.SizeOf(typeof(EAN2AN_TYPE)];

            EAN2AN_TYPE oReturn = new EAN2AN_TYPE();

            try
            {
                //if (EOF) return null;

                _fs.Read(buffer, 0, buffer.Length);
                GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
                IntPtr rawDataPtr = handle.AddrOfPinnedObject();

               oReturn = (EAN2AN_TYPE)Marshal.PtrToStructure(rawDataPtr, typeof(EAN2AN_TYPE));

                handle.Free();

                if (_fs.Position >= _fs.Length)
                    Close();

                return oReturn;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

編集:バイナリファイルのアップロード画像 ここに画像の説明を入力

編集:C# プログラムによって読み取られる最初の 8 バイトの値 ここに画像の説明を入力

エディタが表示するバイナリデータ ここに画像の説明を入力

誰でも何か考えがありますか?

前もって感謝します

4

3 に答える 3

3

eanは40ビットエンティティとして定義され、rec_no24ビットであるため、構造体全体が64ビットのみになります。の定義EAN2AN_TYPEは128ビットなので、明らかに問題が発生します。最初のコードを書いた人の正気に疑問を投げかけますが、あなたの仕事はそれを取り戻して使用することなので、あなたはあなたが扱っているもので遊んでいます。

編集:指定されたデータを使用し、ベンの苦情を考慮に入れるように更新されました

同じ結果を得るには2つの方法があります。1つは段階的に移動するため、もう少し理解しやすく、もう1つはより速く、「より正確」です。結果を検証するために、サンプルのEANデータを入力に入れました。

public struct EAN2AN_TYPE
{
    public long ean; // can hold 5 bytes
    public int rec_no; // can hold 3 bytes
}

byte[] incoming = new byte[] { 0x6F, 0x5D, 0x7C, 0xBA, 0xE3, 0x06, 0x07, 0x08 };

メモリコピー:

using(var stream = new MemoryStream(incoming))
using (var reader = new BinaryReader(stream))
{
    // I leave it to you to get to the data
    stream.Seek(0, SeekOrigin.Begin);

    // get the data, padded to where we need for endianness
    var ean_bytes = new byte[8];
    // read the first 5 bytes
    Buffer.BlockCopy(reader.ReadBytes(5), 0, ean_bytes, 0, 5);
    var rec_no_bytes = new byte[4];
    // read the last 3
    Buffer.BlockCopy(reader.ReadBytes(3), 0, rec_no_bytes, 0, 3);

    var ean2 = new EAN2AN_TYPE();

    // convert
    ean2.ean = BitConverter.ToInt64(ean_bytes, 0);
    ean2.rec_no = BitConverter.ToInt32(rec_no_bytes, 0);
}

ビットシフト:

using (var stream = new MemoryStream(incoming))
using (var reader = new BinaryReader(stream))
{
    // I leave it to you to get to the data
    stream.Seek(0, SeekOrigin.Begin);

    // get the data
    var data = BitConverter.ToUInt64(reader.ReadBytes(8), 0);
    var ean2 = new EAN2AN_TYPE();

    // shift into our data
    ean2.ean = (long)(data & ~0xFFFFFF0000000000);
    ean2.rec_no = (int)(data >> 40);
}

もちろんEAN2AN_TYPE、クラスを作成し、それを8バイトでフィードしてから、シフトシェナニガンを実行するプロパティアクセサーを使用することもできます。これが双方向である必要がある場合(つまり、Cアプリに送り返すためにこれらの構造体の1つにデータを入れる必要がある場合)にそれを行います。

于 2012-10-04T01:02:13.903 に答える
2

データのエンディアン (それが単語の場合) に問題がある可能性があります。データがビッグ エンディアン システムで書き込まれ、リトル エンディアンとして読み取られた場合、またはその逆の場合、このような問題が発生します。

もう 1 つの問題は、2 つのフィールドが実際には 1 つの 64 ビット値にパックされることです。Int64 を読み取ってから、ビット操作を使用して 2 つのフィールドを抽出する必要がある場合があります。あなたのコードはすべて、さまざまな方法で 2 つの Int64 値を読み取っているように見えます。

于 2012-10-04T00:39:02.460 に答える
1

お返事をありがとうございます..

最初の C++ コードはベンダーによって作成されます。C++コードを読んで理解するしかありません。私の理解では..バイナリファイルを作成してデータに書き込むだけです..コードからエンコード/変換部分を見つけることができません..

最初の ean(978086288751) をコードで手動で byte[] に変換しようとしました。byte[] は 111 93 124 186 227 0 0 0 です。これは、取得した結果とは異なります..

ctacke の推奨コードをテストしました。しかし、私はまだ正しいeanを取得できません..

以下はコーディングです..(バイナリファイルを読み取るためにファイルストリームに追加しました)

 using (FileStream fileStream = File.OpenRead(_File))
            {
                MemoryStream memStream = new MemoryStream();
                memStream.SetLength(fileStream.Length);
                fileStream.Read(memStream.GetBuffer(), 0, (int)fileStream.Length);

                using (BinaryReader reader = new BinaryReader(memStream))
                {
                    //stream.SetLength(_fs);               
                    // I leave it to you to get to the data
                    memStream.Seek(0, SeekOrigin.Begin);

                    // get the data, padded to where we need for endianness
                    byte[] ean_bytes = new byte[8];
                    // if this is wrong - then change param 4 to '3' to align at the other end
                    Buffer.BlockCopy(reader.ReadBytes(8), 0, ean_bytes, 0, 8);
                    //byte[] rec_no_bytes = new byte[4];

                    byte[] rec_no_bytes = new byte[4];
                    // if this is wrong - then change param 4 to '1' to align at the other end
                    Buffer.BlockCopy(reader.ReadBytes(3), 0, rec_no_bytes, 0, 3);

                    EAN2AN_TYPE ean2 = new EAN2AN_TYPE();

                    // convert
                    ean2.ean = BitConverter.ToInt64(ean_bytes, 0);
                    ean2.rec_no = BitConverter.ToInt32(rec_no_bytes, 0);
                }

            }

//結果読み込み 5 バイト : 17 0 0 0 0 ean : 17

//に変更しました

   var ean_bytes = new byte[8];
    Buffer.BlockCopy(reader.ReadBytes(8), 0, ean_bytes, 0, 8);

結果読み取り 8 バイト:17 0 0 0 0 108 94 5 ean:386865365256241169

申し訳ありませんが、私はまだ新しいユーザーです..添付ファイルを投稿できません..私の解釈から理解していただければ幸いです。

于 2012-10-04T02:56:51.320 に答える