C# 对象、文件与二进制串(byte数组)之间的转换

1.关于本文

在使用C#下的TCP(类TcpClient)、UDP(类UdpClient)协议传输信息时,都需要将信息转换为byte类型的数组进行发送。本文实现了两种object与byte数组的转换和一种文件与byte数组转换的方式。基础类型的数据,可以用BitConverter类中的函数进行转换。

2.object与byte[]的相互转换:使用IFormatter的Serialize和Deserialize进行序列化与反序列化

实现这个功能,需要先引用三个命名空间:System.IO、System.Runtime.Serialization、System.Runtime.Serialization.Formatters.Binary;

/// <summary>
/// 工具类:对象与二进制流间的转换
/// </summary>
class ByteConvertHelper
{
    /// <summary>
    /// 将对象转换为byte数组
    /// </summary>
    /// <param name="obj">被转换对象</param>
    /// <returns>转换后byte数组</returns>
    public static byte[] Object2Bytes(object obj)
    {
        byte[] buff;
        using (MemoryStream ms = new MemoryStream())
        {
            IFormatter iFormatter = new BinaryFormatter();
            iFormatter.Serialize(ms, obj);
            buff = ms.GetBuffer();
        }
        return buff;
    }

    /// <summary>
    /// 将byte数组转换成对象
    /// </summary>
    /// <param name="buff">被转换byte数组</param>
    /// <returns>转换完成后的对象</returns>
    public static object Bytes2Object(byte[] buff)
    {
        object obj;
        using (MemoryStream ms = new MemoryStream(buff))
        {
            IFormatter iFormatter = new BinaryFormatter();
            obj = iFormatter.Deserialize(ms);
        }
        return obj;
    }
}

调用示例:

假设有一个添加了Serializable特性的结构:

/// <summary>
/// 测试结构
/// </summary>
[Serializable]
struct TestStructure
{
    public string A; //变量A
    public char B;   //变量B
    public int C;    //变量C

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="paraA"></param>
    /// <param name="paraB"></param>
    /// <param name="paraC"></param>
    public TestStructure(string paraA, char paraB, int paraC)
    {
        this.A = paraA;
        this.B = paraB;
        this.C = paraC;
    }

    /// <summary>
    /// 输出本结构中内容
    /// </summary>
    /// <returns></returns>
    public string DisplayInfo()
    {
        return string.Format("A:{0};B:{1};C:{2}", this.A, this.B, this.C);
    }
}

那么调用下面的代码可以完成这个结构的转换

static void Main(string[] args)
{
    TestStructure tsA = new TestStructure("1234", ‘5‘, 6);
    byte[] bytTemp = ByteConvertHelper.Object2Bytes(tsA);
    Console.WriteLine("数组长度:" + bytTemp.Length);
    TestStructure tsB = (TestStructure)ByteConvertHelper.Bytes2Object(bytTemp);
    Console.WriteLine(tsB.DisplayInfo());

    Console.ReadLine();
}

输出为:

需要注意的是,用这个方式进行结构与byte数组间的转换,结构或类必须有Serializable特性。否则会有异常(SerializationException):“程序集 "XXX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 中的类型 "XXX.XXX" 未标记为可序列化”

另外,这个方式生成的byte数组长度较大

3.使用Marshal类的StructureToPtr与PtrToStructure函数对object与byte数组进行转换

实现这个功能,需要先引用命名空间:System.Runtime.InteropServices

/// <summary>
/// 工具类:对象与二进制流间的转换
/// </summary>
class ByteConvertHelper
{
    /// <summary>
    /// 将对象转换为byte数组
    /// </summary>
    /// <param name="obj">被转换对象</param>
    /// <returns>转换后byte数组</returns>
    public static byte[] Object2Bytes(object obj)
    {
        byte[] buff = new byte[Marshal.SizeOf(obj)];
        IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);
        Marshal.StructureToPtr(obj, ptr, true);
        return buff;
    }

    /// <summary>
    /// 将byte数组转换成对象
    /// </summary>
    /// <param name="buff">被转换byte数组</param>
    /// <param name="typ">转换成的类名</param>
    /// <returns>转换完成后的对象</returns>
    public static object Bytes2Object(byte[] buff, Type typ)
    {
        IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);
        return Marshal.PtrToStructure(ptr, typ);
    }
}

调用示例:

现有结构如下(就是比上面示例中的结构少了特性Serializable):

/// <summary>
/// 测试结构
/// </summary>
struct TestStructure
{
    public string A; //变量A
    public char B;   //变量B
    public int C;    //变量C

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="paraA"></param>
    /// <param name="paraB"></param>
    /// <param name="paraC"></param>
    public TestStructure(string paraA, char paraB, int paraC)
    {
        this.A = paraA;
        this.B = paraB;
        this.C = paraC;
    }

    /// <summary>
    /// 输出本结构中内容
    /// </summary>
    /// <returns></returns>
    public string DisplayInfo()
    {
        return string.Format("A:{0};B:{1};C:{2}", this.A, this.B, this.C);
    }
}

调用下面的代码可以完成转换:

static void Main(string[] args)
{
    TestStructure tsA = new TestStructure("1234", ‘5‘, 6);
    byte[] bytTemp = ByteConvertHelper.Object2Bytes(tsA);
    Console.WriteLine("数组长度:" + bytTemp.Length);
    TestStructure tsB = (TestStructure)ByteConvertHelper.Bytes2Object(
        bytTemp, Type.GetType("ByteConverter2.TestStructure"));
    Console.WriteLine(tsB.DisplayInfo());

    Console.ReadLine();
}

