FileStream 总结

article/2025/9/27 6:47:31

FileStream

如何去理解FileStream?

我们磁盘的中任何文件都是通过2进制组成,最为直观的便是记事本了,当我们新建一个记事本时,它的大小是0KB, 我们每次输入一个数字或

字母时文件便会自动增大4kb,可见随着我们输入的内容越来越多,文件也会相应增大,同理当我们删除文件内容时,文件也会相应减小,对了,

往于各个地方,FileStream也是一样,byte可以通过FileStream进行传输,这样我们便能在计算机上对任何文件进行一系列的操作了。

FileStream 的重要性

FileStream 顾名思义文件流,我们电脑上的文件都可以通过文件流进行操作,例如文件的复制,剪切,粘贴,删除, 本地文件上传,下载,等许

多重要的功能都离不开文件流,所以文件流不仅在本机上非常重要,在如今的网络世界也是万万不能缺少的,想象一下我们开启虚机后,直接从本

地复制一个文件到虚机上,是多么方便,如果没有文件流,这个将难以想象。(大家别误解,文件流无法直接通过网络进行传输,而是

通过网络流将客户端上传的文件传到端接收,然后通过文件流进行处理,下载正好相反)

FileStream 常用构造函数介绍(可能理解上有点复杂,请大家务必深刻理解)

*1: FileStream(SafeFileHandle, FileAccess)

非托管参数SafeFileHandle简单介绍

SafeFileHandle :是一个文件安全句柄,这样的解释可能大家一头雾水,

别急,大家先不要去理睬这深邃的含义,只要知道这个类型是c#非托管资源,

也就是说它能够调用非托管资源的方法,而且不属于c#回收机制,所以我们必须

使用GC手动或其他方式(Finalize 或Dispose方法)进行非托管资源的回收,所以

SafeFileHandle是个默默无闻的保镖 ,一直暗中保护FileStream和文件的安全

为了能让大家更好的理解这个保镖,请看第一段代码:

会什么会报错呢?其实程序被卡在 Console.ReadLine()这里,FileStream并没有

被释放,系统不知道这个文件是否还有用﹐所以帮我们保护这个文件

(那个非托管资源SafeFileHandle所使用的内存还被程序占用着)

所以SafeFileHandled 在内部保护了这个文件从而报出了这个异常

如果我们将流关闭后,这个问题也就不存在了

所以又回到了一个老问题上面,我们每次使用完FileStream后都必须将他关闭并释放资源

*2: FileStream(String, FileMode)

String 参数表示文件所在的地址,FIleMode是个枚举,表示确定如何打开或创建文件。

FileMode枚举参数包含以下内容:

成员名称

说明

Append

打开现有文件并查找到文件尾,或创建新文件。FileMode.Append 只能同 FileAccess.Write 一起使用。

Create

指定操作系统应创建新文件。如果文件已存在,它将被改写。这要求 FileIOPermissionAccess.Write。 System.IO.FileMode.Create 等效于这样的请求:如果文件不存在,则使用 CreateNew;否则使用 Truncate。

CreateNew

指定操作系统应创建新文件。此操作需要 FileIOPermissionAccess.Write。如果文件已存在,则将引发 IOException。

Open

指定操作系统应打开现有文件。打开文件的能力取决于 FileAccess 所指定的值。如果该文件不存在, 则引发 System.IO.FileNotFoundException。

OpenOrCreate

指定操作系统应打开文件(如果文件存在);否则,应创建新文件。如果用 FileAccess.Read 打开文件,则需要 FileIOPermissionAccess.Read。如果文件访问为 FileAccess.Write 或 FileAccess.ReadWrite,则需要 FileIOPermissionAccess.Write。如果文件访问为 FileAccess.Append,则需要 FileIOPermissionAccess.Append。

Truncate

指定操作系统应打开现有文件。文件一旦打开,就将被截断为零字节大小。此操作需要 FileIOPermissionAccess.Write。 试图从使用 Truncate 打开的文件中进行读取将导致异常。

