1数据的存取方式
1.1数据库存取:适合大量且关系复杂并有序的数据存取
1.2文件存取:适合大量且数据关系简单的数据存取,如软件的日志文件等
2文件存取的好处
读取操作方便
文件可以存取在任何介质中
3文件存取的方式:流对象
4代码
1 string path_Debug = Directory.GetCurrentDirectory();
1 //【1】创建文件流 2 FileStream fs = new FileStream(path_Debug+"\\myfile.txt", FileMode.Create); 3 //【2】创建写入器 4 StreamWriter sw = new StreamWriter(fs); 5 //【3】以流的方式写入数据 6 sw.Write(this.tb_Content.Text.Trim()); 7 //【4】关闭写入器 8 sw.Close(); 9 //【5】关闭文件流 10 fs.Close();
1 //【1】创建文件流 2 FileStream fs = new FileStream(path_Debug+"\\myfile.txt", FileMode.Open); 3 //【2】创建读取器 4 StreamReader sr = new StreamReader(fs); 5 //【3】以流的方式读取数据 6 this.tb_Content.Text = sr.ReadToEnd(); 7 //【4】关闭读取器 8 sr.Close(); 9 //【5】关闭文件流 10 fs.Close();
1 //【1】创建文件流(文件模式为:追加) 2 FileStream fs = new FileStream(path_Debug+"\\myfile.txt", FileMode.Append); 3 //【2】创建写入器 4 StreamWriter sw = new StreamWriter(fs); 5 //【3】以流的方式“逐行”写入数据 6 sw.WriteLine(DateTime.Now.ToString() + " 文件操作正常!"); 7 //【4】关闭写入器 8 sw.Close(); 9 //【5】关闭文件流 10 fs.Close();
1 File.Delete(this.txtFrom.Text.Trim());
1 if (File.Exists(this.txtTo.Text.Trim())) //首先判断文件是否存在(如果文件存在,直接复制会出现错误) 2 { 3 File.Delete(this.txtTo.Text.Trim());//删除文件 4 } 5 File.Copy(this.txtFrom.Text.Trim(), this.txtTo.Text.Trim()); //复制文件
1 //首先判断目标路径文件是否存在(如果文件存在,直接复制会出现错误) 2 if (File.Exists(this.txtTo.Text.Trim())) 3 { 4 File.Delete(this.txtTo.Text.Trim());//删除文件 5 } 6 if (File.Exists(this.txtFrom.Text.Trim()))//如果当前文件存在则移动 7 { 8 //移动文件 9 File.Move(this.txtFrom.Text.Trim(), this.txtTo.Text.Trim()); 10 } 11 else 12 { 13 MessageBox.Show("文件不存在!"); 14 }
1 string[] files = Directory.GetFiles(path_Debug); 2 this.tb_Content.Clear(); 3 foreach (string item in files) 4 { 5 this.tb_Content.Text += item + "\r\n"; 6 }
1 string[] dirs = Directory.GetDirectories(path_Debug); 2 this.tb_Content.Clear(); 3 foreach (string item in dirs) 4 { 5 this.tb_Content.Text += item + "\r\n"; 6 }
1 Directory.CreateDirectory(path_Debug+"\\Myfiles\\newfiles");
1 Directory.Delete("C:\\Myfiles");//要求目录必须为空 2 //使用DirectoryInfo对象,可以删除不为空的目录 3 DirectoryInfo dir = new DirectoryInfo(path_Debug + "\\Myfiles"); 4 dir.Delete(true);
1 /// <summary> 2 /// 复制目录下的所有子目录及文件(递归) 3 /// </summary> 4 /// <param name="Source">源目录</param> 5 /// <param name="Goal">新目录</param> 6 public static void copyDirectory(string Source, string Goal) 7 { 8 String[] Files; 9 if (Goal[Goal.Length - 1] != Path.DirectorySeparatorChar) 10 { 11 Goal += Path.DirectorySeparatorChar; 12 } 13 if (!Directory.Exists(Goal)) 14 { 15 Directory.CreateDirectory(Goal); 16 } 17 Files = Directory.GetFileSystemEntries(Source); 18 foreach (string Element in Files) 19 { 20 if (Directory.Exists(Element)) 21 copyDirectory(Element, Goal + Path.GetFileName(Element)); 22 else System.IO.File.Copy(Element, Goal + Path.GetFileName(Element), true); 23 } 24 }
1 DirectoryInfo dir_Images = new DirectoryInfo(sPath); 2 DirectoryInfo[] DirImages = dir_Images.GetDirectories(); 3 Dictionary<DirectoryInfo, DateTime> DirCreateDate = new Dictionary<DirectoryInfo, DateTime>(); 4 for (int i = 0; i < DirImages.Length; i++) 5 { 6 DirectoryInfo fi = new DirectoryInfo(DirImages[i].FullName); 7 DirCreateDate[DirImages[i]] = fi.CreationTime; 8 } 9 DirCreateDate = DirCreateDate.OrderBy(f => f.Value).ToDictionary(f => f.Key, f => f.Value); 10 int m = 0; 11 foreach (KeyValuePair<DirectoryInfo, DateTime> item in DirCreateDate) 12 { 13 if (m == 0) 14 {//对最先保存的图像给予删除。在这里尝试了隔月和隔年的特殊情况,暂无意外 15 item.Key.Delete(true); 16 } 17 m++; 18 if (m > 1) 19 { 20 string[] name = item.Key.Name.Split('-'); 21 if (name.Length != 4) 22 {//对文件夹不满足默认格式的文件给予删除 23 item.Key.Delete(true); 24 } 25 } 26 }
if (!Directory.Exists(LogPath))//检测文件夹是否存在 { }
DirectoryInfo directoryInfo = Directory.CreateDirectory(LogPath);//一次性创建全部的子路径 Directory.Move(LogPath, LogMovePath);//移动 原文件夹就不在了 Directory.Delete(LogMovePath);//删除
//DirectoryInfo不存在不报错 注意exists属性
Directory.CreateDirectory(LogPath);//创建文件的前提是文件所在文件夹必须事先存在,否则会报错 //创建文本文件的几种方式 using (FileStream fileStream = File.Create(fileName)) { string name = "12345567778890"; byte[] bytes = Encoding.Default.GetBytes(name); fileStream.Write(bytes, 0, bytes.Length); fileStream.Flush(); } using (FileStream fileStream = File.Create(fileName)) { StreamWriter sw = new StreamWriter(fileStream); 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(); }
//一次性将文本文件读入到内存的几种方式,适合小文件,如果文件太大不见这样操作 foreach (string result in File.ReadAllLines(fileName)) { Console.WriteLine(result); } string sResult = File.ReadAllText(fileName); Byte[] byteContent = File.ReadAllBytes(fileName); string sResultByte = Encoding.UTF8.GetString(byteContent); //分批读取 using (FileStream stream = File.OpenRead(fileName))//分批读取 { int length = 5; int result = 0; do { byte[] bytes = new byte[length]; result = stream.Read(bytes, 0, 5); for (int i = 0; i < result; i++) { Console.WriteLine(bytes[i].ToString()); } } while (length == result); }
File.Copy(fileName, fileNameCopy); File.Move(fileName, fileNameMove); File.Delete(fileNameMove);//尽量不要delete
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); }
Console.WriteLine(Path.GetDirectoryName(LogPath)); //返回目录名,需要注意路径末尾是否有反斜杠对结果是有影响的 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(LogPath, "log.txt"));//合并两个路径
private static void GetChildDirectory(List<DirectoryInfo> directoryList, DirectoryInfo directoryParent) { DirectoryInfo[] directoryListChild = directoryParent.GetDirectories();//一级子文件夹 if (directoryListChild != null && directoryListChild.Length > 0)//递归的跳出条件 { directoryList.AddRange(directoryListChild); foreach (var child in directoryListChild) { GetChildDirectory(directoryList, child); } } }
//分批读取 using (FileStream stream = File.OpenRead(fileName))//分批读取 { int length = 5; int result = 0; do { byte[] bytes = new byte[length]; result = stream.Read(bytes, 0, 5); for (int i = 0; i < result; i++) { Console.WriteLine(bytes[i].ToString()); } } while (length == result); }
5文本保存对象的不足
使用文本保存对象存在两个问题:
当对象属性变化时,增加和减少信息的写入或读取次数会很多。
信息安全性较差。
6对象序列化保存
对象序列化(Serialize)成流(stream),流可以反序列化(Deserialize)成对象。
对象序列化前的准备:
引入命名空间 using System.Runtime.Serialization.Formatters.Binary;
所要保存的类前面需要加上对象可序列化标记: [Serializable]
使用二进制格式化器
反序列化方法参数只有一个;并且返回值时object类型,需要强制转换成具体类型
7序列化与反序列化小结
序列化:内存中的对象保存到本地的文件; 反序列化:本地的文件重新转化为内存中的对象
1 [Serializable]//很重要 2 class Student 3 { 4 public string Name { get; set; } 5 public string Gender { get; set; } 6 public int Age { get; set; } 7 public DateTime Birthday { get; set; } 8 }
1 //封装对象信息 2 Student objStu = new Student() 3 { 4 Name = this.txtName.Text.Trim(), 5 Age = Convert.ToInt16(this.txtAge.Text.Trim()), 6 Gender = this.txtGender.Text.Trim(), 7 Birthday = Convert.ToDateTime(this.txtBirthday.Text.Trim()) 8 }; 9 //【1】创建文件流 10 FileStream fs = new FileStream("C:\\objStu.obj", FileMode.Create); 11 //【2】创建二进制格式化器 12 BinaryFormatter formatter = new BinaryFormatter(); 13 //【3】调用序列化方法 14 formatter.Serialize(fs, objStu); 15 //【4】关闭文件流 16 fs.Close();
1 //【1】创建文件流 2 FileStream fs = new FileStream("C:\\objStu.obj", FileMode.Open); 3 //【2】创建二进制格式化器 4 BinaryFormatter formatter = new BinaryFormatter(); 5 //【3】调用序列化方法 6 Student objStu = (Student)formatter.Deserialize(fs); 7 //【4】关闭文件流 8 fs.Close(); 9 //显示对象属性 10 this.txtName.Text = objStu.Name; 11 this.txtAge.Text = objStu.Age.ToString(); 12 this.txtGender.Text = objStu.Gender; 13 this.txtBirthday.Text = objStu.Birthday.ToShortDateString();
//BinaryFormatter序列化自定义类的对象时,序列化之后的流中带有空字符,以致于无法反序列化,反序列化时总是报错“在分析完成之前就遇到流结尾”(已经调用了stream.Seek(0, SeekOrigin.Begin);)。
//改用XmlFormatter序列化之后,可见流中没有空字符,从而解决上述问题,但是要求类必须有无参数构造函数,而且各属性必须既能读又能写,即必须同时定义getter和setter,若只定义getter,则反序列化后的得到的各个属性的值都为null。
应用场合:应用系统配置信息,信息量大时可用该方法方便读取和写入
需用数据库时可作为数据存取载体
模块之间数据传递
好处:对象保存和读取方便,扩张性强
数据安全高效
8什么是XML?
XML是可扩展标记语言。
可用来创建自定义的标记语言,由万维网协会(W3C)创建,用来克服HTML的局限。
XML主要用来数据的储蓄,HTML主要用来数据显示。
版本号和字符集不能修改。节点成对出现。节点区分大小写。节点可自由扩展。
9 XML文档的格式要求
确定且唯一的根元素
开始标签和结束标签匹配
元素标签的正确嵌套
属性值要用引号括起来
同一个元素的属性不能重复
10 XML语法要求
元素:<标签>文本内容</标签>
处理指令:<?xmlversion="1.0"?>
注释:<!--这是一个XML注释-->
属性:<salary curuency="USS">25000</salary>
11 XML文件读取步骤
1创建文档对象 2加载XML文档
3获取根节点 4遍历节点并封装数据
12 XML文件读取总结
常用对象:XmlDocument对象表示XML整个文档
XmlNode对象表示XML文件的单个节点
1 XmlDocument objDoc = new XmlDocument(); //【1】创建XML文档操作对象 2 objDoc.Load("StuScore.xml"); //【2】加载XML文件到文档对象中 3 XmlNode rootNode = objDoc.DocumentElement; //【3】获取XML文档根目录 4 List<Student> list = new List<Student>();//创建对象集合 5 foreach (XmlNode stuNode in rootNode.ChildNodes) //【4】遍历根节点(根节点包含所有节点) 6 { 7 if (stuNode.Name == "Student") 8 { 9 Student objStu = new Student(); 10 foreach (XmlNode subNode in stuNode) //【5】遍历子节点 11 { 12 switch (subNode.Name)//根据子节点的名称封装到对象的属性 13 { 14 case "StuName": 15 objStu.StuName = subNode.InnerText;//获取《节点名称》对应的《节点值》 16 break; 17 case "StuAge": 18 objStu.StuAge = Convert.ToInt16(subNode.InnerText); 19 break; 20 case "Gender": 21 objStu.Gender = subNode.InnerText; 22 break; 23 case "ClassName": 24 objStu.ClassName = subNode.InnerText; 25 break; 26 } 27 } 28 list.Add(objStu); 29 } 30 } 31 this.dgvStuList.DataSource = list;
常用属性与说明
| 对象 | 属性和方法 | 说明 |
| XmlDocument | DocumentElement属性 | 获取根节点 |
| ChildNodes属性 | 获取所有子节点 | |
| Load()方法 | 读取整个XML的结构 | |
| XmlNode | InnerText属性 | 当前节点的值 |
| Name属性 | 当前节点的名字 | |
| ChildNodes属性 | 当前节点的所有子节点 |
13.Json
using System.Web.Script.Serialization;//System.Web.Extensions using Newtonsoft.Json;//nuget Newtonsoft namespace Helper { //【Json序列化】将一组对象降低维度为一个string字符串 //【Json反序列化】将一个string字符串增加维度转化为一组对象 public class JsonHelper { //System.Web.Script.Serialization序列化 public static string ObjectToString<T>(T obj) { JavaScriptSerializer jss = new JavaScriptSerializer(); return jss.Serialize(obj); } //System.Web.Script.Serialization反序列化 public static T StringToObject<T>(string content) { JavaScriptSerializer jss = new JavaScriptSerializer(); return jss.Deserialize<T>(content); } //Newtonsoft.Json序列化 public static string ToJson<T>(T obj) { return JsonConvert.SerializeObject(obj); } //Newtonsoft.Json反序列化 public static T ToObject<T>(string content) { return JsonConvert.DeserializeObject<T>(content); } } }
{ string jResult = JsonHelper.ObjectToString<List<Programmer>>(list); List<Programmer> list1 = JsonHelper.StringToObject<List<Programmer>>(jResult); } { string jResult = JsonHelper.ToJson<List<Programmer>>(list); List<Programmer> list1 = JsonHelper.ToObject<List<Programmer>>(jResult); }
14.XML
using System.Xml.Serialization; using System.IO; namespace Helper { /// <summary> /// 使用序列化器完成的 /// </summary> public class XmlHelper { // XmlSerializer序列化实体为字符串 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; } // 字符串反序列化成XML 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); } } /// xml文件反序列化成实体 public static T FileToObject<T>(string fileName) where T : new() { 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(); { //一堆对象序列化为xml字符串 string xmlResult = XmlHelper.ToXml<List<Programmer>>(list); //xml字符串反序列化为一堆对象 List<Programmer> list1 = XmlHelper.ToObject<List<Programmer>>(xmlResult); //【一个xml文件直接反序列化为一堆对象】 List<Programmer> list2 = XmlHelper.FileToObject<List<Programmer>>(fileName); }
15.SerializeHelper
public class SerializeHelper { /// <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);//反序列化对象 } } /// <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();//反序列化对象 } } //BinaryFormatter序列化自定义类的对象时,序列化之后的流中带有空字符,以致于无法反序列化,反序列化时总是报错“在分析完成之前就遇到流结尾”(已经调用了stream.Seek(0, SeekOrigin.Begin);)。 //改用XmlFormatter序列化之后,可见流中没有空字符,从而解决上述问题,但是要求类必须有无参数构造函数,而且各属性必须既能读又能写,即必须同时定义getter和setter,若只定义getter,则反序列化后的得到的各个属性的值都为null。 /// <summary> /// XML序列化器 /// </summary> public static void XmlSerialize() { //使用XML序列化对象 string fileName = Path.Combine(Constant.SerializeDataPath, @"XmlStudent.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序列化器,需要指定对象的类型 fStream.Position = 0;//重置流位置 List<Programmer> pList = pList = (List<Programmer>)xmlFormat.Deserialize(fStream); } } }
16.ImageHelper
using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; namespace Helper { /// <summary> /// /// </summary> public class ImageHelper { private static string ImagePath = @"D:\软媒\课程代码+课件\20180515Advanced11Course7IOSerialize\IOSerialize\IOSerialize\bin\Debug"; private static string VerifyPath = ImagePath; //绘图的原理很简单:Bitmap就像一张画布,Graphics如同画图的手,把Pen或Brush等绘图对象画在Bitmap这张画布上 /// <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(VerifyPath, "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; } System.Drawing.Image bitmap = new System.Drawing.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(); } //添加水印 //二维码 QRCode } }