C#开发合集

用C#轻松搞定m3u8视频下载与合并

嘿,程序员们!今天咱们来聊聊如何用C#写个小程序,轻松下载和合并m3u8视频文件。没错,就是那种分段的流媒体视频。准备好了吗?让我们开始吧!

准备工作

在动手之前,先确保你有以下工具:

  1. Visual Studio(或者你喜欢的任何C# IDE)
  2. FFmpeg(这个工具可别少了,确保它在你指定的路径下)

代码实现

下面的代码将帮助你完成这个任务。它的逻辑很简单:从数据库读取视频信息,下载视频分段,然后用FFmpeg合并成一个完整的mp4文件。

// 将以下代码粘贴到你的C#项目中
using System.Diagnostics;
namespace ConsoleApp1
{
    public class Demo
    {
        string RootPath = $"D:/Test/Demo";
        public async Task Main()
        {
            await InitFun();
            async Task InitFun()
            {
                // 从数据库读取数据
                List<dynamic> items = new List<dynamic>
                {
                    new
                    {
                        FlagName = "A",
                        Name="计时器 m3u8 ",
                        Url="http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8"
                    }
                };

                using (HttpClient client = new HttpClient())
                {
                    foreach (var item in items)
                    {
                        try
                        {
                            string flagName = item.FlagName; // 顶层目录
                            string name = item.Name;          // 子目录
                            string m3u8Url = item.Url;
                            // 创建文件夹结构
                            var date = DateTime.Now;
                            string rootPath = $"{RootPath}/{date.Year}/{date.Month}/{flagName}/";
                            // 创建顶层目录
                            if (!Directory.Exists(rootPath))
                            {
                                Directory.CreateDirectory(rootPath);
                            }

                            // 创建子目录
                            string subFolderPath = Path.Combine(rootPath, name);
                            string outputDirectory = Path.Combine(subFolderPath, "ts"); // "ts" 文件夹
                            string outputFilePath = Path.Combine(subFolderPath, $"{name}.mp4");

                            if (!Directory.Exists(outputDirectory))
                            {
                                Directory.CreateDirectory(outputDirectory);
                            }
                            // 检查 URL 是否为 MP4 文件
                            if (m3u8Url.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase))
                            {
                                // 直接下载 MP4 文件
                                Console.WriteLine($"Downloading MP4 directly from {m3u8Url}...");
                                byte[] mp4Data = await client.GetByteArrayAsync(m3u8Url);
                                await File.WriteAllBytesAsync(outputFilePath, mp4Data);
                                Console.WriteLine($"Downloaded MP4 file to {outputFilePath}.");
                            }
                            else
                            {
                                string m3u8Content = await client.GetStringAsync(m3u8Url);
                                string[] lines = m3u8Content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                                var downloadTasks = new List<Task>();
                                // 下载每个分段视频
                                foreach (var line in lines)
                                {
                                    if (line.EndsWith(".ts"))
                                    {
                                        string segmentUrl = line.StartsWith("http") ? line : new Uri(new Uri(m3u8Url), line).ToString();
                                        string segmentFilePath = Path.Combine(outputDirectory, Path.GetFileName(segmentUrl));

                                        // 启动下载任务
                                        downloadTasks.Add(Task.Run(async () =>
                                        {
                                            try
                                            {
                                                Console.WriteLine($"Downloading {segmentUrl}...");
                                                byte[] segmentData = await client.GetByteArrayAsync(segmentUrl);
                                                await File.WriteAllBytesAsync(segmentFilePath, segmentData);
                                            }
                                            catch
                                            {
                                            }
                                        }));
                                    }
                                }
                                // 等待所有下载任务完成
                                await Task.WhenAll(downloadTasks);
                                //合并
                                await MergeVideosWithFFmpeg(outputDirectory, outputFilePath);
                            }
                        }
                        catch
                        {
                            Console.WriteLine($"Downloading Fail");
                        }
                        finally
                        {

                        }

                    }
                }
            }
            return;
        }


        private async Task MergeVideosWithFFmpeg(string outputDirectory, string outputFilePath)
        {
            try
            {
                string ffmpegPath = @"D:\Bin\ffmpeg-master-latest-win64-gpl\bin\ffmpeg.exe"; // 确保FFmpeg在此路径下
                string concatFilePath = Path.Combine(outputDirectory, "concat.txt");

                // 创建合并文件
                using (StreamWriter writer = new StreamWriter(concatFilePath))
                {
                    foreach (var tsFile in Directory.GetFiles(outputDirectory, "*.ts"))
                    {
                        writer.WriteLine($"file '{tsFile}'");
                    }
                }

                // 执行FFmpeg合并命令
                var ffmpegArgs = $"-f concat -safe 0 -i \"{concatFilePath}\" -c copy \"{outputFilePath}\"";
                var processStartInfo = new System.Diagnostics.ProcessStartInfo
                {
                    FileName = ffmpegPath,
                    Arguments = ffmpegArgs,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

                using (var process = new Process { StartInfo = processStartInfo })
                {
                    try
                    {
                        process.Start();
                        // 异步读取输出和错误信息
                        var outputTask = process.StandardOutput.ReadToEndAsync();
                        var errorTask = process.StandardError.ReadToEndAsync();

                        // 等待进程退出,并设置超时
                        if (process.WaitForExit(60000 * 2)) // 设置超时为 60*2 秒
                        {
                            // 输出读取结果
                            string output = await outputTask;
                            string error = await errorTask;

                            if (process.ExitCode == 0)
                            {
                                Console.WriteLine($"Merge completed for {outputFilePath}.");
                            }
                            else
                            {
                                Console.WriteLine($"FFmpeg exited with code {process.ExitCode}. Error: {error}");
                            }
                        }
                        else
                        {
                            Console.WriteLine("FFmpeg process timed out.");
                        }
                        process.Kill(); // 杀死进程
                    }
                    finally
                    {
                        // 删除文件夹
                        if (Directory.Exists(outputDirectory))
                        {
                            Directory.Delete(outputDirectory, true);
                            Console.WriteLine($"Deleted directory {outputDirectory}.");
                        }
                    }
                }
            }
            catch
            {

            }
        }
    }

}

// 代码内容请参见上方给出的代码

步骤解析

  1. 创建C#控制台项目:打开Visual Studio,创建一个新的控制台应用程序。
  2. 粘贴代码:把上面的代码粘贴到 Program.cs 文件里。
  3. 配置路径:根据你的实际情况修改 RootPathffmpegPath 变量的值。
  4. 编译运行:编译并运行程序,看看效果!

注意事项

  • 确保引用了必要的命名空间,比如 System.Net.HttpSystem.IOSystem.Diagnostics
  • FFmpeg的路径一定要正确,确保工具安装无误。
    – FFmpeg教程(超级详细版)

运行结果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

总结

通过这个小程序,你不仅能下载m3u8视频,还能把它们合并成一个完整的mp4文件。是不是很简单?

用C#获取“掌上高考”学校信息

嘿,大家好!今天我们来聊聊如何用C#编写一个程序,从“掌上高考”平台获取学校信息。这个程序不仅能获取学校的基本信息,还能提取特色专业、校园设施、就业政策等信息。准备好了吗?让我们开始吧!

准备工作

在开始之前,请确保你已经安装了以下工具:

  1. Visual Studio(或者你喜欢的任何C# IDE)
  2. Newtonsoft.Json库(用于处理JSON数据)

你可以在NuGet包管理器中安装Newtonsoft.Json:

Install-Package Newtonsoft.Json

代码实现

下面是程序的主要代码。它会从指定的API获取学校信息,并将其输出到控制台。

// 将以下代码粘贴到你的C#项目中

using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Text.RegularExpressions;

namespace ConsoleApp1
{
    public class Main4
    {
        private readonly static string Root = "https://static-data.gaokao.cn";

        public async Task Main()
        {
            string[] strings = { "31" }; // 这里可以替换成需要查询的学校编码
            foreach (string item in strings)
            {
                await GetSchoolInfo(item);
            }
        }

        static async Task GetSchoolInfo(string schoolCode)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    string url = $"{Root}/www/2.0/school/{schoolCode}/info.json";

                    HttpResponseMessage response = await client.GetAsync(url);
                    if (response.IsSuccessStatusCode)
                    {
                        string json = await response.Content.ReadAsStringAsync();
                        JObject data = JObject.Parse(Regex.Unescape(json));

                        if (data != null)
                        {
                            var schoolInfo = JsonConvert.DeserializeObject<dynamic>(data["data"].ToString());
                            Console.WriteLine("高校名称: " + schoolInfo?.name);
                            Console.WriteLine("高校地址: " + schoolInfo?.address);
                            Console.WriteLine("校园面积: " + schoolInfo?.area + "亩");
                            Console.WriteLine("招办电话: " + schoolInfo?.phone);
                            Console.WriteLine("招生官网: " + schoolInfo?.site);
                            Console.WriteLine("校园官网: " + schoolInfo?.school_site);

                            var tag = $"{schoolInfo?.level_name},{schoolInfo?.school_nature_name},{schoolInfo?.dual_class_name},{(schoolInfo?.f985 == "1" ? "985工程" : "")},{(schoolInfo?.f211 == "1" ? "211工程" : "")}";
                            Console.WriteLine("学校等级特色标签: " + tag);

                            var specialName = await GetNationFeature(schoolCode);
                            Console.WriteLine("优势专业(特色专业): " + specialName);

                            var dormitoryInfo = await GetDormitory(schoolCode);
                            Console.WriteLine("住宿: " + dormitoryInfo.dormitory);
                            Console.WriteLine("食堂: " + dormitoryInfo.canteen);
                            Console.WriteLine("校园风光: " + dormitoryInfo.schoolImg);

                            var reportInfo = await GetReportName(schoolCode);
                            Console.WriteLine("就业报告: " + string.Join(',', reportInfo));

                            var gradeLine = await GetGradeLine(schoolCode);
                            Console.WriteLine("上一年 内蒙古本科一批分数: " + string.Join(',', gradeLine));

                            Console.WriteLine("========================\n");
                        }
                    }
                    else
                    {
                        Console.WriteLine("获取数据失败,状态码: " + response.StatusCode);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("发生异常: " + ex.Message);
            }
        }

        // 其他方法(GetNationFeature, GetDormitory, GetReportName, GetGradeLine)请按需粘贴
    }
}

其他方法

在上面的代码中,我们定义了一些辅助方法来获取特色专业、校园设施、就业政策和分数线。这些方法的实现逻辑与 GetSchoolInfo 类似,都是通过HTTP请求获取JSON数据并进行解析。

注意事项

  • 请确保你在项目中引用了 System.Net.HttpNewtonsoft.Json 命名空间。
  • 根据需要替换学校编码(如 "31")以获取不同学校的信息。

总结

通过这个小程序,你可以轻松获取高校的详细信息,包括地址、面积、特色专业等。这对于想要了解学校的同学们来说,简直是一大利器!

明白了,感谢你的澄清!在这个上下文中,channel 是指通道代码,通常用于标识特定的商品或服务。接下来我会更新教程中的相关内容,以确保读者能够理解这一点。

使用C#抓取布宫票务小程序售票信息

大家好!今天我们将深入探讨如何使用C#编写一个程序,从布宫票务系统抓取可预订的票务信息。这个程序能够获取指定商品的售票信息,并检查明天是否可以预订票。准备好了吗?让我们开始吧!

准备工作

在开始之前,请确保你已经安装了以下工具:

  1. Visual Studio(或你喜欢的任何C# IDE)
  2. Newtonsoft.Json库(用于处理JSON数据)

你可以在NuGet包管理器中安装Newtonsoft.Json:

Install-Package Newtonsoft.Json

代码实现

下面是程序的主要代码。它会向指定API发送请求,获取票务信息,并将结果输出到控制台。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    public class Main3
    {
        static string token = "********"; // 请使用Fiddler抓取你的token
        static string channel = "2"; // 通道代码,替换为你需要查询的通道代码

        public async Task Main()
        {
            await GetSalesList(channel, token);
        }

        static async Task GetSalesList(string commodity_id, string token)
        {
            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("token", token);

                var _postData = new
                {
                    commodity_id
                };
                var postData = JsonConvert.SerializeObject(_postData);
                var _data = new StringContent(postData, Encoding.UTF8, "application/json");
                HttpResponseMessage response = await client.PostAsync($"https://yjtxcx.potalapalace.cn/addons/shopro/sales/make_date", _data);
                response.EnsureSuccessStatusCode();

                if (response.IsSuccessStatusCode)
                {
                    string responseContent = await response.Content.ReadAsStringAsync();
                    Console.WriteLine(Regex.Unescape(responseContent));

                    // 解析 JSON 数据
                    var jsonDataObject = JsonConvert.DeserializeObject<RootObject>(responseContent);
                    CheckForAvailableTickets(jsonDataObject);
                }
            }
        }

        static void CheckForAvailableTickets(RootObject jsonDataObject)
        {
            // 获取当前日期和明天的日期
            DateTime currentDate = DateTime.Now.Date;
            DateTime tomorrowDate = currentDate.AddDays(1);

            // 查找明天是否可预订
            foreach (var item in jsonDataObject.data)
            {
                DateTime date = DateTime.Parse(item.date);

                // 检查明天是否可以订票
                if (date == tomorrowDate && item.type == 1)
                {
                    Console.WriteLine($"明天可预订的日期是:{date}");
                    // 在这里添加消息推送逻辑,例如发送通知
                    break;
                }

                if (date >= currentDate && item.type == 1)
                {
                    string status = item.info == "售罄" ? "售罄" : "可预订";
                    Console.WriteLine($"日期:{date:yyyy-MM-dd},状态:{status}");
                    // 在这里添加消息推送逻辑,例如发送通知
                }
            }
        }

        public class Datum
        {
            public string date { get; set; }
            public int type { get; set; }
            public string info { get; set; }
        }

        public class RootObject
        {
            public int code { get; set; }
            public string msg { get; set; }
            public string time { get; set; }
            public List<Datum> data { get; set; }
        }
    }
}