*3: FileStream(IntPtr, FileAccess, Boolean ownsHandle)

FileAccess 参数也是一个枚举, 表示对于该文件的操作权限

ReadWrite

对文件的读访问和写访问。可从文件读取数据和将数据写入文件

Write

文件的写访问。可将数据写入文件。同 Read组合即构成读/写访问权

Read

对文件的读访问。可从文件中读取数据。同 Write组合即构成读写访问权

参数ownsHandle:也就是类似于前面和大家介绍的SafeFileHandler,有2点必须注意:

1. 对于指定的文件句柄,操作系统不允许所请求的 access,例如,当 access 为 Write 或 ReadWrite 而文件句柄设置为只读访问时,会报出异常。所以 ownsHandle才是老大,FileAccess的权限应该在ownsHandle的范围之内

2. FileStream 假定它对句柄有独占控制权。当 FileStream 也持有句柄时,读取、写入或查找可能会导致数据破坏。为了数据的安全,请使用句柄前调用 ,并避免在使用完句柄后调用 Close 以外的任何方法。

*4: FileStream(String, FileMode, FileAccess, FileShare)

FileShare:同样是个枚举类型:确定文件如何由进程共享。

Delete

允许随后删除文件。

Inheritable

使文件句柄可由子进程继承。Win32 不直接支持此功能。

None

谢绝共享当前文件。文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。

Read

允许随后打开文件读取。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。

ReadWrite

允许随后打开文件读取或写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。

Write

允许随后打开文件写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。

*5: FileStream(String, FileMode, FileAccess, FileShare, Int32, Boolean async )

Int32:这是一个缓冲区的大小,大家可以按照自己的需要定制,

Boolean async:是否异步读写,告诉FileStream示例,是否采用异步读写

*6: FileStream(String, FileMode, FileAccess, FileShare, Int32, FileOptions)

FileOptions:这是类似于FileStream对于文件操作的高级选项

FileStream 常用属性介绍

*1:CanRead :指示FileStream是否可以读操作

*2:CanSeek:指示FileStream是否可以跟踪查找流操作

*3:IsAsync:FileStream是否同步工作还是异步工作

*4:Name:FileStream的名字 只读属性

*5:ReadTimeout :设置读取超时时间

*6:SafeFileHandle : 文件安全句柄 只读属性

*7:position:当前FileStream所在的流位置

FileStream 常用方法介绍

以下方法重写了Stream的一些虚方法

1:IAsyncResult BeginRead 异步读取

2:IAsyncResult BeginWrite 异步写

3:void Close 关闭当前FileStream

4:void EndRead 异步读结束

5:void EndWrite 异步写结束

6:void Flush 立刻释放缓冲区,将数据全部导出到基础流(文件中)

7:int Read 一般读取

8:int ReadByte 读取单个字节

9:long Seek 跟踪查找流所在的位置

10:void SetLength 设置FileStream的长度

11:void Write 一般写

12:void WriteByte写入单个字节

属于FileStream独有的方法

*1:FileSecurity GetAccessControl()

这个不是很常用,FileSecurity 是文件安全类,直接表达当前文件的访问控制列表(ACL)的符合当前文件权限的项目,ACL大家有个了解就行,以后会单独和大家讨论下ACL方面的知识

*2: void Lock(long position,long length)

这个Lock方法和线程中的Look关键字很不一样,它能够锁住文件中的某一部分,非常的强悍!用了这个方法我们能够精确锁定住我们需要锁住的文件的部分内容

*3: void SetAccessControl(FileSecurity fileSecurity)

和GetAccessControl很相似,ACL技术会在以后单独介绍

*4: void Unlock (long position,long length)

正好和lock方法相反,对于文件部分的解锁

文件的新建和拷贝(主要演示文件同步和异步操作)

首先我们尝试DIY一个IFileConfig

    /// <summary>/// 文件配置接口/// </summary>public interface IFileConfig{string FileName { get; set; }bool IsAsync { get; set; }}

