当前位置: 首页 > news >正文

C#文件安全管理解析

在实际的项目开发中,我们经常需要使用到文件的I/O操作,主要包含对文件的增改删查等操作,这些基本的操作我们都是很熟悉,但是较少的人去考虑文件的安全和操作的管理等方面,例如文件的访问权限管理,文件数据的彻底删除和数据的恢复等等,这一系列的操作需要我们对.NET的相关知识有一个深刻的学习。

在本文章主要介绍文件和目录的一些基本操作,以及文件目录的权限和安全设置的相关内容。

一.DotNet文件目录常用操作:

提到文件的I/O操作,这个对于每一个开发者来说都不是陌生的事,因为这些操作是我们在项目开发过程中经常使用到的一些操作。那么在.NET中操作文件的类在System.IO命名空间下,一下介绍一下常见的I/O操作类:

DiveInfo:提供了对逻辑磁盘的基本信息访问的途径。(只能查看信息,不能做任何修改。)

System.Environment:用来枚举驱动器。(不能获取驱动器的属性)

System.Management:.NET针对WMI调用。

Directory和DircetoryInfo:用于操作目录。(前者为静态类,后者则须在实例化后调用,功能上相同)

File和FileInfo:用于操作文件。(前者为静态类,后者须实例化后调用,功能上相同)

以上介绍了一些文件的基本操作类,本次主要讲解目录和文件操作,一下给出文件和目录操作的一些基本方法:

1.文件常规操作:

(1).文件读写操作:
   /// <summary>/// 写文件/// </summary>/// <param name="fileName">文件名</param>/// <param name="content">文件内容</param>/// <param name="encoding">指定文件编码</param>protected void Write_Txt(string fileName, string content, string encoding){if (string.IsNullOrEmpty(fileName)){throw new ArgumentNullException(fileName);}if (string.IsNullOrEmpty(content)){throw new ArgumentNullException(content);}if (string.IsNullOrEmpty(encoding)){throw new ArgumentNullException(encoding);}var code = Encoding.GetEncoding(encoding);var htmlfilename = HttpContext.Current.Server.MapPath("Precious\\" + fileName + ".txt");var str = content;var sw = StreamWriter.Null;try{using (sw = new StreamWriter(htmlfilename, false, code)){sw.Write(str);sw.Flush();}}catch (IOException ioex){throw new IOException(ioex.Message);}catch (Exception ex){throw new Exception(ex.Message);}finally{sw.Close();}}/// <summary>/// 读文件/// </summary>/// <param name="filename">文件路径</param>/// <param name="encoding">文件编码</param>/// <returns></returns>protected string Read_Txt(string filename, string encoding){if (string.IsNullOrEmpty(filename)){throw new ArgumentNullException(filename);}if (string.IsNullOrEmpty(encoding)){throw new ArgumentNullException(encoding);}var code = Encoding.GetEncoding(encoding);var temp = HttpContext.Current.Server.MapPath("Precious\\" + filename + ".txt");var str = string.Empty;if (!System.IO.File.Exists(temp)) return str;var sr = StreamReader.Null;try{using (sr = new StreamReader(temp, code)){str = sr.ReadToEnd();}}catch (IOException ioex){throw new IOException(ioex.Message);}catch (Exception ex){throw new Exception(ex.Message);}finally{sr.Close();}return str;}
(2).文件附加操作:
    /// <summary>/// 拷贝文件/// </summary>/// <param name="orignFile">原始文件</param>/// <param name="newFile">新文件路径</param>public static void FileCoppy(string orignFile, string newFile){if (string.IsNullOrEmpty(orignFile)){throw new ArgumentException(orignFile);}if (string.IsNullOrEmpty(newFile)){throw new ArgumentException(newFile);}System.IO.File.Copy(orignFile, newFile, true);}/// <summary>/// 删除文件/// </summary>/// <param name="path">路径</param>public static void FileDel(string path){if (string.IsNullOrEmpty(path)){throw new ArgumentException(path);}System.IO.File.Delete(path);}/// <summary>/// 移动文件/// </summary>/// <param name="orignFile">原始路径</param>/// <param name="newFile">新路径</param>public static void FileMove(string orignFile, string newFile){if (string.IsNullOrEmpty(orignFile)){throw new ArgumentException(orignFile);}if (string.IsNullOrEmpty(newFile)){throw new ArgumentException(newFile);}System.IO.File.Move(orignFile, newFile);}

