C#非常实用的技巧

1、解压和压缩

.NET Framework 4.5以上版本:

string zipFilePath = @"C:\path\to\file.zip";
        string destFolder = @"C:\path\to\destination\folder";

        using (var archive = ZipFile.OpenRead(zipFilePath))
        {
            foreach (var entry in archive.Entries)
            {
                // 如果是文件,则解压到指定目录
                if (!entry.FullName.EndsWith("/"))
                {
                    string destinationPath = Path.Combine(destFolder, entry.FullName);
                    entry.ExtractToFile(destinationPath, true);
                }
                // 如果是文件夹,则创建对应目录
                else
                {
                    Directory.CreateDirectory(Path.Combine(destFolder, entry.FullName));
                }
            }
        }

.NET Framework 4以下

虽然微软的net提供了很多解压和压缩的程序,但是如果你的系统是net Framework4,那上面的代码就用不了了,此时需要借用7za.exe

1.0 C# 解压文件

//放置7z的路径
            string Zip7FileName = Path.Combine("D:\\Project", "7za.exe");
            var tarArgs = string.Format("x \"{0}\" -o\"{1}\" -y", "待解压路径", "输出路径");
            using (var process = new Process())
            {
                process.StartInfo.FileName = Zip7FileName;
                process.StartInfo.Arguments = tarArgs;
                process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
                process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
                process.Start();
                process.WaitForExit();
            }

解压解释:

var tarArgs = string.Format("x \"{0}\" -o\"{1}\" -y", "待解压路径", "输出路径");

-y 参数表示 "yes to all",即自动回答 "yes",也就是在出现任何提示时都自动选择 "是"。这意味着 7z 命令行工具不会询问用户是否覆盖已有的文件、创建缺失的目录等等,而是直接按照默认行为执行。

例如,在以下语句中 -y 参数告诉 7z 命令行工具在解压缩文件时自动覆盖目标文件夹中已有的同名文件。

 
 

csharpCopy Code

var tarArgs = string.Format("x \"{0}\" -o\"{1}\" -y", "待解压路径", "输出路径");

-o 参数表示 "output directory",即指定解压缩后的文件输出目录。在 7z 命令行工具中,可以使用 -o 参数来指定输出目录的路径。例如,在以上语句中,-o"{1}" 参数将解压缩后的文件输出到名为 importzipedFolder 的目录中。

需要注意的是,7z 命令行工具只能解压缩一些特定的文件格式,例如.zip, .tar, .gz, .bz2 等等。如果需要解压缩其它类型的文件,可能需要使用相应的解压缩工具,并根据相应工具的使用方法来编写代码。

1.1 C# 压缩文件

//选择保存压缩包的的位置(此处以C:\Program Files (x86)\001.tar为例)
            string zipFilePath = "C:\Program Files (x86)\001.tar";
            StringBuilder tarArgs = new StringBuilder($"a -ttar \"{zipFilePath}\"");
            //需要压缩的文件夹
            DirectoryInfo dirInfo = new DirectoryInfo(Path.Combine(exportzipedFolder));
            foreach (var subDir in dirInfo.GetDirectories())
            {
                tarArgs.Append(" \"").Append(subDir.FullName).Append("\"");
            }
            using (var process = new Process())
            {
                process.StartInfo.FileName = Zip7FileName;
                process.StartInfo.Arguments = tarArgs.ToString();
                process.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
                process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.Start();
                process.WaitForExit();
            }
            if (Directory.Exists(exportzipedFolder))
            {
                Directory.Delete(exportzipedFolder, true);
            }

2 按位读取二进制

2.0 C#读取二进制

