GDI/GDI+(1): 将Bitmap导出为Byte[]

本文介绍三种从PNG图像导出Byte[]数组的方法,并将其保存为不同格式的图片。第一种方法利用GDI+的LockBits函数,第二种方法通过临时文件和IStream实现,第三种方法则是转换为BMP格式。

最近遇到一个问题,需要将Bitmap中的图像Buffer导出来。


有人说用GDI的GetDIBits方法,有人说用GDI+的LockBits方法。


找了很多资料,都没找到可直接运行的代码,只有老老实实的查MSDN。

最后终于搞定了,下面见代码:

// BitmapToByteArray.cpp : Defines the entry point for the console application.
//

#include <tchar.h>
#include <windows.h>

#include <gdiplus.h>
#pragma comment(lib, "gdiplus")
using namespace Gdiplus;

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	UINT  num = 0;          // number of image encoders
	UINT  size = 0;         // size of the image encoder array in bytes

	ImageCodecInfo* pImageCodecInfo = NULL;

	GetImageEncodersSize(&num, &size);
	if(size == 0)
		return -1;  // Failure

	pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
	if(pImageCodecInfo == NULL)
		return -1;  // Failure

	GetImageEncoders(num, size, pImageCodecInfo);

	for(UINT j = 0; j < num; ++j)
	{
		if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
		{
			*pClsid = pImageCodecInfo[j].Clsid;
			free(pImageCodecInfo);
			return j;  // Success
		}
	}

	free(pImageCodecInfo);
	return -1;  // Failure
}

void ExtractBitmapToByteArray_1()
{
	// Create a Bitmap object from a BMP file.
	Bitmap bitmap(_T("menu.png"));

	BitmapData bmpData;
	Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());

	bitmap.LockBits(
		&rect,
		ImageLockModeWrite,
		PixelFormat32bppARGB,
		&bmpData);

	// Write to the temporary buffer provided by LockBits.
	UINT* pixels = (UINT*)bmpData.Scan0;

	int byteCount = bmpData.Stride * bmpData.Height;
	BYTE* pBuffer = new BYTE[byteCount];
	memcpy(pBuffer, pixels, byteCount);

	Bitmap bitmap22(
		bmpData.Width,
		bmpData.Height,
		bmpData.Stride,
		bmpData.PixelFormat,
		(BYTE*)bmpData.Scan0);

	CLSID clsid;
	GetEncoderClsid(_T("image/png"), &clsid);
	bitmap22.Save(_T("menu_1.png"), &clsid);
	delete []pBuffer;

	bitmap.UnlockBits(&bmpData);
}

// 通过临时文件将png图片保存到IStream中
BOOL ExtractBitmapToByteArray_2()
{
	Bitmap bitmap(_T("menu.png"));

	TCHAR pszPath[MAX_PATH] = {0};
	GetTempPath(MAX_PATH, pszPath);
	const TCHAR tmpName[] = _T("menu.png.tmp");
	lstrcat(pszPath, tmpName);

	IStorage* pstgFile = NULL;
	HRESULT hr = ::StgCreateDocfile(pszPath,
		STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
		0, &pstgFile);
	if( FAILED(hr) ) { return FALSE; }

	IStream * pStream = NULL;
	TCHAR pszName[10] = _T("Image");
	hr = pstgFile->OpenStream(pszName, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, &pStream);
	if (FAILED(hr)) {
		hr = pstgFile->CreateStream(pszName, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream);
		if (FAILED(hr)) { return FALSE; }
	}

	// 以png格式保存到IStream中
	CLSID ImageClsid;
	GetEncoderClsid(_T("image/png"), &ImageClsid);
	bitmap.Save(pStream, &ImageClsid);

	// Begin -- HH Debug
	STATSTG statstg;
	pStream->Stat(&statstg, STATFLAG_NONAME);
	int nDatalen = (ULONG)statstg.cbSize.QuadPart;
	// End -- HH Debug

	// read
	GetEncoderClsid(_T("image/png"), &ImageClsid);
	Gdiplus::Bitmap* pRead = Gdiplus::Bitmap::FromStream(pStream);
	pRead->Save(_T("menu2.png"), &ImageClsid);

	pStream->Release();
	pstgFile->Release();
	DeleteFile(pszPath);

	return TRUE;
}