复制

创建文件配置类CreateFileConfig,用于添加文件一些配置设置,实现添加文件的操作

    /// <summary>/// 创建文件配置类/// </summary>public class CreateFileConfig : IFileConfig{// 文件名public string FileName { get; set; }//是否异步操作public bool IsAsync { get; set; }//创建文件所在urlpublic string CreateUrl { get; set; }}

复制

让我们定义一个文件流测试类:FileStreamTest 来实现文件的操作

    /// <summary>/// FileStreamTest 类/// </summary>public class FileStreamTest

复制

在该类中实现一个简单的Create方法用来同步或异步的实现添加文件,FileStream会根据配置类去选择相应的构造函数,实现异步或同步的添加方式

       /// <summary>/// 添加文件方法/// </summary>/// <param name="config"> 创建文件配置类</param>public void Create(IFileConfig config){lock (_lockObject){//得到创建文件配置类对象var createFileConfig = config as CreateFileConfig;//检查创建文件配置类是否为空if (this.CheckConfigIsError(config)) return;//假设创建完文件后写入一段话,实际项目中无需这么做,这里只是一个演示char[] insertContent = "HellowWorld".ToCharArray();//转化成 byte[]byte[] byteArrayContent = Encoding.Default.GetBytes(insertContent, 0, insertContent.Length);//根据传入的配置文件中来决定是否同步或异步实例化stream对象FileStream stream = createFileConfig.IsAsync ?new FileStream(createFileConfig.CreateUrl, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, true): new FileStream(createFileConfig.CreateUrl, FileMode.Create);using (stream){// 如果不注释下面代码会抛出异常,google上提示是WriteTimeout只支持网络流// stream.WriteTimeout = READ_OR_WRITE_TIMEOUT;//如果该流是同步流并且可写if (!stream.IsAsync && stream.CanWrite)stream.Write(byteArrayContent, 0, byteArrayContent.Length);else if (stream.CanWrite)//异步流并且可写stream.BeginWrite(byteArrayContent, 0, byteArrayContent.Length, this.End_CreateFileCallBack, stream);stream.Close();}}}

复制

如果采用异步的方式则最后会进入End_CreateFileCallBack回调方法,result.AsyncState对象就是上图stream.BeginWrite()方法的最后一个参数

还有一点必须注意的是每一次使用BeginWrite()方法事都要带上EndWrite()方法,Read方法也一样

        /// <summary>///  异步写文件callBack方法/// </summary>/// <param name="result">IAsyncResult</param>private void End_CreateFileCallBack(IAsyncResult result){//从IAsyncResult对象中得到原来的FileStreamvar stream = result.AsyncState as FileStream;//结束异步写Console.WriteLine("异步创建文件地址:{0}", stream.Name);stream.EndWrite(result);Console.ReadLine();}

复制

文件复制的方式思路比较相似,首先定义复制文件配置类,由于在异步回调中用到该配置类的属性,所以新增了文件流对象和相应的字节数组

    /// <summary>/// 文件复制/// </summary>public class CopyFileConfig : IFileConfig{// 文件名public string FileName { get; set; }//是否异步操作public bool IsAsync { get; set; }//原文件地址public string OrginalFileUrl { get; set; }//拷贝目的地址public string DestinationFileUrl { get; set; }//文件流,异步读取后在回调方法内使用public FileStream OriginalFileStream { get; set; }//原文件字节数组,异步读取后在回调方法内使用public byte[] OriginalFileBytes { get; set; }}

复制

