JAVA 整合 AWS S3(Amazon Simple Storage Service)文件上传,分片上传,删除,下载
依赖
因为aws需要发送请求上传、下载等api,所以需要加上httpclient相关的依赖
<dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>1.11.628</version>
</dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.13</version>
</dependency>
工具类
上传和下载方式都被重载了,所以可以根据不同的业务场景去使用不同的重载方式。
import com.amazonaws.AmazonServiceException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;
import com.amazonaws.util.StringUtils;
import com.mocha.order.enums.PropertiesEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;@Component
public class CosUtil {private static final Logger LOGGER = LoggerFactory.getLogger(CosUtil.class);//访问keypublic static String accessKey;//密钥keypublic static String secretKey;//服务区域public static String serviceEndpoint; // e.g., "cos.gz-tst.cos.tg.unicom.local"//区域public static String region; // e.g., "gz-tst"static AWSCredentials credentials ;static AWSStaticCredentialsProvider awsStaticCredentialsProvider ;static ClientConfiguration config ;static AwsClientBuilder.EndpointConfiguration endpointConfiguration ;static AmazonS3 conn ;//分片大小5M,一般设置5的倍数即可,分片大小最大不要超过100Mpublic static final int FIVE_PARTSIZE=5242880;//1Mpublic static final int ONE_PARTSIZE=1048576;@PostConstructpublic void init() {//这些配置的值,可以从数据库获取、也可以丛配置文件获取final String cosAccessKey = PropertiesEnum.getCosAccessKey();final String cosSecretKey = PropertiesEnum.getCosSecretKey();final String cosServiceEndpoint = PropertiesEnum.getCosServiceEndpoint();final String cosRegion = PropertiesEnum.getCosRegion();if (org.apache.commons.lang3.StringUtils.isBlank(cosAccessKey)){LOGGER.error("联通云Cos配置的AccessKey为空,请保证【COS_ACCESSKEY】值不为空,否则会影响项目相关功能的使用");}if (org.apache.commons.lang3.StringUtils.isBlank(cosSecretKey)){LOGGER.error("联通云Cos配置的SecretKey为空,请保证【COS_SECRETKEY】值不为空,否则会影响项目相关功能的使用");}if (org.apache.commons.lang3.StringUtils.isBlank(cosServiceEndpoint)){LOGGER.error("联通云Cos配置的ServiceEndpoint为空,请保证【COS_SERVICEENDPOINT】值不为空,否则会影响项目相关功能的使用");}if (org.apache.commons.lang3.StringUtils.isBlank(cosRegion)){LOGGER.error("联通云Cos配置的Region为空,请保证【COS_REGION】值不为空,否则会影响项目相关功能的使用");}LOGGER.info("联通云Cos的配置分别为,accessKey:{},secretKey:{},serviceEndpoint:{},region:{}",cosAccessKey,cosAccessKey,cosServiceEndpoint,cosRegion);LOGGER.info("开始初始化联通云Cos的配置,开始初始化时间:{}",new Date());accessKey=cosAccessKey;secretKey=cosSecretKey;serviceEndpoint=cosServiceEndpoint;region=cosRegion;LOGGER.info("结束初始化联通云Cos的配置,结束初始化时间:{}",new Date());credentials = new BasicAWSCredentials(accessKey, secretKey);awsStaticCredentialsProvider = new AWSStaticCredentialsProvider(credentials);config = new ClientConfiguration();endpointConfiguration = new AwsClientBuilder.EndpointConfiguration(serviceEndpoint, region);conn = AmazonS3ClientBuilder.standard().withCredentials(awsStaticCredentialsProvider).withClientConfiguration(config.withProtocol(Protocol.HTTP).withSignerOverride("S3SignerType")).withEndpointConfiguration(endpointConfiguration).build();}//检查桶是否存在public static boolean doesBucketExist(String bucketName){return conn.listBuckets().stream().map(Bucket::getName).collect(Collectors.toList()).contains(bucketName);}/*** 创建桶* 1、创建已经存在的桶,不会把之前存在的桶内容删除**/public static Bucket createBucket(String bucketName){LOGGER.info("创建桶:{}",bucketName);return conn.createBucket(bucketName);}// 列出所有桶列表public static List<Bucket> listBuckets(){return conn.listBuckets();}// 列出桶内对象public static ObjectListing listObjects(String bucketName){ObjectListing objects = conn.listObjects(bucketName);do {for (S3ObjectSummary objectSummary : objects.getObjectSummaries()) {LOGGER.info(objectSummary.getKey() + "\t" + objectSummary.getSize() + "\t" + StringUtils.fromDate(objectSummary.getLastModified()));}objects = conn.listNextBatchOfObjects(objects);} while (objects.isTruncated());return objects;}// 获取文件public static ObjectMetadata getObjectMeta(String bucketName, String fileName){LOGGER.info("上传文件,桶名称:{},文件名称:{}",bucketName,fileName);return conn.getObjectMetadata(bucketName, fileName);}// 上传文件-通过实体类public static PutObjectResult uploadFile(PutObjectRequest putObjectRequest){LOGGER.info("上传文件桶实体类方式,实体类是:{}",putObjectRequest);return conn.putObject(putObjectRequest);}// 上传文件-通过Filepublic static PutObjectResult uploadFile(String bucketName, String keyName, File file){LOGGER.info("上传文件,桶名称:{},文件名称:{}",bucketName,keyName);return conn.putObject(bucketName, keyName, file);}// 上传文件-通过InputStreampublic static PutObjectResult uploadFile(String bucketName, String keyName, InputStream inputStream){LOGGER.info("上传文件,桶名称:{},文件名称:{}",bucketName,keyName);return conn.putObject(bucketName, keyName, inputStream, new ObjectMetadata());}// 上传文件-通过字符串public static PutObjectResult uploadFile(String bucketName, String keyName, String content){LOGGER.info("上传文件,桶名称:{},文件名称:{}",bucketName,keyName);return conn.putObject(bucketName, keyName, content);}// 分片上传(不要需要指定分片的大小、还提供上传进度跟踪、断点续传、并发上传等功能)public static Upload uploadFileByShard(String bucketName, String keyName, String filePath) throws InterruptedException,AmazonServiceException {TransferManager tm = TransferManagerBuilder.standard().withS3Client(conn).build();try {LOGGER.info("开始分片上传,桶名称:{},文件名称:{},路径:{}",bucketName,keyName,filePath);Upload upload = tm.upload(bucketName, keyName, new File(filePath));upload.waitForCompletion();LOGGER.info("结束分片上传,桶名称:{},文件名称:{},路径:{}",bucketName,keyName,filePath);return upload;} catch (AmazonServiceException | InterruptedException e) {LOGGER.error("分片上传异常,桶名称:{},文件名称:{},路径:{}",bucketName,keyName,filePath);e.printStackTrace();throw e;}}/*** 大文件分段上传(需要指定分片的大小,自定义的线程池)** @param bucketName bucketName* @param objectName objectName* @param file MultipartFile* @param minPartSize 每片大小,单位:字节(eg:5242880 <- 5m)* @return*/public static boolean uploadMultipartFileByPart(String bucketName, String objectName, File file, int minPartSize) {long size = file.length();final String fileName = file.getName();if (size==0) {LOGGER.error("分片上传的文件:{}为空",fileName);return false;}// 计算分片大小// 得到总共的段数,和 分段后,每个段的开始上传的字节位置List<Long> positions = Collections.synchronizedList(new ArrayList<>());long filePosition = 0;while (filePosition < size) {positions.add(filePosition);filePosition += Math.min(minPartSize, (size - filePosition));}if (LOGGER.isDebugEnabled()) {LOGGER.info("文件:{},总大小:{}字节,分为{}段",fileName, size, positions.size());}// 创建一个列表保存所有分传的 PartETag, 在分段完成后会用到List<PartETag> partETags = Collections.synchronizedList(new ArrayList<>());// 第一步,初始化,声明下面将有一个 Multipart Upload// 设置文件类型ObjectMetadata metadata = new ObjectMetadata();String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);metadata.setContentType(fileType);InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, objectName, metadata);InitiateMultipartUploadResult initResponse = conn.initiateMultipartUpload(initRequest);if (LOGGER.isDebugEnabled()) {LOGGER.info("分片上传开始,上传的文件时:{}",fileName);}//声明线程池ExecutorService exec = Executors.newFixedThreadPool(5);long begin = System.currentTimeMillis();try {for (int i = 0; i < positions.size(); i++) {int finalI = i;exec.execute(() -> {long time1 = System.currentTimeMillis();UploadPartRequest uploadRequest = new UploadPartRequest().withBucketName(bucketName).withKey(objectName).withUploadId(initResponse.getUploadId()).withPartNumber(finalI + 1).withFileOffset(positions.get(finalI)).withFile(file).withPartSize(Math.min(minPartSize, (size - positions.get(finalI))));// 第二步,上传分段,并把当前段的 PartETag 放到列表中partETags.add(conn.uploadPart(uploadRequest).getPartETag());LOGGER.info("分片上传的文件时:{},第{}段上传耗时:{}",fileName ,finalI + 1, (System.currentTimeMillis() - time1));});}//任务结束关闭线程池exec.shutdown();//判断线程池是否结束,不加会直接结束方法while (true) {if (exec.isTerminated()) {break;}}// 第三步,完成上传,合并分段CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(bucketName, objectName, initResponse.getUploadId(), partETags);conn.completeMultipartUpload(compRequest);} catch (Exception e) {conn.abortMultipartUpload(new AbortMultipartUploadRequest(bucketName, objectName, initResponse.getUploadId()));LOGGER.error("分片上传文件:{}异常,异常是:{}, ",fileName, e.getLocalizedMessage());e.printStackTrace();}LOGGER.info("分片上传文件:{}结束,总上传耗时:{}毫秒",fileName, (System.currentTimeMillis() - begin));return false;}/*** 初始化,声明有一个Multipart Upload** @param initRequest 初始化请求* @return 初始化返回*/private InitiateMultipartUploadResult initiateMultipartUpload(InitiateMultipartUploadRequest initRequest) {return conn.initiateMultipartUpload(initRequest);}/*** 上传分段** @param uploadRequest 上传请求* @return 上传分段返回* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/UploadPart">AWS* API Documentation</a>*/private UploadPartResult uploadPart(UploadPartRequest uploadRequest) {return conn.uploadPart(uploadRequest);}/*** 分段合并** @param compRequest 合并请求* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/CompleteMultipartUpload">AWS* API Documentation</a>*/private CompleteMultipartUploadResult completeMultipartUpload(CompleteMultipartUploadRequest compRequest) {return conn.completeMultipartUpload(compRequest);}/*** 中止分片上传** @param uploadRequest 中止文件上传请求* @see <a href="http://docs.aws.amazon.com/goto/WebAPI/s3-2006-03-01/AbortMultipartUpload">AWS* API Documentation</a>*/private void abortMultipartUpload(AbortMultipartUploadRequest uploadRequest) {conn.abortMultipartUpload(uploadRequest);}// 修改对象的访问控制权限public static void modifyFileAccessAuthority(String bucketName, String keyName, CannedAccessControlList cannedAccessControlList){LOGGER.info("修改文件的访问权限,桶名称:{},文件名称:{},权限类型时:{}",bucketName,keyName,cannedAccessControlList.toString());conn.setObjectAcl(bucketName, keyName, cannedAccessControlList);}// 下载一个对象(到指定路径)public static ObjectMetadata downloadFileAssignPath(String bucketName, String keyName, String fileSavePath){return conn.getObject(new GetObjectRequest(bucketName, keyName), new File(fileSavePath));}// 生成对象下载链接(带签名)public static URL generatorFileUrl(String bucketName, String keyName){GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, keyName);return conn.generatePresignedUrl(request);}// 删除文件public static void deleteFie(String bucketName, String keyName){LOGGER.info("删除文件,桶名称:{},文件名称:{},删除时间:{}",bucketName,keyName,new Date());conn.deleteObject(bucketName, keyName);}// 删除桶public static void deleteFie(String bucketName){LOGGER.info("删除桶,桶名称:{},删除时间:{}",bucketName,new Date());conn.deleteBucket(bucketName);}public static void main(String[] args) {String filePath = "G:\\mk\\GDrepo\\repo\\org\\apache\\httpcomponents\\httpcomponents-core\\4.0.1\\httpcomponents-core-4.0.1.pom"; //文件路径// ByteArrayInputStream input1 = new ByteArrayInputStream("Hello World!".getBytes());
// CosUtil.createBucket("aaa");
// final FileInputStream inputStream;
// try {
// inputStream = new FileInputStream("G:\\mk\\GDrepo\\repo\\org\\apache\\httpcomponents\\httpcomponents-core\\4.0.1\\httpcomponents-core-4.0.1.pom");
// } catch (FileNotFoundException e) {
// throw new RuntimeException(e);
// }
// CosUtil.uploadFile("aaa","a.pom",inputStream);CosUtil.uploadFile("test","a.txt",new File(filePath));CosUtil.uploadFile("test","a.txt",new File(filePath));//上传空文件夹conn.putObject("aaa", "demo" + "/","");//上传文件到指定的文件夹final PutObjectRequest putObjectRequest = new PutObjectRequest("aaa", "demo" + "/" + "a.txt", new File(filePath));conn.putObject(putObjectRequest);// 列出所有桶列表List<Bucket> buckets = conn.listBuckets();for (Bucket bucket : buckets) {System.out.println(bucket.getName() + "\t" + StringUtils.fromDate(bucket.getCreationDate()));}// 创建桶Bucket bucket = conn.createBucket("111");Bucket bucket1 = conn.createBucket("111");Bucket bucket12 = conn.createBucket("111");System.out.println(bucket.getName());// 列出桶内对象ObjectListing objects = conn.listObjects(bucket.getName());do {for (S3ObjectSummary objectSummary : objects.getObjectSummaries()) {System.out.println(objectSummary.getKey() + "\t" +objectSummary.getSize() + "\t" +StringUtils.fromDate(objectSummary.getLastModified()));}objects = conn.listNextBatchOfObjects(objects);} while (objects.isTruncated());// 创建对象ByteArrayInputStream input = new ByteArrayInputStream("Hello World!".getBytes());conn.putObject(bucket.getName(), "hello.txt", input, new ObjectMetadata());//分段上传String keyName = "demoya"; //文件上传成功后的文件名TransferManager tm = TransferManagerBuilder.standard().withS3Client(conn).build();try {// TransferManager processes all transfers asynchronously,// so this call returns immediately.System.out.println("开始分片上传");Upload upload = tm.upload("my-test-bucket", keyName, new File(filePath));//Optionally, wait for the upload to finish before continuing.upload.waitForCompletion();System.out.println("结束分片上传");} catch (AmazonServiceException | InterruptedException e) {// The call was transmitted successfully, but Amazon S3 couldn't process// it, so it returned an error response.e.printStackTrace();}// 修改对象的访问控制权限conn.setObjectAcl(bucket.getName(), "hello.txt", CannedAccessControlList.PublicRead);// 下载一个对象(到本地文件)conn.getObject(new GetObjectRequest(bucket.getName(), "hello.txt"), new File("G:\\mk\\hello.txt"));// 生成对象下载链接(带签名)GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket.getName(), "hello.txt");System.out.println(conn.generatePresignedUrl(request));// 删除一个对象conn.deleteObject(bucket.getName(), "hello.txt");//删除桶conn.deleteBucket(bucket.getName());}
}相关文章:
JAVA 整合 AWS S3(Amazon Simple Storage Service)文件上传,分片上传,删除,下载
依赖 因为aws需要发送请求上传、下载等api,所以需要加上httpclient相关的依赖 <dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>1.11.628</version> </dependency&…...
记录:Unity脚本的编写9.0
目录 射线一些准备工作编写代码 突然发现好像没有写过关于射线的内容,我就说怎么总感觉好像少了什么东西(心虚 那就在这里写一下关于射线的内容吧,将在这里实现射线检测鼠标点击的功能 射线 射线是一种在Unity中检测碰撞器或触发器的方法&am…...
共享单车停放(简单的struct结构运用)
本来不想写这题的,但是想想最近沉迷玩雨世界,班长又问我这题,就草草写了一下 代码如下: #include<stdio.h> #include<math.h> struct parking{int distance;int remain;int speed;int time;int jud; }parking[50]; …...
【Java8系列07】Java8日期处理
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
为什么做CSGO搬砖的不直接去炒股呢?
首先,CS2并非只有一个交易平台,阿阳个人觉得像IGXE等交易平台一样是交易,况且我记得很早的时候我就开始用IGXE了,我记得最早的时候还是机器人发货,后来因为V社对于很多开箱网站的管控,所以让这种发货的方式…...
12月01日,每日信息差//阿里国际发布3款AI设计生态工具//美团买菜升级为“小象超市”//外国人永居证换新、6国游客免签来华
_灵感 🎖 阿里国际发布3款AI设计生态工具 🎄 AITO问界系列11月交付新车18827辆 🌍 美团买菜升级为“小象超市” 🌋 全球首个金融风控大模型国际标准出炉,由腾讯牵头制定 🎁 支付宝:支持外国人…...
ChatGPT探索:提示工程详解—程序员效率提升必备技能【文末送书】
文章目录 一.人工智能-ChatGPT1.1 ChatGPT简介1.2 ChatGPT探索:提示工程详解1.2 提示工程的优势 二.提示工程探索2.1 提示工程实例:2.2 英语学习助手2.3 Active-Prompt思维链(CoT)方法2.4 提示工程总结 三.文末推荐与福利3.1《Cha…...
Pytest做性能测试?
Pytest其实也是可以做性能测试或者基准测试的。是非常方便的。 可以考虑使用Pytest-benchmark类库进行。 安装pytest-benchmark 首先,确保已经安装了pytest和pytest-benchmark插件。可以使用以下命令安装插件: pip install pytest pytest-benchmark …...
Swagger各版本访问地址
2.9.x 访问地址: http://ip:port/{context-path}/swagger-ui.html 3.0.x 访问地址: http://ip:port/{context-path}/swagger-ui/index.html 3.0集成knife4j 访问地址: http://ip:port/{context-path}/doc.html...
docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbor
docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbor 文章目录 docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbordocker-compose私有镜像仓库harbor搭建镜像推送到私有仓库harbor docker-compose D…...
OpenTSDB(CVE-202035476)漏洞复现及利用
任务一: 复现环境中的命令注入漏洞。 任务二: 利用命令注入执行whoami,使用DNS外带技术获取结果 任务三:使用反弹shell,将漏洞环境中的shell反弹到宿主机或者vps服务器。 任务一: 1.搭建好环境 2.先去了…...
Maven无法拉取依赖/构建失败操作步骤(基本都能解决)
首先检查配置文件,确认配置文件没有问题(也可以直接用同事的配置文件(记得修改文件里的本地仓库地址)) 1.file->Invalidate Caches清除缓存重启(简单粗暴,但最有效) 2.刷新maven以及mvn clean,多刷几次,看看还有没有报红的依赖…...
【数据库】数据库并发控制的目标,可串行化序列的分析,并发控制调度器模型
数据库并发控制 专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会定期更…...
带头结点的双向循环链表
目录 带头结点的双向循环链表 1.存储定义 2.结点的创建 3.结点的初始化 4.尾插结点 5.尾删结点 6.头插结点 7.头删结点 8.查找并返回结点 9.在pos结点前插入结点 10.删除pos结点 11.打印链表 12.销毁链表 13.头插结点2.0版 14.尾插结点2.0版 前言: 当…...
2023年11月下旬大模型新动向集锦
2023年11月下旬大模型新动向集锦 2023.12.1版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、微软将向中国大陆开放Windows Copilot服务 据微软发布的消息,微软将在 2023 年 12 月 1 日面向中国大陆的企业和教育机构推出 We…...
有IP没有域名可以申请证书吗?
一、IP证书是什么? ip证书是用于公网ip地址的SSL证书,与我们通常所讲的SSL证书并无本质上的区别,但由于SSL证书通常颁发给域名,而组织机构需要公共ip地址的SSL证书,这类SSL证书就是我们所说的ip证书。ip证书具有安全、…...
【软件推荐】卸载360软件geek;护眼软件flux;
卸载360软件geek f.lux: software to make your life better (justgetflux.com) 卸载完扫描残留 护眼软件 hf.lux: software to make your life better (justgetflux.com)https://justgetflux.com/https://justgetflux.com/...
Module build failed: Error: ENOENT: no such file or directory
前言 这个错误通常发生在Node.js 和 vue,js项目中,当你试图访问一个不存在的文件或目录时。在大多数情况下,这是因为你的代码试图打开一个不存在的文件,或者你的构建系统(例如Webpack)需要一个配置文件,但找…...
Postgresql BatchInsert唯一键冲突及解决
Postgresql BatchInsert唯一键冲突及解决 当有唯一键冲突时,批量插入可能会报错; insert into tableA(sno,name,age,emp) values(),(),(); 会报错 insert into tableA(sno,name,age,emp) values(),(),() on conflict on contraint tableA_unique_key do …...
腾讯云AMD服务器标准型SA5实例AMD EPYC Bergamo处理器
腾讯云服务器标准型SA5实例是最新一代的标准型实例,CPU采用AMD EPYC™ Bergamo全新处理器,采用最新DDR5内存,默认网络优化,最高内网收发能力达4500万pps。腾讯云百科txybk.com分享腾讯云标准型SA5云服务器CPU、内存、网络、性能、…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