//------------保存Bitmap到文件---------------
BOOL SaveBitmapToFile(HBITMAP hBitmap, LPCTSTR lpFileName ) 
{ 
	HDC hDC; //设备描述表 
	int iBits; //当前显示分辨率下每个像素所占字节数 
	WORD wBitCount; //位图中每个像素所占字节数 
	DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 
		dwBmBitsSize, 
		dwDIBSize, dwWritten; 
	BITMAP Bitmap; //位图属性结构 
	BITMAPFILEHEADER bmfHdr; //位图文件头结构 
	BITMAPINFOHEADER bi; //位图信息头结构 
	LPBITMAPINFOHEADER lpbi; //指向位图信息头结构 

	HANDLE fh, hDib, hPal,hOldPal=NULL; //定义文件,分配内存句柄,调色板句柄 

	//计算位图文件每个像素所占字节数 
	HDC hWndDC = CreateDC(_T("DISPLAY"),NULL,NULL,NULL); 
	hDC = ::CreateCompatibleDC( hWndDC ) ; 
	iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
	DeleteDC(hDC); 

	if (iBits <= 1) 
		wBitCount = 1; 
	else if (iBits <= 4) 
		wBitCount = 4; 
	else if (iBits <= 8) 
		wBitCount = 8; 
	else if (iBits <= 24) 
		wBitCount = 24; 
	else 
		wBitCount = 24 ; 

	//计算调色板大小 
	if (wBitCount <= 8) 
		dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD); 

	//设置位图信息头结构 
	GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
	bi.biSize = sizeof(BITMAPINFOHEADER); 
	bi.biWidth = Bitmap.bmWidth; 
	bi.biHeight = Bitmap.bmHeight; 
	bi.biPlanes = 1; 
	bi.biBitCount = wBitCount; 
	bi.biCompression = BI_RGB; 
	bi.biSizeImage = 0; 
	bi.biXPelsPerMeter = 0; 
	bi.biYPelsPerMeter = 0; 
	bi.biClrUsed = 0; 
	bi.biClrImportant = 0; 

	dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32) * 4 * Bitmap.bmHeight ; 

	//为位图内容分配内存 
	hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER)); 
	lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
	*lpbi = bi; 

	// 处理调色板 
	hPal = GetStockObject(DEFAULT_PALETTE); 
	if (hPal) 
	{ 
		hDC = ::GetDC(NULL); 
		hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
		RealizePalette(hDC); 
	} 

	// 获取该调色板下新的像素值 
	GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, 
		(LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
		+dwPaletteSize, 
		(LPBITMAPINFO ) 
		lpbi, DIB_RGB_COLORS); 

	//恢复调色板 
	if (hOldPal) 
	{ 
		SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
		RealizePalette(hDC); 
		::ReleaseDC(NULL, hDC); 
	} 

	//创建位图文件 
	fh = CreateFile(lpFileName, GENERIC_WRITE, 
		0, NULL, CREATE_ALWAYS, 
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

	if (fh == INVALID_HANDLE_VALUE) 
		return FALSE; 

	// 设置位图文件头 
	bmfHdr.bfType = 0x4D42; // "BM" 
	dwDIBSize = sizeof(BITMAPFILEHEADER) 
		+ sizeof(BITMAPINFOHEADER) 
		+ dwPaletteSize + dwBmBitsSize; 
	bmfHdr.bfSize = dwDIBSize; 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) 
		+ (DWORD)sizeof(BITMAPINFOHEADER) 
		+ dwPaletteSize; 

	// 写入位图文件头 
	WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 

	// 写入位图文件其余内容 
	WriteFile(fh, (LPSTR)lpbi, dwDIBSize, 
		&dwWritten, NULL); 

	//清除 
	GlobalUnlock(hDib); 
	GlobalFree(hDib); 
	CloseHandle(fh); 

	return TRUE; 
}

void ExtractBitmapToByteArray_3()
{
	Bitmap bmp(_T("menu.png"));
	HBITMAP hBitmap;
	bmp.GetHBITMAP(Color(0,255,255,255), &hBitmap);
	SaveBitmapToFile(hBitmap, _T("menu_3.bmp"));
}

int _tmain(int argc, _TCHAR* argv[])
{
	ULONG_PTR gdiplusToken;
	GdiplusStartupInput gdiplusStartupInput;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	ExtractBitmapToByteArray_1();

	GdiplusShutdown(gdiplusToken);

	return 0;
}

一共有2种方法将png保存到图片中。

第3种是将png保存到bmp中。