2.目录常规操作:

   /// <summary>/// 在当前目录下创建目录/// </summary>/// <param name="orignFolder">当前目录</param>/// <param name="newFloder">新目录</param>public static void FolderCreate(string orignFolder, string newFloder){if (string.IsNullOrEmpty(orignFolder)){throw new ArgumentException(orignFolder);}if (string.IsNullOrEmpty(newFloder)){throw new ArgumentException(newFloder);}Directory.SetCurrentDirectory(orignFolder);Directory.CreateDirectory(newFloder);}/// <summary>/// 创建文件夹/// </summary>/// <param name="path"></param>public static void FolderCreate(string path){if (string.IsNullOrEmpty(path)){throw new ArgumentException(path);}if (!Directory.Exists(path)){Directory.CreateDirectory(path);}}public static void FileCreate(string path){if (string.IsNullOrEmpty(path)){throw new ArgumentException(path);}var createFile = new FileInfo(path);if (createFile.Exists) return;var fs = createFile.Create();fs.Close();fs.Dispose();}/// <summary>/// 递归删除文件夹目录及文件/// </summary>/// <param name="dir"></param>/// <returns></returns>public static void DeleteFolder(string dir){if (string.IsNullOrEmpty(dir)){throw new ArgumentException(dir);}if (!Directory.Exists(dir)) return;foreach (var d in Directory.GetFileSystemEntries(dir)){if (System.IO.File.Exists(d)){//直接删除其中的文件System.IO.File.Delete(d);}else{//递归删除子文件夹DeleteFolder(d);}}//删除已空文件夹Directory.Delete(dir, true);}/// <summary>/// 指定文件夹下面的所有内容copy到目标文件夹下面/// </summary>/// <param name="srcPath">原始路径</param>/// <param name="aimPath">目标文件夹</param>public static void CopyDir(string srcPath, string aimPath){if (string.IsNullOrEmpty(srcPath)){throw new ArgumentNullException(srcPath);}if (string.IsNullOrEmpty(aimPath)){throw new ArgumentNullException(aimPath);}try{if (aimPath[aimPath.Length - ] != Path.DirectorySeparatorChar){aimPath += Path.DirectorySeparatorChar;}if (!Directory.Exists(aimPath)){Directory.CreateDirectory(aimPath);}var fileList = Directory.GetFileSystemEntries(srcPath);foreach (var file in fileList){if (Directory.Exists(file)){CopyDir(file, aimPath + Path.GetFileName(file));}else{System.IO.File.Copy(file, aimPath + Path.GetFileName(file), true);}}}catch (IOException ioex){throw new IOException(ioex.Message);}catch (Exception ee){throw new Exception(ee.ToString());}}/// <summary>/// 获取指定文件夹下所有子目录及文件/// </summary>/// <param name="path">详细路径</param>public static string GetFoldAll(string path){if (string.IsNullOrEmpty(path)){throw new ArgumentNullException(path);}var str =string.Empty;var thisOne = new DirectoryInfo(path);str = ListTreeShow(thisOne, , str);return str;}/// <summary>/// 获取指定文件夹下所有子目录及文件函数/// </summary>/// <param name="theDir">指定目录</param>/// <param name="nLevel">默认起始值,调用时,一般为0</param>/// <param name="rn">用于迭加的传入值,一般为空</param>/// <returns></returns>public static string ListTreeShow(DirectoryInfo theDir, int nLevel, string rn){if (theDir == null){throw new ArgumentNullException("theDir");}//获得目录DirectoryInfo[] subDirectories = theDir.GetDirectories();foreach (DirectoryInfo dirinfo in subDirectories){if (nLevel == ){rn += "├";}else{var s =string.Empty;for (int i = ; i <= nLevel; i++){s += "│&nbsp;";}rn += s + "├";}rn += "<b>" + dirinfo.Name + "</b><br />";//目录下的文件var fileInfo = dirinfo.GetFiles();foreach (FileInfo fInfo in fileInfo){if (nLevel == ){rn += "│&nbsp;├";}else{var f = string.Empty;for (int i = ; i <= nLevel; i++){f += "│&nbsp;";}rn += f + "│&nbsp;├";}rn += fInfo.Name.ToString() + " <br />";}rn = ListTreeShow(dirinfo, nLevel + , rn);}return rn;}/// <summary>/// 获取指定文件夹下所有子目录及文件(下拉框形)/// </summary>/// <param name="path">详细路径</param>///<param name="dropName">下拉列表名称</param>///<param name="tplPath">默认选择模板名称</param>public static string GetFoldAll(string path, string dropName, string tplPath){if (string.IsNullOrEmpty(path)){throw new ArgumentNullException(path);}if (string.IsNullOrEmpty(tplPath)){throw new ArgumentNullException(tplPath);}var strDrop = "<select name=\"" + dropName + "\" id=\"" + dropName + "\"><option value=\"\">--请选择详细模板--</option>";var str =string.Empty;DirectoryInfo thisOne = new DirectoryInfo(path);str = ListTreeShow(thisOne, , str, tplPath);return strDrop + str + "</select>";}/// <summary>/// 获取指定文件夹下所有子目录及文件函数/// </summary>/// <param name="theDir">指定目录</param>/// <param name="nLevel">默认起始值,调用时,一般为0</param>/// <param name="rn">用于迭加的传入值,一般为空</param>/// <param name="tplPath">默认选择模板名称</param>/// <returns></returns>public static string ListTreeShow(DirectoryInfo theDir, int nLevel, string rn, string tplPath){if (theDir == null){throw new ArgumentNullException("theDir");}//获得目录DirectoryInfo[] subDirectories = theDir.GetDirectories();foreach (DirectoryInfo dirinfo in subDirectories){rn += "<option value=\"" + dirinfo.Name + "\"";if (string.Equals(tplPath, dirinfo.Name, StringComparison.CurrentCultureIgnoreCase)){rn += " selected ";}rn += ">";if (nLevel == ){rn += "┣";}else{string s = string.Empty;for (int i = ; i <= nLevel; i++){s += "│&nbsp;";}rn += s + "┣";}rn += "" + dirinfo.Name + "</option>";//目录下的文件FileInfo[] fileInfo = dirinfo.GetFiles();foreach (FileInfo fInfo in fileInfo){rn += "<option value=\"" + dirinfo.Name + "/" + fInfo.Name + "\"";if (string.Equals(tplPath, fInfo.Name, StringComparison.CurrentCultureIgnoreCase)){rn += " selected ";}rn += ">";if (nLevel == ){rn += "│&nbsp;├";}else{string f = string.Empty;for (int i = ; i <= nLevel; i++){f += "│&nbsp;";}rn += f + "│&nbsp;├";}rn += fInfo.Name + "</option>";}rn = ListTreeShow(dirinfo, nLevel + , rn, tplPath);}return rn;}/// <summary>/// 获取文件夹大小/// </summary>/// <param name="dirPath">文件夹路径</param>/// <returns></returns>public static long GetDirectoryLength(string dirPath){if (string.IsNullOrEmpty(dirPath)){throw new ArgumentNullException(dirPath);}if (!Directory.Exists(dirPath)){return ;}long len = ;DirectoryInfo di = new DirectoryInfo(dirPath);foreach (FileInfo fi in di.GetFiles()){len += fi.Length;}DirectoryInfo[] dis = di.GetDirectories();if (dis.Length > ){for (int i = ; i < dis.Length; i++){len += GetDirectoryLength(dis[i].FullName);}}return len;}/// <summary>/// 获取指定文件详细属性/// </summary>/// <param name="filePath">文件详细路径</param>/// <returns></returns>public static string GetFileAttibe(string filePath){if (string.IsNullOrEmpty(filePath)){throw new ArgumentNullException(filePath);}var str = string.Empty;FileInfo objFi = new FileInfo(filePath);str += "详细路径:" + objFi.FullName + "<br>文件名称:" + objFi.Name + "<br>文件长度:" + objFi.Length + "字节<br>创建时间" + objFi.CreationTime.ToString() + "<br>最后访问时间:" + objFi.LastAccessTime.ToString() + "<br>修改时间:" + objFi.LastWriteTime.ToString() + "<br>所在目录:" + objFi.DirectoryName + "<br>扩展名:" + objFi.Extension;return str;}

