c# IOSerialize 验证码、图片缩放
文件流的读写
文件写入方式:
{ DirectoryInfo directory = new DirectoryInfo(LogPath);//不存在不报错 注意exists属性 Console.WriteLine(string.Format("{0} {1} {2}", directory.FullName, directory.CreationTime, directory.LastWriteTime)); string fileName = Path.Combine(LogPath, "log.txt"); string fileNameCopy = Path.Combine(LogPath, "logCopy.txt"); string fileNameMove = Path.Combine(LogPath, "logMove.txt"); bool isExists = File.Exists(fileName); if (!isExists) { Directory.CreateDirectory(LogPath);//创建了文件夹之后,才能创建里面的文件 using (FileStream fileStream = File.Create(fileName))//打开文件流 (创建文件并写入) { string name = "12345567778890"; byte[] bytes = Encoding.Default.GetBytes(name); fileStream.Write(bytes, 0, bytes.Length); //数据是先被读到了内存中的 ,再把数据写到文件中,当你数据读完的时候不代表你的数据已经写完了, //因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了close()方法关闭了读写流, //那么这部分数据就会丢失,所以为了防止数据丢失,应该在关闭读写流之前先flush()。 fileStream.Flush(); } // 如果文件不存在就创建,如果存在就新建一个覆盖掉 using (FileStream fileStream = File.Create(fileName))//打开文件流 (创建文件并写入) { StreamWriter sw = new StreamWriter(fileStream); //直接通过StreamWriter对象的WriteLine方法写入数据 sw.WriteLine("1234567890"); sw.Flush(); } //追加内容 using (StreamWriter sw = File.AppendText(fileName))//流写入器(创建/打开文件并写入) { string msg = "今天是Course6IOSerialize,今天上课的人有55个人"; sw.WriteLine(msg); sw.Flush(); } using (StreamWriter sw = File.AppendText(fileName))//流写入器(创建/打开文件并写入) { //二进制的写法 string name = "0987654321"; byte[] bytes = Encoding.Default.GetBytes(name); sw.BaseStream.Write(bytes, 0, bytes.Length); sw.Flush(); }
File.Copy(fileName, fileNameCopy);
File.Move(fileName, fileNameMove);
File.Delete(fileNameCopy);
File.Delete(fileNameMove);//尽量不要delete
}
}
文件读取方式
{ #region 文件太大,分批读取 //文件太大,用工具去打开的时候,计算机直接卡死了 using (FileStream stream = File.OpenRead(fileName))//分批读取 { int length = 1024*1024;//1M int result = 0; //do-while循环,先读取一部分长度的,如果实际读出来的和假定读取的长度一样,说明还未读完或刚好读完,继续读取然后再判断 do { byte[] bytes = new byte[length]; result = stream.Read(bytes, 0, length); for (int i = 0; i < result; i++) { Console.WriteLine(bytes[i].ToString()); } } while (length == result); } #endregion } { //读取硬盘信息 DriveInfo[] drives = DriveInfo.GetDrives(); foreach (DriveInfo drive in drives) { if (drive.IsReady) Console.WriteLine("类型:{0} 卷标:{1} 名称:{2} 总空间:{3} 剩余空间:{4}",
drive.DriveType, drive.VolumeLabel, drive.Name, drive.TotalSize, drive.TotalFreeSpace); else Console.WriteLine("类型:{0} is not ready", drive.DriveType); } }
换一种方式:
public static void BigFile() { List<byte> list = new List<byte>(); #region 文件太大,分批读取 //文件太大,用工具去打开的时候,计算机直接卡死了 using (FileStream stream = File.OpenRead(@"D:\迅雷下载\【朝夕教育】2021春招Kafka高频面试题.pdf"))//分批读取 { //获取包含扩展名的文件名 string fileName = stream.Name.Substring(stream.Name.LastIndexOf("\\") + 1); //获取到文件的后缀名 string aLastName = stream.Name.Substring(stream.Name.LastIndexOf(".") + 1); int length = 1024 * 1024; int result = 0; //do-while循环,先读取一部分长度的,如果实际读出来的和假定读取的长度一样,说明还未读完或刚好读完,继续读取然后再判断 do { byte[] bytes = new byte[length]; //result是实际读取到的字节数 result = stream.Read(bytes, 0, length); for (int i = 0; i < result - 1; i++) { list.Add(bytes[i]); } } while (length == result); } byte[] test = list.ToArray(); using (FileStream fs = new FileStream($@"D:\迅雷下载\text.pdf", FileMode.Create)) { fs.Write(test, 0, test.Length); fs.Flush(); } #endregion }
其他一些使用方式
{ Console.WriteLine(Path.GetDirectoryName(@"d:\\abc")); //将返回 d:\ Console.WriteLine(Path.GetDirectoryName(@"d:\\abc\"));// 将返回 d:\abc Console.WriteLine(Path.GetRandomFileName());//将返回随机的文件名 Console.WriteLine(Path.GetFileNameWithoutExtension("d:\\abc.txt"));// 将返回abc Console.WriteLine(Path.GetInvalidPathChars());// 将返回禁止在路径中使用的字符 Console.WriteLine(Path.GetInvalidFileNameChars());//将返回禁止在文件名中使用的字符 Console.WriteLine(Path.Combine("d:\\abc\\", "log.txt"));//合并两个路径,结果:d:\\abc\\log.txt }
自定义的日志
public static void Log(string msg) { StreamWriter sw = null; try { string fileName = "log.txt"; string totalPath = Path.Combine(LogPath, fileName); if (!Directory.Exists(LogPath)) { Directory.CreateDirectory(LogPath); } sw = File.AppendText(totalPath); // 如果文件不存在,就新建一个文件,然后写入内容,存在直接追加内容 这里其实和上面的if判断重复了,功能一样。 sw.WriteLine(string.Format("{0}:{1}", DateTime.Now, msg)); sw.WriteLine("***************************************************"); } catch (Exception ex) { Console.WriteLine(ex.Message);//log //建议大家在写日志的时候,把异常吞掉; //throw ex; //throw new exception("这里异常"); } finally//无论是否发生异常 全都都会执行 { if (sw != null) { sw.Flush(); sw.Close(); sw.Dispose(); } } }
找出全部的子文件夹,递归实现
递归:可以理解为类型,或者说是一种编程方式
/// <summary> /// 找出全部的子文件夹 /// 递归:可以理解为类型,或者说是一种编程方式 /// /// 获取“D:\软谋教育\Git_Work”路径下的所有文件夹 /// /// 1、在递归的时候,计算机是在高强度的计算; /// 2、一定要有跳出循环的判断,避免死循环; /// 3、在使用递归的时候,尽量避免多线程; /// </summary> /// <param name="rootPath">根目录</param> /// <returns></returns> public static List<DirectoryInfo> GetAllDirectory(string rootPath) { if (!Directory.Exists(rootPath)) return new List<DirectoryInfo>(); //一个存储路径信息的容器 List<DirectoryInfo> directoryList = new List<DirectoryInfo>();//容器 DirectoryInfo directory = new DirectoryInfo(rootPath);//root文件夹 directoryList.Add(directory); var directioryList = GetChilds(directoryList, directory); return directioryList; } private static List<DirectoryInfo> GetChilds(List<DirectoryInfo> directoryList, DirectoryInfo directory) { //获取当前目录下的所有子目录 var chaildArray = directory.GetDirectories(); if (chaildArray != null && chaildArray.Length > 0) { foreach (var child in chaildArray) { directoryList.Add(child); GetChilds(directoryList, child); } } return directoryList; }
看下面的一个递归方法:
private void Wait() { if (DateTime.Now.Millisecond < 999) { Wait(); } else return; }
这个递归方法是会出问题的,因为计算机的能力是很强大的,一秒内会执行很多次递归方法,很容易卡死的,还有就是不要在递归中写多线程,这样会疯狂开启很多子线程的。
序列化
基础类:
namespace IOSerialize { [Serializable] //必须添加序列化特性 public class Person { [NonSerialized] public int Id = 1; public string Name { get; set; } public string Sex { get; set; } } [Serializable] //必须添加序列化特性 public class Programmer : Person { private string Language { get; set; }//编程语言 public string Description { get; set; } } public class DataFactory { /// <summary> /// 初始化数据的 /// </summary> /// <returns></returns> public static List<Programmer> BuildProgrammerList() { #region data prepare List<Programmer> list = new List<Programmer>(); list.Add(new Programmer() { Id = 1, Description="高级班学员", Name = "SoWhat", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "day", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "领悟", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "Sam", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "AlphaGo", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "折腾", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "Me860", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "打兔子的猎人", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "Nine", Sex = "女" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "望", Sex = "女" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "微笑刺客", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "waltz", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "爱在昨天", Sex = "男" }); list.Add(new Programmer() { Id = 1, Description = "高级班学员", Name = "waltz", Sex = "男" }); #endregion return list; } } }
二进制序列化
/// <summary> /// 二进制序列化器 /// </summary> public static void BinarySerialize() { //使用二进制序列化对象 string fileName = Path.Combine(Constant.SerializeDataPath, @"BinarySerialize.txt");//文件名称与路径 using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)) {//需要一个stream,这里是直接写入文件了 List<Programmer> pList = DataFactory.BuildProgrammerList(); BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器 binFormat.Serialize(fStream, pList); } using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite)) {//需要一个stream,这里是来源于文件 BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器 //使用二进制反序列化对象 fStream.Position = 0;//重置流位置 List<Programmer> pList = (List<Programmer>)binFormat.Deserialize(fStream);//反序列化对象 } }
上面代码实现了二进制的序列化与反序列化
SOAP序列化
/// <summary> /// soap序列化器 /// </summary> public static void SoapSerialize() { //使用Soap序列化对象 string fileName = Path.Combine(Constant.SerializeDataPath, @"SoapSerialize.txt");//文件名称与路径 using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)) { List<Programmer> pList = DataFactory.BuildProgrammerList(); SoapFormatter soapFormat = new SoapFormatter();//创建二进制序列化器 //soapFormat.Serialize(fStream, list);//SOAP不能序列化泛型对象 soapFormat.Serialize(fStream, pList.ToArray()); } using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite)) { SoapFormatter soapFormat = new SoapFormatter();//创建二进制序列化器 //使用二进制反序列化对象 fStream.Position = 0;//重置流位置 List<Programmer> pList = ((Programmer[])soapFormat.Deserialize(fStream)).ToList();//反序列化对象 } }
需要注意的是SOAP序列化器是不支持泛型对象的。在跨平台传输的时候用的比较多。
Simple Object Access Protocol 简单对象访问协议。是一种轻量的,简单的,基于xml的协议。
它是一种通信协议,用于应用程序之间的能信,它是一种用于发送消息的格式,被设计用来通过互联网进行通信,它基于xml,独立于平台,语言,它简单且可以扩展,它可以允许绕过防火墙。
可以所它认为是一种协议,同时它也是一种消息发送的格式。
XML序列化器
/// <summary> /// XML序列化器 /// </summary> public static void XmlSerialize() { //使用XML序列化对象 string fileName = Path.Combine(@"D:\TEST", @"Student.xml");//文件名称与路径 using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite)) { List<Programmer> pList = DataFactory.BuildProgrammerList(); XmlSerializer xmlFormat = new XmlSerializer(typeof(List<Programmer>));//创建XML序列化器,需要指定对象的类型 xmlFormat.Serialize(fStream, pList); } using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite)) { XmlSerializer xmlFormat = new XmlSerializer(typeof(List<Programmer>));//创建XML序列化器,需要指定对象的类型 //使用XML反序列化对象 fStream.Position = 0;//重置流位置 List<Programmer> pList = pList = (List<Programmer>)xmlFormat.Deserialize(fStream); } }
XML是独立于软件和硬件的信息传输工具。
目前,XML在Web中起到的作用不会亚于一直作为 Web 基石的 HTML。
XML无所不在。XML是各种应用程序之间进行数据传输的最常用的工具,并且在信息存储和描述领域变得越来越流行。
上面是将数据以xml序列化的形式存在硬盘上,然后访问硬盘中的文件来解析,下面实现直接在内存中进行序列化并且解析:
/// <summary> /// 使用序列化器完成的 /// </summary> public class XmlHelper { /// <summary> /// XmlSerializer序列化实体为字符串 不保存到硬盘,只在内存中处理 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="t"></param> /// <returns></returns> public static string ToXml<T>(T t) where T : new() { XmlSerializer xmlSerializer = new XmlSerializer(t.GetType()); Stream stream = new MemoryStream(); xmlSerializer.Serialize(stream, t); stream.Position = 0; StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); return text; } /// <summary> /// 字符串序列化成XML /// </summary> /// <typeparam name="T"></typeparam> /// <param name="content"></param> /// <returns></returns> public static T ToObject<T>(string content) where T : new() { using (MemoryStream stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(content))) { XmlSerializer xmlFormat = new XmlSerializer(typeof(T)); return (T)xmlFormat.Deserialize(stream); } } /// <summary> /// 文件反序列化成实体 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fileName"></param> /// <returns></returns> public static T FileToObject<T>(string fileName) where T : new() { string CurrentXMLPath = ConfigurationManager.AppSettings["CurrentXMLPath"]; fileName = Path.Combine(CurrentXMLPath, @"Student.xml"); using (Stream fStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite)) { XmlSerializer xmlFormat = new XmlSerializer(typeof(T)); return (T)xmlFormat.Deserialize(fStream); } } }
调用:
List<Programmer> list = DataFactory.BuildProgrammerList(); { Console.WriteLine("********************XmlHelper**********************"); string xmlResult = XmlHelper.ToXml<List<Programmer>>(list); List<Programmer> list1 = XmlHelper.ToObject<List<Programmer>>(xmlResult); //List<Programmer> list2 = XmlHelper.FileToObject<List<Programmer>>(""); }
验证码
绘图的原理很简单:Bitmap就像一张画布,Graphics如同画图的手,把Pen或Brush等绘图对象画在Bitmap这张画布上。
下面是封装了2个很简单的生成验证码的方法:
/// <summary> /// 画验证码 /// </summary> public static void Drawing() { Bitmap bitmapobj = new Bitmap(100, 100); //在Bitmap上创建一个新的Graphics对象 Graphics g = Graphics.FromImage(bitmapobj); //创建绘画对象,如Pen,Brush等 Pen redPen = new Pen(Color.Red, 8); g.Clear(Color.White); //绘制图形 g.DrawLine(redPen, 50, 20, 500, 20); g.DrawEllipse(Pens.Black, new Rectangle(0, 0, 200, 100));//画椭圆 g.DrawArc(Pens.Black, new Rectangle(0, 0, 100, 100), 60, 180);//画弧线 g.DrawLine(Pens.Black, 10, 10, 100, 100);//画直线 g.DrawRectangle(Pens.Black, new Rectangle(0, 0, 100, 200));//画矩形 g.DrawString("我爱北京天安门", new Font("微软雅黑", 12), new SolidBrush(Color.Red), new PointF(10, 10));//画字符串 //g.DrawImage( if (!Directory.Exists(ImagePath)) Directory.CreateDirectory(ImagePath); bitmapobj.Save(ImagePath + "pic1.jpg", ImageFormat.Jpeg); //释放所有对象 bitmapobj.Dispose(); g.Dispose(); } public static void VerificationCode() { Bitmap bitmapobj = new Bitmap(300, 300); //在Bitmap上创建一个新的Graphics对象 Graphics g = Graphics.FromImage(bitmapobj); g.DrawRectangle(Pens.Black, new Rectangle(0, 0, 150, 50));//画矩形 g.FillRectangle(Brushes.White, new Rectangle(1, 1, 149, 49)); g.DrawArc(Pens.Blue, new Rectangle(10, 10, 140, 10), 150, 90);//干扰线 string[] arrStr = new string[] { "我", "们", "孝", "行", "白", "到", "国", "中", "来", "真" }; Random r = new Random(); int i; for (int j = 0; j < 4; j++) { i = r.Next(10); g.DrawString(arrStr[i], new Font("微软雅黑", 15), Brushes.Red, new PointF(j * 30, 10)); } bitmapobj.Save(Path.Combine(ImagePath, "Verif.jpg"), ImageFormat.Jpeg); bitmapobj.Dispose(); g.Dispose(); }
图片压缩
/// <summary> /// 按比例缩放,图片不会变形,会优先满足原图和最大长宽比例最高的一项 /// </summary> /// <param name="oldPath"></param> /// <param name="newPath"></param> /// <param name="maxWidth"></param> /// <param name="maxHeight"></param> public static void CompressPercent(string oldPath, string newPath, int maxWidth, int maxHeight) { Image _sourceImg = Image.FromFile(oldPath); double _newW = (double)maxWidth; double _newH = (double)maxHeight; double percentWidth = (double)_sourceImg.Width > maxWidth ? (double)maxWidth : (double)_sourceImg.Width; if ((double)_sourceImg.Height * (double)percentWidth / (double)_sourceImg.Width > (double)maxHeight) { _newH = (double)maxHeight; _newW = (double)maxHeight / (double)_sourceImg.Height * (double)_sourceImg.Width; } else { _newW = percentWidth; _newH = (percentWidth / (double)_sourceImg.Width) * (double)_sourceImg.Height; } Image bitmap = new Bitmap((int)_newW, (int)_newH); Graphics g = Graphics.FromImage(bitmap); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(Color.Transparent); g.DrawImage(_sourceImg, new Rectangle(0, 0, (int)_newW, (int)_newH), new Rectangle(0, 0, _sourceImg.Width, _sourceImg.Height), GraphicsUnit.Pixel); _sourceImg.Dispose(); g.Dispose(); bitmap.Save(newPath, System.Drawing.Imaging.ImageFormat.Jpeg); bitmap.Dispose(); } /// <summary> /// 按照指定大小对图片进行缩放,可能会图片变形 /// </summary> /// <param name="oldPath"></param> /// <param name="newPath"></param> /// <param name="newWidth"></param> /// <param name="newHeight"></param> public static void ImageChangeBySize(string oldPath, string newPath, int newWidth, int newHeight) { Image sourceImg = Image.FromFile(oldPath); System.Drawing.Image bitmap = new System.Drawing.Bitmap(newWidth, newHeight); Graphics g = Graphics.FromImage(bitmap); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.Clear(Color.Transparent); g.DrawImage(sourceImg, new Rectangle(0, 0, newWidth, newHeight), new Rectangle(0, 0, sourceImg.Width, sourceImg.Height), GraphicsUnit.Pixel); sourceImg.Dispose(); g.Dispose(); bitmap.Save(newPath, System.Drawing.Imaging.ImageFormat.Jpeg); bitmap.Dispose(); }
二维码
/// <summary> /// 生成二维码图片 /// </summary> /// <param name="codeNumber">要生成二维码内容的字符串</param> /// <param name="size">大小尺寸</param> /// <returns>二维码图片</returns> public string Create_ImgCode(string codeNumber) { //创建二维码生成类 QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(); //设置编码模式 qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; //设置编码测量度 qrCodeEncoder.QRCodeScale = 10; //设置编码版本 qrCodeEncoder.QRCodeVersion = 0; //设置编码错误纠正 qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M; //生成二维码图片 System.Drawing.Bitmap image = qrCodeEncoder.Encode(codeNumber, Encoding.GetEncoding("UTF-8")); string filePath = System.Web.HttpContext.Current.Server.MapPath(string.Format("~/QRCode/{0}.jpg", codeNumber)); image.Save(filePath); image.Dispose(); return string.Format("/QRCode/{0}.jpg", codeNumber); }
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术