string filePath = "C:\Program Files (x86)\001.bin";
            using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                using (var reader = new BinaryReader(fs, Encoding.Default))
                {
                    //此处需要知道,需要读取多少位、用什么类型读取
                    var readType =Type;
                    object countent = new object();
                    switch (readType)
                    {
                        case Hmi.DataType.UInt16:
                            countent = reader.ReadUInt16();
                            break;
                        case Hmi.DataType.Int16:
                            countent = reader.ReadInt16();
                            break;
                        case Hmi.DataType.UInt32:
                            countent = reader.ReadUInt32();
                            break;
                        case Hmi.DataType.Int32:
                            countent = reader.ReadInt32();
                            break;
                        case Hmi.DataType.BCD16:
                            countent = reader.ReadUInt16();
                            break;
                        case Hmi.DataType.BCD32:
                            countent = reader.ReadInt32();
                            break;
                        case Hmi.DataType.Single:
                            countent = reader.ReadSingle();
                            break;
                        case Hmi.DataType.Double:
                            countent = reader.ReadDouble();
                            break;
                        case Hmi.DataType.String:
                            byte[] data = new byte[recipeDataType[i].StringLength];
                            int bytesRead = reader.Read(data, 0, data.Length);
                            string result = Encoding.Default.GetString(data, 0, bytesRead);
                            int byteCount = Encoding.Default.GetByteCount(result);
                            fs.Seek(byteCount, SeekOrigin.Current);
                            string str = string.Join("", result).TrimEnd('\0');
                            countent = str;
                            break;
                        case Hmi.DataType.Hex16:
                            countent = reader.ReadUInt16();
                            break;
                        case Hmi.DataType.Hex32:
                            countent = reader.ReadUInt16();
                            break;
                        case Hmi.DataType.Binary16:
                            countent = reader.ReadUInt16();
                            break;
                        case Hmi.DataType.Binary32:
                            countent = reader.ReadUInt16();
                            break;
                        case Hmi.DataType.UInt64:
                            countent = reader.ReadUInt64();
                            break;
                        case Hmi.DataType.Int64:
                            countent = reader.ReadInt64();
                            break;
                        case Hmi.DataType.Bool:
                            countent = reader.ReadInt16();
                            break;
                        default:
                            break;
                    }

                }
            }

 代码解释:读取二进制的时候,需要注意中文的读取方式,即类型中的string类型,如果需要读取18个字节,但是中文只有三个(UTF8编码中,中文占用3个字节,用Encoding.Default读取,默认使用的是GB2312编码,一个中文占用2个字节,ASCII码中一个中文也是占用2个字节)按照GB2312读取,实际只能读取到6个字节,此时18个字节是浪费掉的,此时需要使用调用fs.Seek(byteCount, SeekOrigin.Current);将文件流的当前位置移动指定的字节数;读取二进制还需要额外注意的类似的bool类型,bool类型在编程语言中是True和False,但是在二进制下只有1和0

2.0 C#写二进制

 string filePath = "C:\Program Files (x86)\001.bin";
            using (FileStream fileStream = new FileStream(filePath, FileMode.Create))
            {
                using (BinaryWriter writer = new BinaryWriter(fileStream, Encoding.Default))
                {
                    string content =String.Empty;
                    //此处需要知道,需要读取多少位、用什么类型读取
                    var readType = Type;
                    switch (readType)
                    {
                        case DataType.UInt16:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.Int16:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.UInt32:
                            writer.Write(Convert.ToUInt32(content));
                            break;
                        case DataType.Int32:
                            writer.Write(Convert.ToInt32(content));
                            break;
                        case DataType.BCD16:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.BCD32:
                            writer.Write(Convert.ToInt32(content));
                            break;
                        case DataType.Single:
                            writer.Write(Convert.ToSingle(content));
                            break;
                        case DataType.Double:
                            writer.Write(Convert.ToDouble(content));
                            break;
                        case DataType.String:
                            //string类型需要处理需要读取多少位
                            int byteCount =100;
                            byte[] buffer = Encoding.Default.GetBytes(content);
                            if (buffer.Length < byteCount)
                            {
                                byte[] paddedBytes = new byte[byteCount];
                                Buffer.BlockCopy(buffer, 0, paddedBytes, 0, buffer.Length);
                                buffer = paddedBytes;
                            }
                            writer.Write(buffer, 0, byteCount);
                            fileStream.Seek(byteCount, SeekOrigin.Current);
                            break;
                        case DataType.Hex16:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.Hex32:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.Binary16:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.Binary32:
                            writer.Write(Convert.ToUInt16(content));
                            break;
                        case DataType.UInt64:
                            writer.Write(Convert.ToUInt64(content));
                            break;
                        case DataType.Int64:
                            writer.Write(Convert.ToInt64(content));
                            break;
                        case DataType.Bool:
                            writer.Write(Convert.ToInt16(content));
                            break;
                        default:
                            break;
                    }
                }
            }

 和读二进制类型,写二进制依旧主要注意编码方式、读取的字节类型。以上代码能帮助我们读取二进制,但是请注意,我们读取的仅仅是某些位的数据,实际的二进制是长这样的:

 实际上,我们上面代码,仅仅读取了二进制文件39,用UTF-7(推荐使用UTF-7)编码GB2123读取出来的是57,没错,这么多00 01 02加那么多代码仅读取了一个57,后面的怎么读,可能需要根据实际情况进行考虑。