另外大家也可以在这里查看: 使用LockBits将Bitmap导出为Byte[]

using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Drawing; using System.Collections; using System.IO; using System.Drawing.Imaging; using System.IO.Compression; using System.Diagnostics; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using Newtonsoft.Json; namespace Util { #region EnumStringAttribute [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)] public class EnumStringAttribute : System.Attribute { public EnumStringAttribute(string str) { this.enumStr = str; } public string GetEnumString() { return this.enumStr; } private string enumStr; } #endregion public class Util { /// <summary> /// 得到可执行程序所在的目录,最后具有分隔符“\\”。 /// </summary> /// <returns></returns> public static string GetApplicationPath() { return AppDomain.CurrentDomain.BaseDirectory; } /// <summary> /// 填充并显示窗体到Panel中 /// </summary> /// <param name="panel"></param> /// <param name="frm"></param> public static void fillShowFrmToPanel(Panel panel, Form frm) { if (panel.Controls.Contains(frm)) { return; } panel.Controls.Clear(); frm.TopLevel = false; panel.Controls.Add(frm); frm.FormBorderStyle = FormBorderStyle.None; frm.Dock = DockStyle.Fill; frm.Show(); } /// <summary> /// 将文件名中的非法字符替换为'_',得到有效的文件名 /// </summary> /// <param name="filename"></param> /// <returns></returns> public static string GetValidFileName(string filename) { string newname = filename; newname = newname.Replace('/', '_'); newname = newname.Replace('\\', '_'); newname = newname.Replace(':', '_'); newname = newname.Replace('*', '_'); newname = newname.Replace('?', '_'); newname = newname.Replace('"', '_'); newname = newname.Replace('<', '_'); newname = newname.Replace('>', '_'); newname = newname.Replace('|', '_'); newname = newname.Replace((char)0xA, ' '); return newname; } /// <summary> /// 将字符串转化为整数 /// </summary> /// <param name="val"></param> /// <param name="defVal"></param> /// <returns></returns> public static int ToInt(string val, int defVal) { if (string.IsNullOrEmpty(val)) return defVal; try { if (val.StartsWith("0x") || val.StartsWith("0X")) { return int.Parse(val.Substring(2, val.Length - 2), System.Globalization.NumberStyles.HexNumber); } else { return int.Parse(val); } } catch (Exception e) { Console.WriteLine("数据转换格式错误:val: {0} {1}", val, e.Message); return defVal; } } /// <summary> /// 将字符串转换为长整数。 /// </summary> /// <param name="val"></param> /// <param name="defVal"></param> /// <returns></returns> public static long ToLong(string val, long defVal) { if (string.IsNullOrEmpty(val)) return defVal; try { if (val.StartsWith("0x") || val.StartsWith("0X")) { return long.Parse(val.Substring(2, val.Length - 2), System.Globalization.NumberStyles.HexNumber); } else { return long.Parse(val); } } catch (Exception e) { Console.WriteLine("数据转换格式错误:val: {0} {1}", val, e.Message); return defVal; } } /// <summary> /// 将二进制转化为16进制字符串。 /// </summary> /// <param name="buf"></param> /// <returns></returns> public static string BinaryToString(byte[] buf, int maxLen) { if (buf == null) return ""; int count = Math.Min(buf.Length, maxLen); bool bOmit = count < buf.Length; StringBuilder sb = new StringBuilder(count * 2 + 30); for (int i = 0; i < count; ++i) { sb.Append(buf[i].ToString("X2")); } if (bOmit) sb.Append(string.Format(" ... Total {0} Bytes", buf.Length)); return sb.ToString(); } /// <summary> /// 将二进制转化为16进制字符串。 /// </summary> /// <param name="buf"></param> /// <param name="cntPerRow">每行显示几个字节</param> /// <returns></returns> public static string BinaryToStringFormat(byte[] buf, int cntPerRow) { if (buf == null) return ""; StringBuilder sb = new StringBuilder(buf.Length * 2); int cnt = 0; int cntall = 0; foreach (byte b in buf) { cnt++; cntall++; if (cnt == 1) { sb.Append((cntall - 1).ToString("d4")).Append(" : "); } sb.Append(b.ToString("X2")).Append(" "); if (cnt >= cntPerRow) { sb.AppendLine(); cnt = 0; } } return sb.ToString(); } /// <summary> /// 将字符串转化为二进制数据数组 /// </summary> /// <param name="str"></param> /// <returns></returns> public static byte[] BinaryFromString(string str) { if (string.IsNullOrEmpty(str)) return new byte[0]; str = str.Trim(); int len = str.Length / 2; byte[] buf = new byte[len + (str.Length % 2)]; for (int i = 0; i < len; ++i) { buf[i] = byte.Parse(str.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); } if ((str.Length % 2) > 0) { // 最后一个字符 buf[buf.Length - 1] = byte.Parse(str.Substring(str.Length - 1, 1), System.Globalization.NumberStyles.HexNumber); } return buf; } /// <summary> /// byte数组格式化为十六进制的字符串 /// </summary> /// <param name="buffer"></param> /// <param name="len">长度</param> /// <param name="spliter">分割符</param> /// <returns></returns> public static string BufferFormat(byte[] buffer, int len, char spliter) { StringBuilder sb = new StringBuilder(""); if (buffer == null) return sb.ToString(); for (int i = 0; i < len; ++i) { sb.Append(buffer[i].ToString("X2")).Append(spliter); } return sb.ToString(); } public static uint ColorToInt(Color color) { return (uint)(((uint)color.B << 16) | (ushort)(((ushort)color.G << 8) | color.R)); } public static Color IntToColor(int color) { int r = 0xFF & color; int g = 0xFF00 & color; g >>= 8; int b = 0xFF0000 & color; b >>= 16; return Color.FromArgb(r, g, b); } #region DllImport 把窗体导出为图片使用 [DllImport("user32.dll")] public static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rectangle rect); [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleDC(IntPtr hdc); [DllImport("gdi32.dll")] public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); [DllImport("gdi32.dll")] public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); [DllImport("gdi32.dll")] public static extern int DeleteDC(IntPtr hdc); [DllImport("gdi32.dll")] public static extern bool BitBlt( IntPtr hdcDest, // 目的 DC的句柄 int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, // 源DC的句柄 int nXSrc, int nYSrc, System.Int32 dwRop // 光栅的处置数值 ); [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, UInt32 nFlags); [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr hwnd); #endregion /// <summary> /// 根据窗口句柄,把窗口显示导出图片(.bmp) /// </summary> /// <param name="hWnd"></param> /// <returns></returns> public static Bitmap GetWindowCapture(IntPtr hWnd) { IntPtr hscrdc = GetWindowDC(hWnd); Rectangle windowRect = new Rectangle(); GetWindowRect(hWnd, ref windowRect); int width = windowRect.Right - windowRect.Left; int height = windowRect.Bottom - windowRect.Top; IntPtr hbitmap = CreateCompatibleBitmap(hscrdc, width, height); IntPtr hmemdc = CreateCompatibleDC(hscrdc); SelectObject(hmemdc, hbitmap); PrintWindow(hWnd, hmemdc, 0); Bitmap bmp = Bitmap.FromHbitmap(hbitmap); DeleteDC(hscrdc);//删除用过的对象 DeleteDC(hmemdc);//删除用过的对象 return bmp; } public static string BufferFormatSimple(byte[] buffer) { return Util.BufferFormat(buffer, buffer.Length, ' '); } static Dictionary<string, List<string>> typeHash = new Dictionary<string, List<string>>(); /// <summary> /// 得到与枚举类型值相关联的字符串 /// </summary> /// <param name="type"></param> /// <returns></returns> public static List<string> GetEnumString(Type type) { if (typeHash.ContainsKey(type.ToString())) { return typeHash[type.ToString()]; } else { List<string> list = new List<string>(); System.Reflection.MemberInfo[] mis = type.GetMembers(); foreach (System.Reflection.MemberInfo mi in mis) { Attribute[] attrs = System.Attribute.GetCustomAttributes(mi); foreach (Attribute at in attrs) { if (at is EnumStringAttribute) { list.Add(((EnumStringAttribute)at).GetEnumString()); } } } typeHash[type.ToString()] = list; return list; } } static Hashtable enumValueHash = new Hashtable(); /// <summary> /// 由枚举类型及枚举显示字符串得到枚举数值。 /// 如 由 SexType "男" 得到 (int)SexType.Male /// </summary> /// <param name="enumType"></param> /// <param name="enumDisStr"></param> /// <returns></returns> public static int GetEnumValue(Type enumType, string enumDisStr) { string key = enumType.ToString() + enumDisStr; if (enumValueHash.Contains(key)) { return (int)enumValueHash[key]; } else { int ret = -1; System.Reflection.MemberInfo[] mis = enumType.GetMembers(); foreach (System.Reflection.MemberInfo mi in mis) { Attribute[] attrs = System.Attribute.GetCustomAttributes(mi); foreach (Attribute at in attrs) { if (at is EnumStringAttribute) { EnumStringAttribute esr = (EnumStringAttribute)at; if (esr.GetEnumString() == enumDisStr) { ret = (int)System.Enum.Parse(enumType, mi.Name); break; } } } if (ret != -1) break; } enumValueHash[key] = ret; return ret; } } static Hashtable enumStringHash = new Hashtable(); /// <summary> /// 有枚举类型及枚举值得到显示字符串。 /// 如 由 SexType (int)SexType.Male 得到 "男" /// </summary> /// <param name="enumType"></param> /// <param name="enumVal"></param> /// <returns></returns> public static string GetEnumDisString(Type enumType, int enumVal) { string key = enumType.ToString() + enumVal.ToString(); if (enumStringHash.Contains(key)) { return (string)enumStringHash[key]; } else { string ret = ""; System.Reflection.MemberInfo[] mis = enumType.GetMembers(); foreach (System.Reflection.MemberInfo mi in mis) { Attribute[] attrs = System.Attribute.GetCustomAttributes(mi); foreach (Attribute at in attrs) { if (at is EnumStringAttribute) { EnumStringAttribute esr = (EnumStringAttribute)at; //object obj = System.Enum.Parse(enumType, mi.Name); if ((int)System.Enum.Parse(enumType, mi.Name) == enumVal) { ret = esr.GetEnumString(); break; } } } if (ret != "") break; } enumStringHash[key] = ret; return ret; } } private static ImageCodecInfo GetEncoderInfo(string mimeType) { // Get image codecs for all image formats ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); // Find the correct image codec for (int i = 0; i < codecs.Length; i++) if (codecs[i].MimeType == mimeType) return codecs[i]; return null; } public static byte[] ConvertToJpgBuff(Image bmp, long quality) { // Encoder parameter for image quality EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality); // JPEG image codec ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg"); EncoderParameters encoderParams = new EncoderParameters(1); encoderParams.Param[0] = qualityParam; MemoryStream msJpg = new MemoryStream(); bmp.Save(msJpg, jpegCodec, encoderParams); bmp.Dispose(); return msJpg.ToArray(); } /// <summary> /// Convert Image to Byte[] /// </summary> /// <param name="image"></param> /// <returns></returns> public static byte[] ImageToBytes(Image image) { ImageFormat format = image.RawFormat; using (MemoryStream ms = new MemoryStream()) { if (format.Equals(ImageFormat.Jpeg)) { image.Save(ms, ImageFormat.Jpeg); } else if (format.Equals(ImageFormat.Png)) { image.Save(ms, ImageFormat.Png); } else if (format.Equals(ImageFormat.Bmp)) { image.Save(ms, ImageFormat.Bmp); } else if (format.Equals(ImageFormat.Gif)) { image.Save(ms, ImageFormat.Gif); } else if (format.Equals(ImageFormat.Icon)) { image.Save(ms, ImageFormat.Icon); } else image.Save(ms, ImageFormat.Jpeg); byte[] buffer = new byte[ms.Length]; //Image.Save()会改变MemoryStream的Position,需要重新Seek到Begin ms.Seek(0, SeekOrigin.Begin); ms.Read(buffer, 0, buffer.Length); return buffer; } } /// <summary> /// Convert Byte[] to Image /// </summary> /// <param name="buffer"></param> /// <returns></returns> public static Image BytesToImage(byte[] buffer) { MemoryStream ms = new MemoryStream(buffer); Image image = System.Drawing.Image.FromStream(ms); return image; } /// <summary> /// Convert Byte[] to a picture and Store it in file /// </summary> /// <param name="fileName"></param> /// <param name="buffer"></param> /// <returns></returns> public static string CreateImageFromBytes(string fileName, byte[] buffer) { string file = fileName; Image image = BytesToImage(buffer); ImageFormat format = image.RawFormat; if (format.Equals(ImageFormat.Jpeg)) { file += ".jpeg"; } else if (format.Equals(ImageFormat.Png)) { file += ".png"; } else if (format.Equals(ImageFormat.Bmp)) { file += ".bmp"; } else if (format.Equals(ImageFormat.Gif)) { file += ".gif"; } else if (format.Equals(ImageFormat.Icon)) { file += ".icon"; } System.IO.FileInfo info = new System.IO.FileInfo(file); System.IO.Directory.CreateDirectory(info.Directory.FullName); File.WriteAllBytes(file, buffer); return file; } public static System.DateTime ConvertIntDateTime(long d) { System.DateTime time = System.DateTime.MinValue; System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); time = startTime.AddMilliseconds(d); return time; } public static long ConvertDateTimeInt(System.DateTime time) { //double intResult = 0; System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0)); long t = (time.Ticks - startTime.Ticks) / 10000; //除10000调整为13位 return t; } /// <summary> /// 压缩缓冲区 /// </summary> /// <param name="inBuff">输入待压缩缓冲区</param> /// <param name="outBuff">输出压缩后缓冲区</param> /// <returns></returns> public static Boolean CompressBuffer(byte[] inBuff, ref byte[] outBuff) { Boolean bLess = false; using (MemoryStream destination = new MemoryStream()) { using (GZipStream output = new GZipStream(destination, CompressionMode.Compress)) { output.Write(inBuff, 0, inBuff.Length); } destination.Flush(); outBuff = destination.ToArray(); bLess = (outBuff.Length < inBuff.Length); if (!bLess) outBuff = inBuff; } return bLess; } /// <summary> /// 解压缩缓冲区 /// </summary> /// <param name="inBuff">待解压缓冲区</param> /// <param name="outBuff">解压后缓冲区</param> /// <returns></returns> public static Boolean DecompressBuffer(byte[] inBuff, ref byte[] outBuff) { Stream source = new MemoryStream(inBuff); using (MemoryStream destination = new MemoryStream()) { using (GZipStream input = new GZipStream(source, CompressionMode.Decompress, true)) { byte[] bytes = new byte[4096]; int n; while ((n = input.Read(bytes, 0, bytes.Length)) != 0) { destination.Write(bytes, 0, n); } } destination.Flush(); destination.Position = 0; outBuff = destination.ToArray(); } return true; } /// <summary> /// 从指定目录获取指定扩展名的文件 /// </summary> /// <param name="path"></param> /// <param name="extNameArr"></param> /// <returns></returns> public static List<FileInfo> GetDirFiles(string path, params string[] extNameArr) { List<FileInfo> lst = new List<FileInfo>(); try { string[] dir = Directory.GetDirectories(path); //文件夹列表 DirectoryInfo fdir = new DirectoryInfo(path); FileInfo[] file = fdir.GetFiles(); if (file.Length != 0 || dir.Length != 0) //当前目录文件或文件夹不为空 { foreach (FileInfo f in file) //显示当前目录所有文件 { foreach(string extName in extNameArr) { if (extName.ToLower().IndexOf(f.Extension.ToLower()) >= 0) { lst.Add(f); break; } } } foreach (string d in dir) { GetDirFiles(d, extNameArr);//递归 } } } catch (Exception ex) { Console.WriteLine(ex.Message); } return lst; } public static int DBM2Int(string dbm) { if (string.IsNullOrEmpty(dbm) || dbm.Length != 3) { Debug.Assert(false, "节点DBM不能为空,且长度必须为3," + dbm); } int id = 0; char[] arr = dbm.ToCharArray(); for (int i = 0; i < arr.Length; i++) { id <<= 8; id |= (byte)arr[i]; } return id; } public static string Int2DBM(int id) { char[] arr = new char[3]; for (int i = 2; i >= 0; i--) { arr[i] = (char)(id & 0xFF); id >>= 8; } return new string(arr); } #region 将类和结构序列化和反序列化的方法 /// <summary> /// 序列化(把类和结构序列化) /// </summary> /// <param name="msg">结构信息</param> /// <returns></returns> //public static byte[] Serialize(object obj) //{ // try // { // string json = JsonConvert.SerializeObject(obj); // byte[] buffer = Encoding.UTF8.GetBytes(json); // return buffer; // } // catch (Exception e) // { // Console.WriteLine(e.Message); // //OutPutLog.WriteLog(LogLevel.Error, "Util.Serialize()错误 " + e.Message, LogObjType.Util.ToString()); // } // return null; //} public static byte[] Serialize(object obj) { try { IFormatter inFormatter = new BinaryFormatter(); MemoryStream stm = new MemoryStream(); inFormatter.Serialize(stm, obj); byte[] buffer = stm.ToArray(); stm.Close(); stm.Dispose(); return buffer; } catch (Exception e) { Console.WriteLine(e.Message); //OutPutLog.WriteLog(LogLevel.Error, "Util.Serialize()错误 " + e.Message, LogObjType.Util.ToString()); } return null; } /// <summary> /// 反序列化(类和结构的反序列化) /// </summary> /// <param name="buffer">串行数据</param> /// <returns></returns> //public static object Deserialize(byte[] buffer) //{ // try // { // string json = Encoding.UTF8.GetString(buffer); // return JsonConvert.DeserializeObject(json) ?? null; // } // catch (Exception e) // { // Console.WriteLine(e.Message); // //OutPutLog.WriteLog(LogLevel.Error, "Util.Deserialize() " + e.Message, LogObjType.Util.ToString()); // } // return null; //} public static object Deserialize(byte[] buffer) { try { MemoryStream stream = new MemoryStream(buffer); BinaryFormatter outFormatter = new BinaryFormatter(); object obj = outFormatter.Deserialize(stream); stream.Close(); stream.Dispose(); return obj; } catch (Exception e) { Console.WriteLine(e.Message); //OutPutLog.WriteLog(LogLevel.Error, "Util.Deserialize() " + e.Message, LogObjType.Util.ToString()); } return null; } #endregion } } 转换.net8.0
最新发布
08-20
将现有的C#代码库迁移到.NET 8.0涉及多个关键步骤,包括兼容性检查、API变更处理以及依赖项更新。以下是详细的迁移指南。 ### 3.1 兼容性检查 在迁移之前,需要确保现有代码库与.NET 8.0兼容。这包括检查目标框架的兼容性、API变更以及依赖项的兼容性。可以使用.NET 8.0的SDK工具来帮助进行兼容性检查。例如,使用`dotnet migrate`命令可以帮助识别潜在的兼容性问题。 ```bash dotnet migrate ``` 在迁移过程中,需要注意Visual Studio的版本兼容性。如果从旧版本的Visual Studio迁移到Visual Studio 2015或2017,需要确保安装最新版本的Visual Assist X以获得最佳兼容性,并在更新前备份现有项目和设置[^2]。 ### 3.2 API变更处理 .NET 8.0引入了许多新的API和功能,同时也可能废弃或修改了一些旧的API。在迁移过程中,需要检查代码中使用的API是否在.NET 8.0中仍然支持。可以使用Visual Studio的智能提示功能来帮助识别和替换废弃的API。 例如,如果某个方法在.NET 8.0中被废弃,可以使用新的替代方法: ```csharp // 旧代码 var result = SomeOldMethod(); // 新代码 var result = SomeNewMethod(); ``` 此外,需要注意.NET 8.0中引入的新特性,如AOT(Ahead-of-Time)编译和原生依赖树修剪,这些特性可能会影响代码的执行方式和性能[^1]。 ### 3.3 依赖项更新 在迁移过程中,需要确保所有依赖项都兼容.NET 8.0。这包括NuGet包、第三方库以及内部依赖项。可以使用NuGet包管理器来更新依赖项到最新版本。 ```bash dotnet add package SomePackage --version 8.0.0 ``` 如果某个依赖项不支持.NET 8.0,可能需要寻找替代的包或联系包的维护者以获取支持。此外,确保所有NuGet包均包含符号源和源码链接,以便于调试和维护[^3]。 ### 3.4 项目文件更新 在迁移过程中,需要更新项目文件(.csproj)以使用.NET 8.0的目标框架。可以手动编辑项目文件,将目标框架更改为.NET 8.0: ```xml <TargetFramework>net8.0</TargetFramework> ``` 如果项目使用了特定的SDK功能或工具,需要确保这些功能和工具在.NET 8.0中仍然支持。 ### 3.5 测试和验证 在迁移完成后,需要进行全面的测试和验证,确保所有功能正常工作。可以使用GitHub Actions实现自动化构建验证,确保每个NuGet包和代码变更都经过充分测试[^3]。 ### 3.6 性能优化 .NET 8.0引入了许多性能优化功能,如改进的垃圾回收器和优化的JIT编译器。可以通过分析应用程序的性能瓶颈,并利用这些新特性进行优化。 ### 3.7 安全性和维护 在迁移过程中,需要注意安全性问题,确保所有依赖项和代码都符合最新的安全标准。此外,定期更新依赖项和代码,以保持代码库的健康和可维护性。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值