运行示例:

可以看到,数组长度仅为12,比上面示例中转换的byte[]数组短了非常多,更加节省空间

3.使用FileStream将文件与byte数组相互转换

实现这个功能,需要先引用命名空间:System.IO

/// <summary>
/// 工具类:文件与二进制流间的转换
/// </summary>
class FileBinaryConvertHelper
{
    /// <summary>
    /// 将文件转换为byte数组
    /// </summary>
    /// <param name="path">文件地址</param>
    /// <returns>转换后的byte数组</returns>
    public static byte[] File2Bytes(string path)
    {
        if(!File.Exists(path))
        {
            return new byte[0];
        }

        FileInfo fi = new FileInfo(path);
        byte[] buff = new byte[fi.Length];

        FileStream fs = fi.OpenRead();
        fs.Read(buff, 0, Convert.ToInt32(fs.Length));
        fs.Close();

        return buff;
    }

    /// <summary>
    /// 将byte数组转换为文件并保存到指定地址
    /// </summary>
    /// <param name="buff">byte数组</param>
    /// <param name="savepath">保存地址</param>
    public static void Bytes2File(byte[] buff, string savepath)
    {
        if (File.Exists(savepath))
        {
            File.Delete(savepath);
        }

        FileStream fs = new FileStream(savepath, FileMode.CreateNew);
        BinaryWriter bw = new BinaryWriter(fs);
        bw.Write(buff, 0, buff.Length);
        bw.Close();
        fs.Close();
    }
}

假设有文件test.txt,调用下面代码可以将test.txt写到byte数组中,并将这个byte数组的内容写入到文件output.txt里

static void Main(string[] args)
{
    byte[] bytTemp = FileBinaryConvertHelper.File2Bytes("test.txt");
    Console.WriteLine("数组长度:" + bytTemp.Length);
    FileBinaryConvertHelper.Bytes2File(bytTemp, "output.txt");
    Console.WriteLine("输出完成");

    Console.ReadLine();
}

运行结果:

END

时间: 2024-10-15 23:52:47

C# 对象、文件与二进制串(byte数组)之间的转换的相关文章

InputStream,BufferedImage与byte数组之间的转换

需要获取网络的一张图片,但是某种需要,要把获取的这段流输入换为BufferedImage流,有的地方还需要转换为byte[]. 获得图片地址,获得了一个图片输入流,例如:    Url img = new  URL(url);   InputStream in = img.openStream(); 接着把输入流转为BufferedImage:    JPEGImageDecoder decoderFile = JPEGCodec.createJPEGDecoder(in);   Buffere

对文件、字符串和byte数组进行MD5加密

近来借助网络研究了一下MD5对文件的加密,顺便也总结一下对字符串和byte数组的加密,现贴出代码: import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.security.MessageDigest; import java

可序列化对象和byte[]数组之间的互转

/// <summary> /// 将可序列化对象转成Byte数组 /// </summary> /// <param name="obj">对象(对象不能为空)</param> /// <returns>返回相关数组</returns> protected static byte[] ObjectToByteArray<T>(T obj) where T : ISerializable { if (o

JAVA关于byte数组与String转换的问题

1 public class ToString{ 2 public static void main(String[] args){ 3 String aa = "hellow"; 4 byte[] bb = aa.getBytes(); 5 byte[] cc = aa.getBytes(); 6 7 System.out.println(aa); 8 System.out.println(bb.toString()); 9 System.out.println(cc.toStrin

C#语言的Image和byte数组的互相转换

/// <summary> /// 字节数组转换为图片 /// </summary> /// <param name="buffer">字节数组</param> /// <returns>图片</returns> public Image BytesToImage(Byte[] buffer) { var ms = new MemoryStream(buffer, 0, buffer.Length); var bf

C# 16进制与字符串、字节数组之间的转换

1.请问c#中如何将十进制数的字符串转化成十六进制数的字符串 //十进制转二进制 Console.WriteLine("十进制166的二进制表示: "+Convert.ToString(166, 2)); //十进制转八进制 Console.WriteLine("十进制166的八进制表示: "+Convert.ToString(166, 8)); //十进制转十六进制 Console.WriteLine("十进制166的十六进制表示: "+Con

C# 16进制与字符串、字节数组之间的转换(转)

1.请问c#中如何将十进制数的字符串转化成十六进制数的字符串   //十进制转二进制 Console.WriteLine("十进制166的二进制表示: "+Convert.ToString(166, 2)); //十进制转八进制 Console.WriteLine("十进制166的八进制表示: "+Convert.ToString(166, 8)); //十进制转十六进制 Console.WriteLine("十进制166的十六进制表示: "+C

C#串口通讯,16进制与字符串、字节数组之间的转换。

1.将十进制数的字符串转化成十六进制数的字符串 //十进制转二进制Console.WriteLine("十进制166的二进制表示: "+Convert.ToString(166, 2));//十进制转八进制Console.WriteLine("十进制166的八进制表示: "+Convert.ToString(166, 8));//十进制转十六进制Console.WriteLine("十进制166的十六进制表示: "+Convert.ToStrin

JAVA中list,set,数组之间的转换详解

JAVA的list,set,数组之间的转换,主要是使用Apache Jakarta Commons Collections,具体的方法如下:import org.apache.commons.collections.CollectionUtils; String[] strArray = {"aaa", "bbb", "ccc"};    List strList = new ArrayList();    Set strSet = new Ha