代码解析

  1. Token 和 Channel:在代码中,token 是需要根据实际情况进行设置的,使用Fiddler抓取你的token。channel 是通道代码,代表你要查询的特定商品或服务。

  2. HttpClient:我们使用 HttpClient 类来发送POST请求,并将结果解析为JSON格式。

  3. 数据解析:通过 JsonConvert.DeserializeObject 方法将返回的JSON数据转换为C#对象,并检查可预订的票务信息。

  4. 日期检查:程序会检查明天的票是否可预订,并输出相关信息。

注意事项

  • 请确保你在项目中引用了 System.Net.HttpNewtonsoft.Json 命名空间。
  • 使用Fiddler抓取token时,请确保你已正确配置代理,并能够捕获HTTP请求。
    -Fiddler 抓取 https 设置详解

总结

通过这个小程序,你可以轻松获取布宫的票务信息,并检查明天是否可预订。这对于想要参观布宫的朋友们来说,绝对是个好帮手!

如果你在实现过程中遇到问题,或者对token的抓取有疑问,随时欢迎在下方留言讨论。希望这篇教程对你有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/922453.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java框架Netty网络编程——问鼎篇

Netty进阶 粘包现象 案例 服务端代码 public static void main(String[] args) {NioEventLoopGroup bossGroupnew NioEventLoopGroup(1);NioEventLoopGroup workerGroupnew NioEventLoopGroup(2);try {ServerBootstrap serverBootstrap new ServerBootstrap();serverBootstr…

堤防安全监测系统方案

一、背景情况 堤防是开发利用水资源和防治水灾害的重要工程措施之一&#xff0c;对防洪、供水、生态、发电、航运等至关重要。我国现有堤防9.8万多座&#xff0c;其中大中型堤防4700多座、小型堤防9.4万座&#xff0c;80%以上修建于上世纪50至70年代。由于堤防管护力量薄弱&am…

模型减肥秘籍:模型压缩技术 知识蒸馏

教程链接&#xff1a;模型减肥秘籍&#xff1a;模型压缩技术-课程详情 | Datawhale 知识蒸馏&#xff1a;让AI模型更轻更快 在人工智能快速发展的今天&#xff0c;我们经常需要在资源受限的设备&#xff08;如手机、IoT设备&#xff09;上运行AI模型。但这些设备的计算能力和…

golang实现TCP服务器与客户端的断线自动重连功能

1.服务端 2.客户端 生成服务端口程序: 生成客户端程序: 测试断线重连: 初始连接成功

React表单联动

Ant Design 1、dependencies Form.Item 可以通过 dependencies 属性&#xff0c;设置关联字段。当关联字段的值发生变化时&#xff0c;会触发校验与更新。 一种常见的场景&#xff1a;注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段&#x…

springboot实战(16)(Validation参数校验冲突问题、分组校验、默认分组)

目录 一、注解NotNull与NotEmpty区别。 二、Validation提供的分组校验。&#xff08;参数校验冲突问题&#xff09; &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;实际案例。 &#xff08;3&#xff09;大模型提问提供的方法。 1、定义分组接口。 2、在字段上…

学Linux的第九天--磁盘管理

目录 一、磁盘简介 &#xff08;一&#xff09;、认知磁盘 &#xff08;1&#xff09;结构 &#xff08;2&#xff09;物理设备的命名规则 &#xff08;二&#xff09;、磁盘分区方式 MBR分区 MBR分区类型 扩展 GPT格式 lsblk命令 使用fdisk管理分区 使用gdisk管理分…

【ubuntu+win】Win10+Ubuntu22.04双系统给ubuntu系统中的某个分区进行扩容(从400G->800G)数据无损坏

给ubuntu已分区的部分进行扩容 1. 准备扩容的空间2.进入ubuntu系统进行卸载分区3.安装图形界面的安装包4.进行对分区扩容5. 重新挂载 我的情况是这式的&#xff08;可以不看&#xff0c;直接看后面的&#xff09;&#xff1a; 刚开始买下电脑的时候&#xff0c;只装了一个 1T 的…

流式上传与分片上传的原理与实现

&#x1f680; 博主介绍&#xff1a;大家好&#xff0c;我是无休居士&#xff01;一枚任职于一线Top3互联网大厂的Java开发工程师&#xff01; &#x1f680; &#x1f31f; 在这里&#xff0c;你将找到通往Java技术大门的钥匙。作为一个爱敲代码技术人&#xff0c;我不仅热衷…

Ettus USRP X410

总线连接器: 以太网 RF频率范围: 1 MHz 至 7.2 GHz GPSDO: 是 输出通道数量: 4 RF收发仪瞬时带宽: 400 MHz 输入通道数量: 4 FPGA: Zynq US RFSoC (ZU28DR) 1 MHz to 7.2 GHz&#xff0c;400 MHz带宽&#xff0c;GPS驯服OCXO&#xff0c;USRP软件无线电设备 Ettus USRP X410集…

oracle 19c RAC到单机ogg部署安装

源端&#xff08;RAC&#xff09;目标端&#xff08;FS&#xff09;IP192.168.40.30/31192.168.40.50数据库版本Oracle 19.3.0Oracle 19.3.0主机名hfdb30/hfdb31hfogg操作系统REHL7.6REHL7.6数据库实例hfdb1/hfdb2hfogg同步用户hfdb1hfdb1同步表testtestOGG版本19.1.0.0.419.1.…

现代密码学

概论 计算机安全的最核心三个关键目标&#xff08;指标&#xff09;/为&#xff1a;保密性 Confidentiality、完整性 Integrity、可用性 Availability &#xff0c;三者称为 CIA三元组 数据保密性&#xff1a;确保隐私或是秘密信息不向非授权者泄漏&#xff0c;也不被非授权者使…

QT QGridLayout控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例&#xff0c;包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizonta…

Adobe Illustrator 2024 安装教程与下载分享

介绍一下 下载直接看文章末尾 Adobe Illustrator 是一款由Adobe Systems开发的矢量图形编辑软件。它广泛应用于创建和编辑矢量图形、插图、徽标、图标、排版和广告等领域。以下是Adobe Illustrator的一些主要特点和功能&#xff1a; 矢量绘图&#xff1a;Illustrator使用矢量…

IDEA2023设置控制台日志输出到本地文件

1、Run->Edit Configurations 2、选择要输出日志的日志&#xff0c;右侧&#xff0c;IDEA2023的Logs在 Modify option 里 选中就会展示Logs栏。注意一定要先把这个日志文件创建出来&#xff0c;不然不会自动创建日志文件的 IDEA以前版本的Logs会直接展示出来 3、但是…

[UE5学习] 一、使用源代码安装UE5.4

一、简介 本文介绍了如何使用源代码安装编译UE5.4&#xff0c;并且新建简单的项目&#xff0c;打包成安卓平台下的apk安装包。 二、使用源代码安装UE5.4 注意事项&#xff1a; 请保证可以全程流畅地科学上网。请保证C盘具有充足的空间。请保证接下来安装下载的visual studi…

细说敏捷:敏捷四会之standup meeting

上一篇文章中&#xff0c;我们讨论了 敏捷四会 中 冲刺计划会 的实施要点&#xff0c;本篇我们继续分享敏捷四会中实施最频繁&#xff0c;团队最容易实施但往往也最容易走形的第二个会议&#xff1a;每日站会 关于每日站会的误区 站会是一个比较有标志性的仪式活动&#xff0…

10M和100M网口的编码及EMC影响

10M网口编码技术 10M网口&#xff0c;即10Base-T&#xff0c;采用的是曼彻斯特编码方法 。在这种编码中&#xff0c;“0”由“”跳变到“-”&#xff0c;而“1”由“-”跳变到“” 。这种编码方式的特点是信号的DC平衡&#xff0c;即信号在任何一段时间内的平均电压为零&#…

docker基本使用

参考视频&#xff1a; 参考视频https://www.bilibili.com/video/BV1e64y1F7pJ/?share_sourcecopy_web&vd_source8fc0c76c477d3db71f89fa5ae5b258c7 docker容器操作&#xff1a; 拉取镜像&#xff1a; 拉取官网ubuntu镜像 sudo docker pull ubuntu 运行镜像&#xff1a;…

音频信号采集前端电路分析

音频信号采集前端电路 一、实验要求 要求设计一个声音采集系统 信号幅度&#xff1a;0.1mVpp到1Vpp 信号频率&#xff1a;100Hz到16KHz 搭建一个带通滤波器&#xff0c;滤除高频和低频部分 ADC采用套件中的AD7920&#xff0c;转换率设定为96Ksps &#xff1b;96*161536 …