二.DotNet文件目录访问管理:

1.文件目录权限概述:

提到权限这个概念,这对于每一个开发者都是再熟悉不过的,因为我们在开发项目时,都会考虑用户权限管理等等,但是文件的权限操作呢?这里我们就简单的介绍一下.NET中对文件访问权限的访问和设置。文件权限中的访问控制列表: 自由访问控制列表(DACL):Microsoft Windows NT和更高版本用于保护资源的机制;系统访问控制列表(SACL):一种控制与资源关联的审核消息的机制。System.Security.AccessControl命名空间通过一些类提供对访问控制列表的访问。DiectorySecurity:该类指定目录的访问控制和审核安全。指定系统目录的访问权限以及访问尝试的审核方式。FileSecurity:该类指定系统文件的访问权限以及如何审核访问尝试。

下面介绍一下文件权限操作的类和方法:

(1).FileStream类GetAccessControl():检索文件的安全对象:
[SecuritySafeCritical]
public FileSecurity GetAccessControl()
{if (this._handle.IsClosed){__Error.FileNotOpen();}return new FileSecurity(this._handle, this._fileName, AccessControlSections.Group | AccessControlSections.Owner | AccessControlSections.Access);
}
[SecurityCritical, SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
internal FileSecurity(SafeFileHandle handle, string fullPath, AccessControlSections includeSections) : base(false, handle, includeSections, false)
{if (fullPath != null){new FileIOPermission(FileIOPermissionAccess.NoAccess, AccessControlActions.View, fullPath).Demand();}else{new FileIOPermission(PermissionState.Unrestricted).Demand();}
}
(2).FileStream类SetAccessControl():保存设置。
[SecuritySafeCritical]
public void SetAccessControl(FileSecurity fileSecurity)
{if (fileSecurity == null){throw new ArgumentNullException("fileSecurity");}if (this._handle.IsClosed){__Error.FileNotOpen();}fileSecurity.Persist(this._handle, this._fileName);
}

2.文件共享操作实例:        

    /// <summary>/// 共享文档操作/// </summary>public class FileSharingOperationHelper{public static bool ConnectState(string path){if (string.IsNullOrEmpty(path)){throw new ArgumentNullException(path);}return ConnectState(path, "", "");}/// <summary>/// 连接远程共享文件夹/// </summary>/// <param name="path">远程共享文件夹的路径</param>/// <param name="userName">用户名</param>/// <param name="passWord">密码</param>/// <returns></returns>public static bool ConnectState(string path, string userName, string passWord){var proc = new Process();try{proc.StartInfo.FileName = "cmd.exe";proc.StartInfo.UseShellExecute = false;proc.StartInfo.RedirectStandardInput = true;proc.StartInfo.RedirectStandardOutput = true;proc.StartInfo.RedirectStandardError = true;proc.StartInfo.CreateNoWindow = true;proc.Start();var dosLine = "net use " + path + " " + passWord + " /user:" + userName;proc.StandardInput.WriteLine(dosLine);proc.StandardInput.WriteLine("exit");while (!proc.HasExited){proc.WaitForExit();}var errormsg = proc.StandardError.ReadToEnd();proc.StandardError.Close();if (!string.IsNullOrEmpty(errormsg)){throw new Exception(errormsg);}}catch (Exception ex){throw new Exception(ex.Message);}finally{proc.Close();proc.Dispose();}return true;}/// <summary>/// 向远程文件夹保存本地内容,或者从远程文件夹下载文件到本地/// </summary>/// <param name="src">要保存的文件的路径,如果保存文件到共享文件夹,这个路径就是本地文件路径如:@"D:\1.avi"</param>/// <param name="dst">保存文件的路径,不含名称及扩展名</param>/// <param name="fileName">保存文件的名称以及扩展名</param>public static void Transport(string src, string dst, string fileName){if (string.IsNullOrEmpty(src)){throw new ArgumentNullException(src);}if (string.IsNullOrEmpty(dst)){throw new ArgumentNullException(dst);}if (string.IsNullOrEmpty(fileName)){throw new ArgumentNullException(fileName);}FileStream inFileStream = null;FileStream outFileStream = null;try{inFileStream = new FileStream(src, FileMode.Open);if (!Directory.Exists(dst)){Directory.CreateDirectory(dst);}dst = dst + fileName;outFileStream = new FileStream(dst, FileMode.OpenOrCreate);var buf = new byte[inFileStream.Length];int byteCount;while ((byteCount = inFileStream.Read(buf, , buf.Length)) > ){outFileStream.Write(buf, , byteCount);}}catch (IOException ioex){throw new IOException(ioex.Message);}catch (Exception ex){throw new Exception(ex.Message);}finally{if (inFileStream != null){inFileStream.Flush();inFileStream.Close();}if (outFileStream != null){outFileStream.Flush();outFileStream.Close();}}}}

文件权限的规则:容器的访问规则可能被配置为不仅应用于对象本身,而且还应用于它的子对象、子容器或这两者。每个访问规则不是显示的就是继承的。DACL可以有对象的所有者任意修改,还可以由所有者已经给予其梗概DACL权限的任何更改。对象的安全描述包含另一个规则列表,称为系统访问权限列表(SACL),该列表将控制系统对对象执行哪个类型的审核。审核是一种具有安全敏感性的操作。在windows中,审核只能由本地安全机构(LSA)生成,LSA是唯一允许向安全事件日志中写入的组件。

三.DotNet彻底删除文件操作:

1.文件彻底删除概述:

看到文件删除,可能有人会问,前面不是已经介绍过文件的删除操作吗?为什么这里还需要详细的介绍。不错,上面的确介绍了文件和目录的删除方法,但是这里是介绍如何彻底的删除文件。我们常规的删除文件和文件格式化,一般是可以被恢复的。我们在操作删除的时候,只是将文件的索引给删除了,并没有删除实际的内容。文件的索引记录了文件在磁盘中的位置信息,当执行删除操作时,只是从文件分配聊表中删除了目录。

那么可能会有人问,怎么讲文件彻底的删除呢?文件的粉碎,其实就是在删除文件分配列表的同时,把文件在磁盘上占用的所有扇区数据置为0。

在.NET中提供了两种文件彻底的方法:

(1).调用系统API来完成这样的“粉碎”操作。

(2).在删除文件之前先删除文件的所有内容,然后在执行删除操作,被称为“假粉碎”。(此方法可以被人恢复文件,但是恢复的数据只是文件中的0)

为了文件安全,可以采用多轮粉碎的方式:第一轮,通过文件操作Windows API,找到原始文件的铭文在存储器上所载区域,逐字符逐位进行完全填充,全部填充为0。第二轮,通过磁盘操作WindowsAPI找到原始文件或目录在FAT表中的位置,将原始文件或目录在FAT表中项清零。第三轮,通过磁盘操作WindowsAPI,找到原始文件或目录在备份FAT表的位置,将原始文件或目录在备份FAT表中的表项清零。

2.文件彻底删除实例:

    /// <summary>/// 粉碎文件操作/// </summary>public class KillFileHelper{/// <summary>/// 强力粉碎文件,文件如果被打开,很难粉碎/// </summary>/// <param name="filename">文件全路径</param>/// <param name="deleteCount">删除次数</param>/// <param name="randomData">随机数据填充文件,默认true</param>/// <param name="blanks">空白填充文件,默认false</param>/// <returns>true:粉碎成功,false:粉碎失败</returns>public static bool KillFile(string filename, int deleteCount, bool randomData = true, bool blanks = false){if (string.IsNullOrEmpty(filename)){throw new ArgumentNullException(filename);}const int bufferLength = ;var ret = true;try{using (var stream = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)){var f = new FileInfo(filename);var count = f.Length;long offset = ;var rowDataBuffer = new byte[bufferLength];while (count >= ){var iNumOfDataRead = stream.Read(rowDataBuffer, , bufferLength);if (iNumOfDataRead == ){break;}if (randomData){var randombyte = new Random();randombyte.NextBytes(rowDataBuffer);}else if (blanks){for (var i = ; i < iNumOfDataRead; i++)rowDataBuffer[i] = ;}else{for (var i = ; i < iNumOfDataRead; i++)rowDataBuffer[i] = Convert.ToByte(Convert.ToChar(deleteCount));}// 写新内容到文件。for (var i = ; i < deleteCount; i++){stream.Seek(offset, SeekOrigin.Begin);stream.Write(rowDataBuffer, , iNumOfDataRead);}offset += iNumOfDataRead;count -= iNumOfDataRead;}}//每一个文件名字符代替随机数从0到9。var newName = "";do{var random = new Random();var cleanName = Path.GetFileName(filename);var dirName = Path.GetDirectoryName(filename);var iMoreRandomLetters = random.Next();// 为了更安全,不要只使用原文件名的大小,添加一些随机字母。for (var i = ; i < cleanName.Length + iMoreRandomLetters; i++){newName += random.Next().ToString();}newName = dirName + "\\" + newName;} while (File.Exists(newName));// 重命名文件的新的随机的名字。File.Move(filename, newName);File.Delete(newName);}catch{//可能其他原因删除失败了,使用我们自己的方法强制删除var matchPattern = @"(?<=\s+pid:\s+)\b(\d+)\b(?=\s+)";try{//要检查被那个进程占用的文件var fileName = filename;var tool = new Process { StartInfo = { FileName = "handle.exe", Arguments = fileName + " /accepteula", UseShellExecute = false, RedirectStandardOutput = true } };tool.Start();tool.WaitForExit();var outputTool = tool.StandardOutput.ReadToEnd();foreach (Match match in Regex.Matches(outputTool, matchPattern)){//结束掉所有正在使用这个文件的程序Process.GetProcessById(int.Parse(match.Value)).Kill();}File.Delete(fileName);}catch{ret = false;}}return ret;}}

四.DotNet文件加密解密操作:

上面介绍了文件的基本操作,文件权限操作,文件的删除操作,最后介绍一下文件的加密和解密操作。File和FileInfo类对文件加密进行了进一步的封装,提供了Encrypt和Decrypt方法用来对文件加密和解密。这两种方法要求文件系统必须为NFTS系统,对操作系统版本也要求必须是NT以上版本,使用该方法加密的文件,必须由同一用户才能进行解密。

具体看一下该方法的实现代码:

1.Encrypt():文件加密操作。

[SecuritySafeCritical]
public static void Encrypt(string path)
{if (path == null){throw new ArgumentNullException("path");}string fullPathInternal = Path.GetFullPathInternal(path);new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();if (!Win32Native.EncryptFile(fullPathInternal)){int errorCode = Marshal.GetLastWin32Error();if (errorCode == ){DriveInfo info = new DriveInfo(Path.GetPathRoot(fullPathInternal));if (!string.Equals("NTFS", info.DriveFormat)){throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS"));}}__Error.WinIOError(errorCode, fullPathInternal);}
}

2.Decrypt():文件解密操作。

[SecuritySafeCritical]
public static void Decrypt(string path)
{if (path == null){throw new ArgumentNullException("path");}string fullPathInternal = Path.GetFullPathInternal(path);new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();if (!Win32Native.DecryptFile(fullPathInternal, )){int errorCode = Marshal.GetLastWin32Error();if (errorCode == ){DriveInfo info = new DriveInfo(Path.GetPathRoot(fullPathInternal));if (!string.Equals("NTFS", info.DriveFormat)){throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS"));}}__Error.WinIOError(errorCode, fullPathInternal);}
}

五.总结:

以上简单的介绍了文件的操作和文件的权限管理方法,如果需要更加深入的了解这些操作方法,可以查看msdn,或者查看.NET的“垫片”,查看相应的接口。在当代社会中,数据安全和文件安全都是很重要的,我们应该更加深入的去学习安全知识,提高系统的稳定性。

相关文章:

C#文件安全管理解析

在实际的项目开发中&#xff0c;我们经常需要使用到文件的I/O操作&#xff0c;主要包含对文件的增改删查等操作&#xff0c;这些基本的操作我们都是很熟悉&#xff0c;但是较少的人去考虑文件的安全和操作的管理等方面&#xff0c;例如文件的访问权限管理&#xff0c;文件数据的…...

基于Dubbo分布式学校信息管理系统设计与实现

一、引言 1.1 课题背景 随着时代的发展与进步,计算机网络也随之日益完善,渐渐覆盖了我们生活的各个方面。在信息化和数字化的时代背景下,使用计算机管理学校信息来提升教育工作的质量和效率,是大势所趋,所以近年来,随着网络技术的不断发展,使用信息管理系统的学校越来…...

oracle面试问题和笔记整理

oracle面试笔记 ORACLE 面试问题-技术篇(2) 如何判断数据库的时区? 解答:SELECT DBTIMEZONE FROM DUAL; 解释GLOBAL_NAMES设为TRUE的用途 解答:GLOBAL_NAMES指明联接数据库的方式。如果这个参数设置为TRUE, 在建立数据库链接时就必须用相同的名字连结远程数据库 23。如何…...

Hadoop_Yarn实践 (三) => (Yarn的基础架构、原理、容量/公平调度器、Tool接口、Yarn常用命令、核心参数)

目录 Hadoop_HDFS、Hadoop_MapReduce、Hadoop_Yarn 实践 (三)一、Hadoop_HDFS二、Hadoop_MapReduce三、Hadoop_Yarn1、Yarn资源调度1.1、基础架构1.2、Yarn的工作调度机制&#xff08;Job提交过程&#xff09;1.3、Yarn 调度器和调度算法1.3.1、先进先出调度器&#xff08;FIFO…...

postgresql 从应用角度看快照snapshot使用,事务隔离控制不再神密

​专栏内容&#xff1a;postgresql内核源码分析 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 快照使用 快照是事务中使用&#xff0c;配合事务的隔离级别&#xff0c;体现出不同的可见性。…...

mysql(mariadb)读写分离部署

目录 一、原理 二、准备环境 三、部署mysql主从复制 1.五台服务器下载mariadb 2.修改master配置文件&#xff0c;重启数据库 3.登录mysql创建replication 4.从服务器登录验证 5.获得master服务器 DB的相关信息 6.备份master原有数据 7.修改slave1、slave2配置 8. 进入…...

ES-工作原理

前言 ​ 搜索引擎是对数据的检索&#xff0c;而数据总体分为两种&#xff1a;结构化数据和非结构化数据。而对于结构化数据&#xff0c;因为他们具有特定的结构&#xff0c;所以一般都是可以通过关系型数据库MySQL/oracle的二维表的方式存储和搜索&#xff0c;也可以建立索引。…...

C++小结(4)

C 字符串 C 提供了两种类型的字符串表示形式&#xff1a; C 风格字符串C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言&#xff0c;并在 C 中继续得到支持。字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此&#xff0c;一个以 null 结尾的字…...

Java框架之spring 的 messaging

写在前面 本文看下spring message相关的内容。 1&#xff1a;Message&#xff1f;Messaging&#xff1f; Message是消息的意思&#xff0c;是一个名词。而Messaging是一个动名词&#xff0c;是将消息发送出去的意思&#xff0c;因此&#xff0c;我们的消息系统是messaging s…...

linux使用grep命令查询nginx的进程情况时总是出现 grep --color=auto nginx

问题&#xff1a; 每次使用ps aux | grep 服务名 命令查询某个服务的进程时&#xff0c;总会出现一条grep --colorauto 服务名 例如&#xff1a; ps aux | grep nginx # 会出现图片中的情况解答&#xff1a; 这是因为grep 也是一条命令&#xff0c;它在输出时&#xff0c;会…...

FFmpeg音视频开发知识点(二)

系列文章目录 FFmpeg音视频开发知识点&#xff08;一&#xff09; 文章目录 系列文章目录前言一、AAC音频编码1. ffmpeg编译第三方的libfdk_aac2. S16重采样FLTP 二、AAC音频解码总结 前言 该篇讲解一下&#xff0c;音频编解码中的难点&#xff0c;以及开发过程中遇到问题&am…...

【Java可执行命令】(十)JAR文件签名工具 jarsigner:通过数字签名及验证保证代码信任与安全,深入解析 Java的 jarsigner命令~

Java可执行命令之jarsigner 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法3.1.1 可选参数&#xff1a;jarsigner -keystore < url>3.1.2 可选参数&#xff1a;jarsigner -storepass <口令>3.1.3 可选参数&#xff1a;jarsigner -keypass <口令>3.1.4 可选参…...

c#调用c++ dll,Release版本内存访问错误

最近遇到个比较经典的案例&#xff0c;在c#中调用yara进行文件检测&#xff0c;yara是c编写的一个非常强大库&#xff0c;github有个大佬用c#对其进行了封装&#xff0c;使其能在跨平台下&#xff0c;只需编译yara的so或dll就能直接跑。但总是在Release版本下时不时就崩溃&…...

内网安全:Cobalt Strike 与 MSF 联动( 会话 相互转移 )

内网安全&#xff1a;Cobalt Strike 与 MSF 联动&#xff08; 会话 相互转移 &#xff09; 在渗透中&#xff0c;有时候 Cobalt Strike 会话可能会受限制&#xff0c;所以我们需要把 Cobalt Strike 会话转移到 MSF 上进行后面的渗透。也有的时候会话在 MSF 上&#xff0c;但是…...

性能测试讲解超详细Jmeter

目录 什么是性能 性能测试的目的 功能测试和性能测试 基准测试 负载测试 稳定性测试 压力测试 并发测试 总结 性能测试指标 响应时间 并发数 吞吐量 点击数 错误率 资源使用率 总结 性能测试流程 性能测试需求分析 性能测试计划和方案 ​编辑性能测试用例​编辑 性…...

微服务 – Spring Cloud – Nacos 配置中心

微服务 – Spring Cloud – Nacos 配置中心 文章目录 微服务 – Spring Cloud – Nacos 配置中心打开nacos面板新建配置引入依赖配置文件启动类业务类打开nacos面板新建配置 Data ID: nacos-config-client-dev.yaml Group: DEV-CLOUD2023 config:info: config info lalalal …...

超细,设计一个“完美“的测试用例,用户登录模块实例...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 好的测试用例一定…...

【C#】文件拖拽,获取文件路径

系列文章 【C#】编号生成器&#xff08;定义单号规则、固定字符、流水号、业务单号&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器&#xff08;开始日期、结束日期&#xff09; 本文链接&#xff1a;h…...

SAP PI/PO初步了解 2023.07.03

SAP PI/PO 是SAP 提供的一种集成中间件解决方案&#xff0c;用于在组织内部或不同组织之间实现系统的无缝通信和数据交换。它使企业能够以统一高效的方式集成各种应用和系统&#xff0c;无论这些系统的技术平台或数据格式如何。 以下是关于SAP PI/PO的简要概述&#xff1a; 1…...

Java中生产者消费者模型

在Java中&#xff0c;生产者消费者模型是一种常见的多线程编程模型&#xff0c;用于解决生产者和消费者之间的数据交互问题。 简介 生产者&#xff08;Producer&#xff09;负责生成数据&#xff0c;并将数据放入共享的缓冲区&#xff08;队列&#xff09;中。消费者&#xf…...

测试Hyperledger Fabric环境

首先进入fabric-samples目录中的first-networked 子目录 cd fabric-samples/first-network 在first-network目录下有一个自动化脚本byfn.sh,可以使用-help参数查看相应的可 用命令&#xff0c;在命令提示符中输入如下命令&#xff1a; ./byfn.sh --help命令执行成功后&#…...

ClickHouse查询sql长度超超过最大限制

ClickHouse查询sql长度超超过最大限制 Max query size exceeded ClickHouse exception, message: Code: 62. DB::Exception: Syntax error: failed at position 262102 (‘fwm00ud6a3ynu0kaxr.ya0eyemkbzdvrxkhwgchccll’) (line 10406, col 17): fwm00ud6a3ynu0kaxr.ya0eyemk…...

【Axure教程】拖动调整行高列宽的表格

表格是在系统软件中非常常用的工具。表格通常由行和列组成&#xff0c;用于以结构化的方式显示和组织数据。它们在各种场景中都有广泛的应用&#xff0c;包括数据分析、数据录入、报表生成、项目管理和数据可视化等领域。 今天作者就教大家如何在Axure里制作一个能通过鼠标拖动…...

中间件-netty(1)

netty 前言篇 文章目录 一、IO基础篇1.概念1.1 阻塞(Block)和非阻塞(Non-Block)1.2 同步(Synchronization)和异步(Asynchronous)1.3 BIO 与 NIO 对比1.3.1 面向流与面向缓冲1.3.2 阻塞与非阻塞1.3.3 选择器的问世 2.NIO 和 BIO 如何影响应用程序的设计2.1 API调用2.2 数据处理2…...

【方法】想把PDF文档转换成PPT,如何操作?

很多小伙伴在工作中&#xff0c;会使用PDF或者PPT来展示内容。那如果需要把PDF转换成PPT&#xff0c;要如何操作呢&#xff1f; 我们知道&#xff0c;PPT转换成PDF很容易操作&#xff0c;只需通过PPT的【导出】选项&#xff0c;就可以直接转换成PDF&#xff1b;还可以通过“另…...

Linux--设置目录或文件的默认权限:umask权限掩码

目录起始权限是从777&#xff0c;普通文件起始权限从666 为何我们创建一个目录或文件&#xff0c;默认权限是你所看到的样子&#xff1f; 因为凡是在umask中出现的权限&#xff0c;都不应该在最终权限中出现&#xff01; 最终权限起始权限&&#xff08;~umask&#xff09…...

C++实现websocket单server单client全双工通信(基于boost!!!)

自身环境&#xff1a;ubuntu18.04gcc7.5.0boost1.7,3 环境配置 gcc或者g一般都有&#xff0c;这里主要介绍一下boost的配置方法   执行如下代码&#xff1a; wget https://boostorg.jfrog.io/artifactory/main/release/1.73.0/source/boost_1_73_0.tar.bz2 --no-check-cert…...

好用的网址5

搜番神器&#xff1a;https://trace.moe/ Online converter&#xff1a;Online converter - convert video, images, audio and documents for free 格式转换 GIF Explode&#xff1a;https://gif-explode.com/ SongDonkey&#xff1a;SongDonkey - AI Online Audio Split…...

做项目去实习到底做的什么?

300万字&#xff01;全网最全大数据学习面试社区等你来&#xff01; 今天是手机编辑的文章&#xff0c;说说做项目/实习这回事。 我之前发过一些视频&#xff0c;讲校招四要素的&#xff0c;其中一个很重要的部分就是实习。 对社招同学来说&#xff0c;就简单了&#xff0c;面试…...

VSC++: 验证身份证

缘由https://ask.csdn.net/questions/1082358 void 验证身份证() {//缘由https://ask.csdn.net/questions/1082358int 权重[] { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }, 个 0, j 0, a 0, he 0;char M[] "10X98765432", 身份号[100][20]{};//…...