然后在FileStreamTest 类中新增一个Copy方法实现文件的复制功能

        /// <summary>/// 复制方法/// </summary>/// <param name="config">拷贝文件复制</param>public void Copy(IFileConfig config){lock (_lockObject){//得到CopyFileConfig对象var copyFileConfig = config as CopyFileConfig;// 检查CopyFileConfig类对象是否为空或者OrginalFileUrl是否为空if (CheckConfigIsError(copyFileConfig) || !File.Exists(copyFileConfig.OrginalFileUrl)) return;//创建同步或异步流FileStream stream = copyFileConfig.IsAsync ?new FileStream(copyFileConfig.OrginalFileUrl, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true): new FileStream(copyFileConfig.OrginalFileUrl, FileMode.Open);//定义一个byte数组接受从原文件读出的byte数据byte[] orignalFileBytes = new byte[stream.Length];using (stream){// stream.ReadTimeout = READ_OR_WRITE_TIMEOUT;//如果异步流if (stream.IsAsync){//将该流和读出的byte[]数据放入配置类,在callBack中可以使用copyFileConfig.OriginalFileStream = stream;copyFileConfig.OriginalFileBytes = orignalFileBytes;if (stream.CanRead)//异步开始读取,读完后进入End_ReadFileCallBack方法,该方法接受copyFileConfig参数stream.BeginRead(orignalFileBytes, 0, orignalFileBytes.Length, End_ReadFileCallBack, copyFileConfig);}else//否则同步读取{if (stream.CanRead){//一般读取原文件stream.Read(orignalFileBytes, 0, orignalFileBytes.Length);}//定义一个写流,在新位置中创建一个文件FileStream copyStream = new FileStream(copyFileConfig.DestinationFileUrl, FileMode.CreateNew);using (copyStream){//  copyStream.WriteTimeout = READ_OR_WRITE_TIMEOUT;//将源文件的内容写进新文件copyStream.Write(orignalFileBytes, 0, orignalFileBytes.Length);copyStream.Close();}}stream.Close();Console.ReadLine();}}}

复制

最后,如果采用异步的方式,则会进入End_ReadFileCallBack回调函数进行异步读取和异步写操作

  /// <summary>/// 异步读写文件方法/// </summary>/// <param name="result"></param>private void End_ReadFileCallBack(IAsyncResult result) {//得到先前的配置文件var config = result.AsyncState as CopyFileConfig;//结束异步读config.OriginalFileStream.EndRead(result);//异步读后立即写入新文件地址if (File.Exists(config.DestinationFileUrl)) File.Delete(config.DestinationFileUrl);FileStream copyStream = new FileStream(config.DestinationFileUrl, FileMode.CreateNew);using (copyStream){Console.WriteLine("异步复制原文件地址:{0}", config.OriginalFileStream.Name);Console.WriteLine("复制后的新文件地址:{0}", config.DestinationFileUrl);//调用异步写方法CallBack方法为End_CreateFileCallBack,参数是copyStreamcopyStream.BeginWrite(config.OriginalFileBytes, 0, config.OriginalFileBytes.Length, this.End_CreateFileCallBack,copyStream);copyStream.Close();}}

复制