3、MQTT发布订阅

using System;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;

public class MqttClient
{
    private IMqttClient mqttClient;

    public async Task ConnectAsync(string brokerIp, int brokerPort, string username, string password)
    {
        var factory = new MqttFactory();
        mqttClient = factory.CreateMqttClient();

        var options = new MqttClientOptionsBuilder()
            .WithTcpServer(brokerIp, brokerPort)
            .WithCredentials(username, password)
            .WithClientId("mqtt-client")
            .WithCleanSession()
            .Build();

        await mqttClient.ConnectAsync(options);
    }

    public void Disconnect()
    {
        if (mqttClient != null && mqttClient.IsConnected)
        {
            mqttClient.DisconnectAsync().Wait();
            mqttClient.Dispose();
            mqttClient = null;
        }
    }

    public async Task PublishAsync(string topic, string payload)
    {
        if (mqttClient == null || !mqttClient.IsConnected)
        {
            throw new InvalidOperationException("MQTT client is not connected.");
        }

        var message = new MqttApplicationMessageBuilder()
            .WithTopic(topic)
            .WithPayload(payload)
            .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
            .Build();

        await mqttClient.PublishAsync(message);
    }

    public async Task SubscribeAsync(string topic, Action<MqttApplicationMessageReceivedEventArgs> handler)
    {
        if (mqttClient == null || !mqttClient.IsConnected)
        {
            throw new InvalidOperationException("MQTT client is not connected.");
        }

        await mqttClient.SubscribeAsync(new TopicFilterBuilder()
            .WithTopic(topic)
            .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
            .Build());

        mqttClient.UseApplicationMessageReceivedHandler(handler);
    }

    public async Task UnsubscribeAsync(string topic)
    {
        if (mqttClient == null || !mqttClient.IsConnected)
        {
            throw new InvalidOperationException("MQTT client is not connected.");
        }

        await mqttClient.UnsubscribeAsync(topic);
    }
}

 低版本可能需要做一个兼容:
 

 private void Subscribe_ClickAsync(object sender, RoutedEventArgs e)
        {
            try
            {
                if (mqttClient == null || !mqttClient.IsConnected)
                {
                    throw new InvalidOperationException("MQTT client is not connected.");
                }
                mqttClient.SubscribeAsync(new MqttTopicFilterBuilder()
                   .WithTopic(txt_topic.Text)
                   .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
                   .Build());
                mqttClient.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceivedAsync1;
            }
            catch (Exception ex)
            {
                MessageBox.Show("系统异常:" + ex.Message);
            }
        }

        StringBuilder StringBuilder = new StringBuilder();
        private async Task MqttClient_ApplicationMessageReceivedAsync1(MqttApplicationMessageReceivedEventArgs arg)
        {
            try
            {
                this.Dispatcher.Invoke(new Action(delegate
                {
                    byte[] buffer = arg.ApplicationMessage.Payload;
                    string result = Encoding.Default.GetString(buffer, 0, buffer.Length);
                    StringBuilder.Append($"接受到:{result}\n");
                    txt_read.Text = StringBuilder.ToString();
                }));
               
            }
            catch (Exception ex)
            {
                MessageBox.Show("系统异常:" + ex.Message);
            }
        }

        private void Publish_ClickAsync(object sender, RoutedEventArgs e)
        {
            try
            {
                if (mqttClient == null || !mqttClient.IsConnected)
                {
                    throw new InvalidOperationException("MQTT client is not connected.");
                }
                byte[] payload = Encoding.Default.GetBytes(txt_writ.Text);

                var message = new MqttApplicationMessageBuilder()
                    .WithTopic(txt_topic.Text)
                    .WithPayload(payload)
                    .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
                    .Build();
                mqttClient.PublishAsync(message);
                txt_read.Text = StringBuilder.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show("系统异常:" + ex.Message);
            }
        }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值