C# 关于序列化、反序列化和保存图像的代码的反馈
下面是我的代码,用于序列化、反序列化图像并将其保存到文件系统。我看过很多序列化/反序列化的例子,我只想得到一些反馈,因为我确信我的代码可以改进。如有任何反馈,将不胜感激。我知道这是一个常见的问题,所以希望这个问题在将来能成为其他人的好资源 这是使用建议修订的代码:C# 关于序列化、反序列化和保存图像的代码的反馈,c#,image,save,serialization,C#,Image,Save,Serialization,下面是我的代码,用于序列化、反序列化图像并将其保存到文件系统。我看过很多序列化/反序列化的例子,我只想得到一些反馈,因为我确信我的代码可以改进。如有任何反馈,将不胜感激。我知道这是一个常见的问题,所以希望这个问题在将来能成为其他人的好资源 这是使用建议修订的代码: private void Form1_Load(object sender, EventArgs e) { RunTest(); } private void RunTest()
private void Form1_Load(object sender, EventArgs e)
{
RunTest();
}
private void RunTest()
{
byte[] jpgba = ConvertFileToByteArray("D:\\Images\\Image01.jpg");
using (Image jpgimg = ConvertByteArrayToImage(jpgba))
{
SaveImageToFileSystem(jpgimg, "D:\\Images\\Image01_Copy.jpg");
}
byte[] pngba = ConvertFileToByteArray("D:\\Images\\Image02.png");
using (Image pngimg = ConvertByteArrayToImage(pngba))
{
SaveImageToFileSystem(pngimg, "D:\\Images\\Image02_Copy.png");
}
byte[] gifba = ConvertFileToByteArray("D:\\Images\\Image03.gif");
using (Image gifimg = ConvertByteArrayToImage(gifba))
{
SaveImageToFileSystem(gifimg, "D:\\Images\\Image03_Copy.gif");
}
MessageBox.Show("Test Complete");
this.Close();
}
private static byte[] ConvertFileToByteArray(String FilePath)
{
return File.ReadAllBytes(FilePath);
}
private static Image ConvertByteArrayToImage(byte[] ImageByteArray)
{
using (MemoryStream ms = new MemoryStream(ImageByteArray))
{
return Image.FromStream(ms);
}
}
private static void SaveImageToFileSystem(Image ImageObject, string FilePath)
{
// ImageObject.Save(FilePath, ImageObject.RawFormat);
// This method only works with .png files.
// This method works with .jpg, .png and .gif
// Need to copy image before saving.
using (Image img = new Bitmap(ImageObject.Width, ImageObject.Height))
{
using (Graphics tg = Graphics.FromImage(img))
{
tg.DrawImage(ImageObject, 0, 0);
}
img.Save(FilePath, img.RawFormat);
}
return;
}
我从快速查看中看到: 流应该使用(…)模式包装,在您的情况下,如果在处理过程中发生异常,则不会调用Dispose()
using (FileStream fs = new FileStream(FilePath, FileMode.Open))
{
// Another small optimization, removed unnecessary variable
byte[] iba = new byte[(int)fs.Length];
fs.Read(iba, 0, iba.Length);
}
您应该只捕获预期的异常。例如,在SerializeImage中,这将是IOException。捕获所有异常是非常糟糕的做法
}
catch (IOException ex)
{
FromStream方法依赖于流,所以如果关闭底层流并返回图像,您可能会收到不可预测的行为(在大多数情况下,这是可行的,但有时会发生错误)。因此,您需要创建图像副本并返回它
using (MemoryStream ms = new MemoryStream(ImageByteArray))
{
using (Image img = Image.FromStream(ms))
{
return new Bitmap(img);
}
}
在SaveImage方法中,您没有处理tg graphics对象和img对象(但处理了ImageObject,请参见下一段)。一般来说,我不认为这种逻辑有必要,如果您想保存图像质量,只需调用ImageObject.Save(…,ImageFormat.Png)
在相同的方法(SaveImage)中,您可以释放ImageObject参数。在大多数情况下,这也是一个不好的做法,考虑通过使用(…)模式将Word图像放置在Word方法之外。 从快速查看中可以看到: 流应该使用(…)模式包装,在您的情况下,如果在处理过程中发生异常,则不会调用Dispose()
using (FileStream fs = new FileStream(FilePath, FileMode.Open))
{
// Another small optimization, removed unnecessary variable
byte[] iba = new byte[(int)fs.Length];
fs.Read(iba, 0, iba.Length);
}
您应该只捕获预期的异常。例如,在SerializeImage中,这将是IOException。捕获所有异常是非常糟糕的做法
}
catch (IOException ex)
{
FromStream方法依赖于流,所以如果关闭底层流并返回图像,您可能会收到不可预测的行为(在大多数情况下,这是可行的,但有时会发生错误)。因此,您需要创建图像副本并返回它
using (MemoryStream ms = new MemoryStream(ImageByteArray))
{
using (Image img = Image.FromStream(ms))
{
return new Bitmap(img);
}
}
在SaveImage方法中,您没有处理tg graphics对象和img对象(但处理了ImageObject,请参见下一段)。一般来说,我不认为这种逻辑有必要,如果您想保存图像质量,只需调用ImageObject.Save(…,ImageFormat.Png)
在相同的方法(SaveImage)中,您可以释放ImageObject参数。在大多数情况下,这也是一个不好的做法,考虑通过使用(…)模式在Word方法之外处理这个图像。 这里有一点:
private void RunTest()
{
// byte array that can be stored in DB
byte[] iba;
// image object to display in picturebox or used to save to file system.
iba = ReadImage("D:\\Images\\Image01.jpg");
using (Image img = DeserializeImage(iba))
{
SaveImage(img, "D:\\Images\\Image01_Copy.jpg");
}
iba = ReadImage("D:\\Images\\Image02.png");
using (Image img1 = DeserializeImage(iba))
{
SaveImage(img1, "D:\\Images\\Image02_Copy.png");
}
iba = ReadImage("D:\\Images\\Image03.gif");
using (var img2 = DeserializeImage(iba))
{
SaveImage(img2, "D:\\Images\\Image03_Copy.gif");
}
MessageBox.Show("Test Complete");
}
private static byte[] ReadImage(String filePath)
{
// This seems to be the easiest way to serialize an image file
// however it would be good to take a image object as an argument
// in this method.
using (var fs = new FileStream(filePath, FileMode.Open))
{
Int32 fslength = Convert.ToInt32(fs.Length);
var iba = new byte[fslength];
fs.Read(iba, 0, fslength);
return iba;
}
}
private static Image DeserializeImage(byte[] imageByteArray)
{
using (var ms = new MemoryStream(imageByteArray))
{
return Image.FromStream(ms);
}
}
private static void SaveImage(Image imageObject, string filePath)
{
// I could only get this method to work for .png files.
// imageObject.Save(filePath, imageObject.RawFormat);
// This method works with .jpg, .png and .gif
// Need to copy image before saving.
using (Image img = new Bitmap(imageObject.Width, imageObject.Height))
{
using (Graphics tg = Graphics.FromImage(img))
{
tg.DrawImage(imageObject, 0, 0);
}
img.Save(filePath, img.RawFormat);
}
return;
}
请注意,您所谓的序列化只是读取中的字节。序列化更多的是保存时要做的事情
我摆脱了所有的“尝试/抓住”障碍。他们为你做的最好的事情就是告诉你问题是发生在阅读、保存还是反序列化中。您可以从堆栈跟踪中确定这一点,您只需显示ex.Message即可销毁堆栈跟踪
您还在一个严重异常(传播失败)上返回null
除此之外,我同意仲裁者所说的一切。这里还有一点:
private void RunTest()
{
// byte array that can be stored in DB
byte[] iba;
// image object to display in picturebox or used to save to file system.
iba = ReadImage("D:\\Images\\Image01.jpg");
using (Image img = DeserializeImage(iba))
{
SaveImage(img, "D:\\Images\\Image01_Copy.jpg");
}
iba = ReadImage("D:\\Images\\Image02.png");
using (Image img1 = DeserializeImage(iba))
{
SaveImage(img1, "D:\\Images\\Image02_Copy.png");
}
iba = ReadImage("D:\\Images\\Image03.gif");
using (var img2 = DeserializeImage(iba))
{
SaveImage(img2, "D:\\Images\\Image03_Copy.gif");
}
MessageBox.Show("Test Complete");
}
private static byte[] ReadImage(String filePath)
{
// This seems to be the easiest way to serialize an image file
// however it would be good to take a image object as an argument
// in this method.
using (var fs = new FileStream(filePath, FileMode.Open))
{
Int32 fslength = Convert.ToInt32(fs.Length);
var iba = new byte[fslength];
fs.Read(iba, 0, fslength);
return iba;
}
}
private static Image DeserializeImage(byte[] imageByteArray)
{
using (var ms = new MemoryStream(imageByteArray))
{
return Image.FromStream(ms);
}
}
private static void SaveImage(Image imageObject, string filePath)
{
// I could only get this method to work for .png files.
// imageObject.Save(filePath, imageObject.RawFormat);
// This method works with .jpg, .png and .gif
// Need to copy image before saving.
using (Image img = new Bitmap(imageObject.Width, imageObject.Height))
{
using (Graphics tg = Graphics.FromImage(img))
{
tg.DrawImage(imageObject, 0, 0);
}
img.Save(filePath, img.RawFormat);
}
return;
}
请注意,您所谓的序列化只是读取中的字节。序列化更多的是保存时要做的事情
我摆脱了所有的“尝试/抓住”障碍。他们为你做的最好的事情就是告诉你问题是发生在阅读、保存还是反序列化中。您可以从堆栈跟踪中确定这一点,您只需显示ex.Message即可销毁堆栈跟踪
您还在一个严重异常(传播失败)上返回null
除此之外,我同意仲裁者所说的一切。正如约翰·桑德所说,序列化和反序列化不仅仅是从文件中读取原始数据。请参见上的Wiki 对于.net中的图像,您只需要使用提供的框架方法(大多数情况下) 因此,在.net中加载映像(反序列化)是非常困难的
using System.Drawing.Image;
Image test;
test = Image.FromFile(@"C:\myfile.jpg")
test = Image.FromStream(myStream); // or you can load from an existing stream
同样,保存映像(序列化)是:
这些是在.net中加载和保存图像的基础知识。如果您有一个更具体的场景,请问另一个问题。正如John Saunder所说,序列化和反序列化不仅仅是从文件中读取原始数据。请参见上的Wiki 对于.net中的图像,您只需要使用提供的框架方法(大多数情况下) 因此,在.net中加载映像(反序列化)是非常困难的
using System.Drawing.Image;
Image test;
test = Image.FromFile(@"C:\myfile.jpg")
test = Image.FromStream(myStream); // or you can load from an existing stream
同样,保存映像(序列化)是:
这些是在.net中加载和保存图像的基础知识。如果您有更具体的场景,请问另一个问题。我最大的建议是使用“使用”模式。谢谢大家!通过发布这个问题,我意识到在同行之间讨论和共享代码是多么重要。我有很多东西要学习,这个网站背后的社区是一个非常棒的资源。我现在有一些严重的重新分解要做!我最大的建议是使用“使用”模式。谢谢大家!通过发布这个问题,我意识到在同行之间讨论和共享代码是多么重要。我有很多东西要学习,这个网站背后的社区是一个非常棒的资源。我现在有一些严重的重新分解要做!怎么样:
private byte[]ReadImage(字符串文件路径){return File.ReadAllBytes(文件路径);}
更好。我不记得有人存在。更好的主意,因为在任何情况下都不会对流执行任何操作。如何:private byte[]ReadImage(string filePath){return File.ReadAllBytes(filePath);}
更好。我不记得有人存在。更好的主意,因为在任何情况下都不会对流进行任何处理。