C# 使用c将字节从结构写入文件#

C# 使用c将字节从结构写入文件#,c#,struct,byte,filestream,C#,Struct,Byte,Filestream,大家早上好 我遇到了一个新问题。我必须写下一个数据,它来自我在系统中声明的结构 我创建的结构只有两个字段,我稍后会将其转换为字节 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] public struct MyStructData { public short Id; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] pu

大家早上好

我遇到了一个新问题。我必须写下一个数据,它来自我在系统中声明的结构

我创建的结构只有两个字段,我稍后会将其转换为字节

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct MyStructData
{
    public short Id;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string Name;
}
我使用以下代码以字节为单位转换此结构:

private byte[] getBytes(MyStructData aux)
{
    int length = Marshal.SizeOf(aux);
    IntPtr ptr = Marshal.AllocHGlobal(length);
    byte[] myBuffer = new byte[length];

    Marshal.StructureToPtr(aux, ptr, true);
    Marshal.Copy(ptr, myBuffer, 0, length);
    Marshal.FreeHGlobal(ptr);

    return myBuffer;
}
此函数用于转换MyStructData类型元素列表结构中的每个元素,其中我有所有要发送到另一台机器的寄存器,我使用粘贴在下面的代码执行此操作:

string saveToFilePath = "D:\\" + filename;
Stream myStream = myFtpRequest.GetRequestStream();

using (FileStream myFileStream = new FileStream(saveToFilePath, FileMode.Create))
{
    foreach (MyStructData myData in myStructDataList)
    {
        int length = 2048;
        byte[] newBuffer = new byte[length];
        newBuffer = getBytes(myCust);

        int len = 0;
        int bytesRead = 0;

        myFileStream.Write(newBuffer, 0, len);
        bytesRead += len;
    }

    myFileStream.Close();
}
我的问题是,我看到我的新文件是空的,我不明白为什么它不能获取我的字节信息。我已经检查了列表中是否有数据,我还检查了字节转换函数是否工作正常,但我无法找到导致文件为空的原因

如果有人知道隧道尽头的光明,我将非常感谢你的帮助

编辑现在我有另一种方法将数据写入文件,效果很好:

using (Stream stream = new FileStream(saveToFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
    using (BinaryWriter writer = new BinaryWriter(stream, Encoding.Default))
    {
        // get all data
        foreach (MyStructData myData in myStructDataList)
        {
            byte[] newBuffer = getBytes(cd);
            writer.Write(newBuffer);
        }
    }
}

FileStream.Write
的第三个参数是要写入的字节数。它不应该是0

string saveToFilePath = "D:\\" + filename;
Stream myStream = myFtpRequest.GetRequestStream();

int bytesWritten = 0;
using (FileStream myFileStream = new FileStream(saveToFilePath, FileMode.Create))
{
    foreach (MyStructData myData in myStructDataList)
    {
        newBuffer = getBytes(myData);
        myFileStream.Write(newBuffer, 0, newBuffer.Length);
        bytesWritten += newBuffer.Length;
    }
}

我认为你不应该把数据写入这样的文件。对于这样的简单结构,最好使用

这里有一个例子。首先,您需要通过添加属性使
MyStructData
可序列化:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
[Serializable]
public struct MyStructData
{
    public short Id;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
    public string Name;
}
然后可以将这些结构的列表写入文件,如下所示:

List<MyStructData> data = new List<MyStructData>();

for (short i = 0; i < 100; ++i)
    data.Add(new MyStructData{Id = i, Name = i.ToString()});

string filename = "C:\\test\\test.data";

using (var file = File.OpenWrite(filename))
{
    var writer = new BinaryFormatter();
    writer.Serialize(file, data); // Writes the entire list.
}

[编辑]

我从未来开始注意到,
BinaryFormatter

BinaryFormatter类型很危险,不建议将其用于数据 处理。应用程序应尽快停止使用BinaryFormatter 可能,即使他们相信他们正在处理的数据是正确的 值得信赖的BinaryFormatter不安全,无法使其安全


NuGet提供了一种更好的现代二进制序列化格式。

当我在代码中写入第二行时,它会给我一个错误。它将myFileStream中的Write函数识别为void,因此它根本不返回任何int值。谢谢!!!这很好,现在我来解决我的下一个问题,所以我希望我不会打扰你所有这一切看起来很好。。。我不知道是否应该使用它,因为这是一个发送文件的测试,可能我必须将结构更改为更复杂的东西。@MarialvyMartínez
BinaryFormatter
可以处理相当复杂的事情。它不能处理与非托管资源(例如窗口句柄)相关的事情,但我认为您不会序列化这些资源。我只建议使用BinaryFormatter,因为它使用起来相当简单。为了更好地控制,可以使用XmlSerializer。无论哪种方式,您都不应该仅仅为了序列化而自行编组数据!封送处理实际上是将数据传递给非托管代码。我强烈建议您在做出决定之前阅读此内容:我可以说的一点是:使用封送处理进行序列化是非常错误的。我找到了另一种方法,但使用
BinaryWriter
,我现在尝试了它,而且效果也非常好。我有所保留,因为我在这里的某个地方读到,
BinaryFormatter
也有一些问题。但我认为之所以做出选择,是因为您可以接受:)要么使用BinaryFormatter,要么使用XmlSerializer(以及DataContacts)——后者是最“现代”的,但XmlSerializer会增加数据大小,因此您可能还需要压缩它。
using (var file = File.OpenRead(filename))
{
    var reader = new BinaryFormatter();
    data = (List<MyStructData>) reader.Deserialize(file); // Reads the entire list.
}

foreach (var item in data)
    Console.WriteLine("Id = {0}, Name = {1}", item.Id, item.Name);
[Serializable]
public struct MyStructData
{
    public short Id;
    public string Name;
}