最后让我们在main函数调用下:

  static void Main(string[] args){FileStreamTest test = new FileStreamTest();//创建文件配置类CreateFileConfig createFileConfig = new CreateFileConfig { CreateUrl = @"d:\MyFile.txt", IsAsync = true };//复制文件配置类CopyFileConfig copyFileConfig = new CopyFileConfig{OrginalFileUrl = @"d:\8.jpg",DestinationFileUrl = @"d:\9.jpg",IsAsync = true};test.Create(createFileConfig);test.Copy(copyFileConfig);}

复制

输出结果

实现文件本地分段上传

上面的例子是将一个文件作为整体进行操作,这样会带来一个问题,当文件很大或者网络不是很稳定的时候会发生意想不到的错误

那我们该怎么解决这一问题呢?其实有种思路还是不错的,那就是分段传输:

那就DIY一个简单的分段传输的例子,我们先将处理每一段的逻辑先整理好

/// <summary>/// 分段上传例子/// </summary>public class UpFileSingleTest{//我们定义Buffer为1000public const int BUFFER_COUNT = 1000;/// <summary>/// 将文件上传至服务器(本地),由于采取分段传输所以,/// 每段必须有一个起始位置和相对应该数据段的数据/// </summary>/// <param name="filePath">服务器上文件地址</param>/// <param name="startPositon">分段起始位置</param>/// <param name="btArray">每段的数据</param>private void WriteToServer(string filePath,int startPositon,byte[] btArray) {FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate);using (fileStream) {//将流的位置设置在该段起始位置fileStream.Position = startPositon;//将该段数据通过FileStream写入文件中,每次写一段的数据,就好比是个水池,分段蓄水一样,直到蓄满为止fileStream.Write(btArray, 0, btArray.Length);}}/// <summary>/// 处理单独一段本地数据上传至服务器的逻辑,根据客户端传入的startPostion/// 和totalCount来处理相应段的数据上传至服务器(本地)/// </summary>/// <param name="localFilePath">本地需要上传的文件地址</param>/// <param name="uploadFilePath">服务器(本地)目标地址</param>/// <param name="startPostion">该段起始位置</param>/// <param name="totalCount">该段最大数据量</param>public void UpLoadFileFromLocal(string localFilePath,string uploadFilePath,int startPostion,int totalCount) {//if(!File.Exists(localFilePath)){return;}//每次临时读取数据数int tempReadCount = 0;int tempBuffer = 0;//定义一个缓冲区数组byte[] bufferByteArray = new byte[BUFFER_COUNT];//定义一个FileStream对象FileStream fileStream = new FileStream(localFilePath,FileMode.Open);//将流的位置设置在每段数据的初始位置fileStream.Position = startPostion;using (fileStream){//循环将该段数据读出在写入服务器中while (tempReadCount < totalCount){tempBuffer = BUFFER_COUNT;//每段起始位置+每次循环读取数据的长度var writeStartPosition = startPostion + tempReadCount;//当缓冲区的数据加上临时读取数大于该段数据量时,//则设置缓冲区的数据为totalCount-tempReadCount 这一段的数据if (tempBuffer + tempReadCount > totalCount) {//缓冲区的数据为totalCount-tempReadCount tempBuffer = totalCount-tempReadCount;//读取该段数据放入bufferByteArray数组中fileStream.Read(bufferByteArray, 0, tempBuffer);if (tempBuffer > 0) {byte[] newTempBtArray = new byte[tempBuffer];Array.Copy(bufferByteArray, 0, newTempBtArray, 0, tempBuffer);//将缓冲区的数据上传至服务器this.WriteToServer(uploadFilePath, writeStartPosition, newTempBtArray);}}//如果缓冲区的数据量小于该段数据量,并且tempBuffer=设定BUFFER_COUNT时,通过//while 循环每次读取一样的buffer值的数据写入服务器中,直到将该段数据全部处理完毕else if (tempBuffer == BUFFER_COUNT) {fileStream.Read(bufferByteArray, 0, tempBuffer);this.WriteToServer(uploadFilePath, writeStartPosition, bufferByteArray);}//通过每次的缓冲区数据,累计增加临时读取数tempReadCount += tempBuffer;}}}}

复制

一切准备就绪,我们剩下的就是将文件切成几段进行上传了

 static void Main(string[] args){UpFileSingleTest test=new UpFileSingleTest();FileInfo info = new FileInfo(@"G:\\Skyrim\20080204173728108.torrent");//取得文件总长度var fileLegth = info.Length;//假设将文件切成5段var divide = 5;//取到每个文件段的长度var perFileLengh = (int)fileLegth / divide;//表示最后剩下的文件段长度比perFileLengh小var restCount = (int)fileLegth % divide;//循环上传数据for (int i = 0; i < divide+1; i++){//每次定义不同的数据段,假设数据长度是500,那么每段的开始位置都是i*perFileLengthvar startPosition = i * perFileLengh;//取得每次数据段的数据量var totalCount = fileLegth - perFileLengh * i > perFileLengh ? perFileLengh : (int)(fileLegth - perFileLengh * i);//上传该段数据test.UpLoadFileFromLocal(@"G:\\Skyrim\\20080204173728108.torrent", @"G:\\Skyrim\\20080204173728109.torrent", startPosition, i == divide ? divide : totalCount);}}

复制

上传结果:

总的来说,分段传输比直接传输复杂许多,我会在今后的例子中加入多线程,这样的话每段数据的传输都能通过一个线程单独处理,能够提升上传性能和速度


http://chatgpt.dhexx.cn/article/4Vb5Xy75.shtml

相关文章

FileStream读写文件

FileStream读写文件 FileStream类:操作字节的&#xff0c;可以操作任何的文件 StreamReader类和StreamWriter类:操作字符的&#xff0c;只能操作文本文件。 1、FileStream类 FileStream类 命名空间: System.IO &#xff08;1&#xff09;构造函数&#xff1a; FileStre…

本地socket unix domain socket

socket API原本是为网络通讯设计的&#xff0c;但后来在socket的框架上发展出一种IPC机制&#xff0c;就是UNIXDomain Socket。虽然网络socket也可用于同一台主机的进程间通讯&#xff08;通过loopback地址127.0.0.1&#xff09;&#xff0c;但是UNIX Domain Socket用于IPC更有…

python中socks包(SocksiPy)的安装、使用方法简介

1、下载SocksiPy csdn地址&#xff1a;点击打开https://download.csdn.net/download/qq_27378621/10536690 官方地址&#xff1a;点击打开https://sourceforge.net/projects/socksipy/?sourcetyp_redirect 2、官方文档介绍 地址&#xff1a;点击打开http://socksipy.sourc…

SOCKS5实现(一)

引文 假如我有一部安卓手机&#xff0c;我想把手机上的全部流量打到指定的代理上&#xff08;即透明代理&#xff09;&#xff0c;代理外接外部的VPN&#xff0c;以达到分散IP出口的目的。 这是这个系列的第一篇文章&#xff0c;本文将简单介绍一下 SOCKS 、iptable 、透明代理…

socks协议详解

0x01 socks协议简介 Socks&#xff08;Socket Secure&#xff09;协议是一种网络协议&#xff0c;处于会话层&#xff0c;用于管理网络连接并提供安全性和隐私保护。通过使用Socks代理服务器&#xff0c;客户端可以隐藏其真实IP地址和其他身份信息&#xff0c;从而匿名地访问互…

socks代理实战

文章目录 Socks代理实战Socks代理简介Socks代理工具Socks代理实战-MSF渗透场景Target1Target2Target3 Socks代理实战-FRPTarget1Target2Target3 Socks代理实战-EWEW使用简介EW正反向Socks代理EW创建一层Socks代理二级级联本地SocksEW创建二层Socks代理三级级联的本地SocksEW创建…

Socket(四)

文章目录 1. 服务器Socket简介2. 使用ServerSocket3. 用Socket写入服务器4. 关闭服务器Socket 1. 服务器Socket简介 博客Socket&#xff08;一&#xff09;&#xff5e;Socket&#xff08;二&#xff09;从客户端的角度讨论了Socket&#xff0c;客户端就是向监听连接的服务器打…

CobaltStrike建立Socks4代理

目录 Socks4代理建立 ProxyChains的使用 Socks4代理建立 当我们的被控主机是位于公网和内网边界的服务器时&#xff0c;我们想利用该主机继续对内网的主机进行渗透&#xff0c;比如经过端口扫描我们发现被控机器的同一网段有一主机开放了80端口&#xff0c;我们想在本地访问…

Java常用工具类

学习内容 包装类型(基本数据类型的包装类型) String字符串常用方法 StringBuffer与Stringbuilder 日期和时间处理工具类 System,Math,Random,UUID等工具类 枚举类型 File类 递归算法 目录 1.包装类型 1.1.Integer的基本用法 1.2.包装类型的使用 1.3.自动装箱与自动…

Java——Collections工具类

Collections工具类 Collections 是一个操作 Set、List 和 Map 等集合的工具类 Collections 中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作&#xff0c;还提供了对集合对象设置不可变、对集合对象实现同步控制等方法。 排序操作&#xff1a;&#xff08;均为…

Spring自带的工具类

最近发现同事写了不少重复的工具类&#xff0c;发现其中很多功能&#xff0c;Spring 自带的都有。于是整理了本文&#xff0c;希望能够帮助到大家&#xff01; 目录 断言 对象、数组、集合 ObjectUtils StringUtils CollectionUtils 文件、资源、IO 流 FileCopyUtils R…

【常用工具类】Java控制台打印工具类LogUtil

文章目录 1 带分割线版2 不带分割线版3 终极版 1 带分割线版 import java.text.SimpleDateFormat; import java.util.Date;/*** W SKH 的输出工具类*/ public class LogUtil {private SimpleDateFormat simpleDateFormat new SimpleDateFormat("yyyy-MM-dd,HH:mm:ss.SSS&…

Java 对象拷贝工具类

目录 1. Spring 中的对象拷贝 2. 本工具类中的对象拷贝 2.1 拷贝对象本身&#xff08;单个&#xff09; 2.2 拷贝对象本身&#xff08;批量&#xff09; 2.3 拷贝对象属性至其他类&#xff08;单个&#xff09; 2.4 拷贝对象属性至其他类&#xff08;批量&#xff09; 4.…

Java表达式运算工具类

对于表达式的运算转换工具类&#xff0c;使用场景&#xff0c;例如前端文本框让用户输入了加减乘除运算&#xff0c;工具类智能转换。 资源下载&#xff1a;Java表达式工具类&#xff0c;用于加减乘除等智能转换-Java文档类资源-CSDN下载 例如&#xff1a; public static void…

阿里OSS工具类

参考博客&#xff1a;阿里OSS入门 bucket配置信息&#xff1a;alios.properties OSS配置文件&#xff1a;AliOSSConfig.java Data public class AliOSSConfig {private String endpoint;private String accessKeyId;private String accessKeySecret;private String bucketNam…

Guava Lists工具类

文章目录 01 概述02 Lists工具类03 文末 01 概述 Guava 是 Google 开源的一个 Java 工具库&#xff0c;里面有很多工具类&#xff0c;本文要讲的是里面的Lists工具类。 注意&#xff0c;使用Guava工具类库&#xff0c;必须先添加依赖&#xff1a; <dependency><gro…

JAVA之常用的工具类

目录 1 集合工具类 1.1 java.util.Collections 1.1.1 基本操作 1.1.2 转换线程安全集合 1.2 org.springframework.util.CollectionUtils 1.3 org.apache.commons.collections.CollectionUtils 1.4 org.apache.commons.lang.ArrayUtils 1.5 org.apache.commons.lang3.Ar…

常用的Java开发工具类

前言 在java的庞大体系中&#xff0c;其实有很多不错的小工具&#xff0c;也就是我们平常说的&#xff1a;轮子。 如果在我们的日常工作当中&#xff0c;能够将这些轮子用户&#xff0c;再配合一下idea的快捷键&#xff0c;可以极大得提升我们的开发效率。 今天我决定把一些…

工具类的详解

工具类网站 1、工具类 1.1 定义 工具类是为了提供一些通用的、某一非业务领域内的公共方法&#xff0c;不需要配套的成员变量&#xff0c;仅仅是作为工具方法被使用。所以将它做成静态方法最合适&#xff0c;不需要实例化&#xff0c;能够获取到方法的定义并调用就行。 1.2…

学习日记-安卓Package Manager和Package Installer

安装和卸载APK&#xff08;安卓应用程序包文件&#xff09;&#xff0c;运作原理。 什么是Package Manager&#xff08;包管理器&#xff09;和Package Installer&#xff08;程序安装包&#xff09;&#xff1f; APK文件保存在Android的哪个地方&#xff1f; APK文件安装过…