pyqt5制作音乐播放器(第三版)

这次接入了数据库,增加了翻页模式,更新了功能跳转之间的细节

数据设计:

收藏 like=1时表示被收藏,展示show=0的时候表示表数据被搜索

from peewee import Model, PrimaryKeyField, CharField, BooleanField, MySQLDatabase,IntegerFielddatabase = MySQLDatabase("czh", host="localhost", port=3306,user="root", password="123456")class BaseModel(Model):class Meta:database = databaseclass Music(BaseModel):id = PrimaryKeyField()singer = CharField(max_length=264, help_text='歌手')song = CharField(max_length=264, help_text='歌曲')path = CharField(max_length=264, help_text='路径')like = BooleanField(default=False, help_text='收藏')show = BooleanField(default=True, help_text='展示')row = IntegerField(help_text='行数')

在load_music中想到了lambda来传条件参数,分别给三个字段设计了对应的条件con1,con2,con3,只有在使用相应功能时修改条件即可实现函数复用了

records = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).offset(start_index).limit(self.page_size)

代码:

注:

7.25:修改了上下切换音乐的BUG,翻页后上下切换已经翻页自动播放等问题

import fnmatch
import os
import random
import sys
import loggingfrom PyQt5.QtGui import QPalette, QBrush, QPixmap, QLinearGradient, QColor, QIntValidator
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QSlider, QLabel, \QTableWidget, QLineEdit, QTableWidgetItem
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl, Qt, QTimerfrom database import Musiclogging.basicConfig(filename="music.log", filemode="w", format="%(asctime)s %(name)s:%(levelname)s:%(message)s",datefmt="%Y-%m-%d %H:%M:%S", level=logging.INFO)
logger = logging.getLogger("music")
KZT = logging.StreamHandler()
KZT.setLevel(logging.INFO)
logger.addHandler(KZT)class MusicPlayer(QMainWindow):def __init__(self):super().__init__()self.music_path = "F://wyy"  # 音乐文件夹,可以有子文件夹self.start_x = 10self.x_step = 100self.start_y = 10self.y_step = 40self.window_w, self.window_h = 500, 800self.duration = 1self.position = 0self.text = "歌曲未加载"self.random_play_list= []self.total_pages = 0self.page_size = 20self.current_page = 1  # 翻页时所在页面self.play_page = 1  # 正在播放音乐的所在页self.current_index = 1  # 数据库idself.current_music_info = Music.select().where(Music.id == self.current_index)[0]self.current_music = self.current_music_info.songself.current_singer = self.current_music_info.singerself.current_path = self.current_music_info.pathself.status = True  # 音乐是否在播放self.update_label = True  # 音乐是否在播放-》是否更新进度条self.random_play_status = False  # 是否处于随机播放状态self.show_favorite_status = False  # 是否展示收藏self.search_status = False  # 查询状态self.con1 = lambda x: x >= 0  # 普通查询条件self.con2 = lambda x: x >= 0  # 搜索查询条件self.con3 = lambda x: x >= 0  # 收藏查询条件self.load_local_music(False)  # 加载本地音乐文件self.init_ui()logger.info("配置加载完成")def init_ui(self):self.setWindowTitle("音乐播放器")self.resize(self.window_w, self.window_h)self.setMinimumSize(self.window_w, self.window_h)self.setMaximumSize(self.window_w, self.window_h)palette = QPalette()  # 主界面背景palette.setBrush(QPalette.Background, QBrush(QPixmap("imgs/21.jpg")))self.setPalette(palette)self.player = QMediaPlayer()self.play_button = QPushButton("播放", self)self.play_button.clicked.connect(self.play_music)self.play_button.move(self.start_x, self.start_y)self.change_button = QPushButton("暂停", self)self.change_button.clicked.connect(self.change_music_status)self.change_button.move(self.start_x + self.x_step, self.start_y)self.play_pre_button = QPushButton("上一首", self)self.play_pre_button.clicked.connect(self.play_pre)self.play_pre_button.move(self.start_x, self.start_y + self.y_step)self.play_next_button = QPushButton("下一首", self)self.play_next_button.clicked.connect(self.play_next)self.play_next_button.move(self.start_x + self.x_step, self.start_y + self.y_step)self.play_random_btn = QPushButton("随机播放", self)self.play_random_btn.clicked.connect(self.change_random_status)self.play_random_btn.move(self.start_x + 2 * self.x_step, self.start_y + self.y_step)self.favorite_btn = QPushButton("我的收藏", self)self.favorite_btn.clicked.connect(self.show_favorite)self.favorite_btn.move(self.start_x + 3 * self.x_step, self.start_y + self.y_step)self.volume_slider = QSlider(Qt.Horizontal, self)self.volume_slider.setRange(0, 100)self.volume_slider.setValue(50)self.volume_slider.setTickPosition(QSlider.TicksBelow)self.volume_slider.setTickInterval(10)self.volume_slider.resize(200, 30)self.volume_slider.sliderReleased.connect(self.change_volume)# self.volume_slider.sliderPressed.connect(self.volume_pressed)self.volume_slider.move(self.start_x, self.start_y + 2 * self.y_step)self.music_pro_bar = QLabel(self)self.music_pro_width = self.window_w - self.start_x - 210self.music_pro_bar.resize(self.music_pro_width, 10)self.music_pro_bar.move(self.start_x + 210, self.start_y + 2 * self.y_step + 10)gradient = QLinearGradient(0, 0, self.music_pro_width, 0)gradient.setColorAt(0, QColor(0, 0, 0))gradient.setColorAt(1, QColor(255, 255, 255))music_pro_bar_palette = QPalette()music_pro_bar_palette.setBrush(QPalette.Background, gradient)self.music_pro_bar.setAutoFillBackground(True)self.music_pro_bar.setPalette(music_pro_bar_palette)self.table_widget = QTableWidget(0, 3, parent=self)  # 检测结果列表self.table_widget.verticalHeader().hide()  # 隐藏行索引self.table_widget.move(self.start_x, self.start_y + 4 * self.y_step)self.table_widget.resize(self.window_w - self.start_x, self.window_h - self.start_y - 5 * self.y_step)self.table_widget.cellClicked.connect(self.cell_clicked)self.table_widget.cellDoubleClicked.connect(self.play_cell)self.table_widget.setColumnWidth(0, 150)self.table_widget.setColumnWidth(1, 250)self.table_widget.setColumnWidth(2, 70)self.table_widget.setEditTriggers(QTableWidget.NoEditTriggers)self.table_widget.setStyleSheet("QTableWidget {background-image: url('imgs/11.jpg');}")self.load_music()self.prev_button = QPushButton("上一页", self)self.next_button = QPushButton("下一页", self)self.prev_button.clicked.connect(self.click_prev_page)self.next_button.clicked.connect(self.click_next_page)self.prev_button.move(100, self.window_h - self.y_step)self.next_button.move(200, self.window_h - self.y_step)self.int_validator = QIntValidator(0, self.total_pages)self.jump_page_btn = QPushButton("跳转", self)self.jump_page_btn.clicked.connect(self.jump_page)self.jump_page_btn.move(300, self.window_h - self.y_step)self.jump_page_text = QLineEdit(self)self.jump_page_text.setValidator(self.int_validator)self.jump_page_text.move(400, self.window_h - self.y_step)self.search_btn = QPushButton("搜索", self)self.search_btn.move(self.start_x + 2 * self.x_step, self.start_y)self.search_btn.clicked.connect(self.change_search_status)self.search_text = QLineEdit(self)self.search_text.resize(self.window_w - self.start_x - 3 * self.x_step - 10, 30)self.search_text.move(self.start_x + 3 * self.x_step, self.start_y)self.search_text.setStyleSheet("QLineEdit {border-radius: 5px;}")self.search_text.returnPressed.connect(self.search_music)self.music_label = QLabel(self.text, self)self.music_label.resize(self.window_w - self.start_x, 30)self.music_label.move(self.start_x, self.start_y + 3 * self.y_step)self.music_label.setAlignment(Qt.AlignCenter)self.timer = QTimer()self.timer.timeout.connect(self.scroll_text)self.timer.start(500)self.player.stateChanged.connect(self.handle_player_status_changed)self.player.mediaStatusChanged.connect(self.handle_media_status_changed)self.player.durationChanged.connect(self.update_duration)self.player.positionChanged.connect(self.update_position)def play_music(self):self.player.setMedia(QMediaContent(QUrl.fromLocalFile(self.current_path)))self.player.play()self.text = f"当前播放:{self.current_music} —— {self.current_singer} "self.music_label.setText(self.text)logger.info("正在播放:%s - %s", self.current_music, self.current_singer)def change_music_status(self):if self.status:self.player.pause()self.status = Falseself.change_button.setText('继续')logger.info("已暂停当前音乐:%s", self.current_music)else:self.status = Trueself.player.play()self.change_button.setText('暂停')logger.info("已继续当前音乐:%s", self.current_music)def handle_media_status_changed(self, status):if status == QMediaPlayer.EndOfMedia:logger.info("播放完毕: %s - %s", self.current_music, self.current_singer)if self.random_play_status:  # 再判断是否随机播放self.play_random()else:self.play_next()def handle_player_status_changed(self, state):if state == QMediaPlayer.PlayingState:self.update_label = Trueelif state == QMediaPlayer.StoppedState:self.update_label = Falsedef clear_table(self):self.table_widget.clearContents()self.table_widget.setHorizontalHeaderLabels(['歌手', '歌曲'])  # 设置列表头self.table_widget.setRowCount(0)logger.info("已更新列表")def cell_clicked(self, row, column):if column != 2:text = self.table_widget.item(row, column).text()logger.info("点击了:%s", text)if column == 2:song = self.table_widget.item(row, column - 1).text()singer = self.table_widget.item(row, column - 2).text()query = Music.select().where((Music.song == song) & (Music.singer == singer))[0]like = query.likeif like == 1:query.like = 0logger.info("取消收藏:%s %s", query.singer, query.song)self.table_widget.setItem(row, column, QTableWidgetItem('收藏'))else:query.like = 1logger.info("收藏音乐:%s %s", query.singer, query.song)self.table_widget.setItem(row, column, QTableWidgetItem('已收藏'))query.save()def play_cell(self, row, column):if column == 1:self.status = Trueself.change_button.setText('暂停')song = self.table_widget.item(row, column).text()singer = self.table_widget.item(row, column - 1).text()query = Music.select().where((Music.song == song) & (Music.singer == singer))if query:self.current_index = query[0].idself.play_page = self.current_pageself.update_current_music()logger.info("双击播放:%s - %s", self.current_music, self.current_singer)self.play_music()def change_search_status(self):self.current_page = 1if not self.search_status:self.search_status = Trueself.search_btn.setText("返回列表")logger.info("点击搜索")self.con2 = lambda x: x == 0self.search_music()else:self.search_status = Falseself.search_btn.setText("搜索")query = Music.select().where(Music.show == 0)for q in query:q.show = 1q.save()self.con2 = lambda x: x >= 0self.load_music()self.search_text.setText('')logger.info("取消查询")def search_music(self):text = self.search_text.text()logger.info("点击查询:%s", text)if text:query = Music.select().where((Music.singer.contains(text)) | (Music.song.contains(text)))for q in query:q.show = Falseq.save()logger.info("查询到 %d条 相关内容", len(query))self.load_music()else:logger.info('未查询到相关音乐')def change_random_status(self):if not self.random_play_status:self.random_play_status = Trueself.play_random_btn.setText("取消随机")logger.info("切换为随机播放")query = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like))self.random_play_list= [q.id for q in query]logger.info("已加载随机列表")self.play_random()  # 切换时启动一次else:self.random_play_status = Falseself.play_random_btn.setText("随机播放")logger.info("取消随机播放")def play_random(self):if not self.random_play_list:self.change_random_status()  # 取消随机self.change_random_status()  # 重新随机self.current_index = random.choice(self.random_play_list)self.random_play_list.remove(self.current_index)logger.info("已获取随机音乐,剩余 %d 首", len(self.random_play_list))self.update_current_music()self.play_music()def load_music(self):total_records = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).count()self.total_pages = (total_records + self.page_size - 1) // self.page_sizeself.int_validator = QIntValidator(0, self.total_pages)records = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).offset((self.current_page - 1) * self.page_size).limit(self.page_size)self.table_widget.setRowCount(len(records))self.table_widget.setColumnCount(3)for i, record in enumerate(records):record.row = irecord.save()like = "收藏" if record.like == 0 else "已收藏"self.table_widget.setItem(i, 0, QTableWidgetItem(record.singer))self.table_widget.setItem(i, 1, QTableWidgetItem(record.song))self.table_widget.setItem(i, 2, QTableWidgetItem(like))self.table_widget.setHorizontalHeaderLabels(['歌手', '歌曲', '♥'])self.statusBar().showMessage(f'{self.current_page}/{self.total_pages}')logger.info('已加载音乐列表')def load_local_music(self, ensure):logger.info('重新加载列表')self.find_mp3_files() if ensure else None  # 从本地重新加载def show_favorite(self):self.current_page = 1if not self.show_favorite_status:logger.info('已进入我的收藏列表')self.show_favorite_status = Trueself.favorite_btn.setText('返回列表')self.con3 = lambda x: x == 1self.change_search_status() if self.search_status else Noneself.load_music()else:logger.info('已返回所有列表')self.show_favorite_status = Falseself.favorite_btn.setText('我的收藏')self.con3 = lambda x: x >= 0self.load_music()def update_current_music(self):self.current_music_info = Music.select().where(Music.id == self.current_index)[0]self.current_music = self.current_music_info.songself.current_singer = self.current_music_info.singerself.current_path = self.current_music_info.pathdef play_pre(self):logger.info("播放上一首")row = self.current_music_info.rowquery = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).offset((self.play_page - 1) * self.page_size).limit(self.page_size)if row == 0:self.play_page = self.total_pages if self.play_page == 1 else self.play_page - 1query = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).offset((self.play_page - 1) * self.page_size).limit(self.page_size)row = len(query) - 1logger.info(f"已播放至第一首,切换至最后一首")else:row -= 1self.current_index = query[row].idself.update_current_music()self.status = Trueself.change_button.setText('暂停')logger.info("切换音乐为:%s - %s", self.current_music, self.current_singer)self.play_music()def play_next(self):logger.info("播放下一首")row = self.current_music_info.rowquery = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).offset((self.play_page - 1) * self.page_size).limit(self.page_size)if row == len(query) - 1:  # 该页最后一条数据row = 0  # 切换至首条数据self.play_page = 1 if self.play_page == self.total_pages else self.play_page + 1  # 若为最后一页切换至首页query = Music.select().where(self.con1(Music.id) & self.con2(Music.show) & self.con3(Music.like)).offset((self.play_page - 1) * self.page_size).limit(self.page_size)  # 重新查询logger.info(f"已播放至最后一首,切换至第一首")else:row += 1self.current_index = query[row].idself.update_current_music()self.status = Trueself.change_button.setText('暂停')logger.info("切换音乐为:%s - %s", self.current_music, self.current_singer)self.play_music()def change_volume(self):value = self.volume_slider.value()self.player.setVolume(value)logger.info("滑动设置音量为%s", value)def set_position(self):self.music_pro_bar.resize(int(self.position / self.duration * self.music_pro_width), 10)def update_duration(self, duration):if not self.update_label:returnself.duration = durationdef update_position(self, position):if not self.update_label:returnself.position = positionself.set_position()def scroll_text(self):current_text = self.music_label.text()scroll_text = current_text[1:] + current_text[0]self.music_label.setText(scroll_text)self.music_label.setStyleSheet(f"color:{self.rgb2hex(*self.random_color())}")def click_prev_page(self):if self.current_page > 1:logger.info('跳转上一页')self.current_page -= 1self.load_music()def click_next_page(self):if self.current_page < self.total_pages:logger.info('跳转点击下一页')self.current_page += 1self.load_music()def jump_page(self):self.current_page = int(self.jump_page_text.text())logger.info('输入跳转 %d 页', self.current_page)self.load_music()def rgb2hex(self, r, g, b):return "#{:02x}{:02x}{:02x}".format(r, g, b)def find_mp3_files(self):  # 生成音乐文件列表,根据需求自定义for root, dirs, files in os.walk(self.music_path):for file in files:if fnmatch.fnmatch(file, '*.mp3'):if '_' in file:path = os.path.join(root, file)s = Music.select().where(Music.path == path)if s:continueelse:tp = Music(singer=file.split('_')[1].split('.')[0], song=file.split('_')[0],path=path, like=False, show=True)tp.save()def random_color(self):  # 随机颜色r, g, b = random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)return r, g, bif __name__ == "__main__":app = QApplication(sys.argv)player = MusicPlayer()player.show()sys.exit(app.exec_())

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/50107.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【区块链+绿色低碳】基于区块链的碳排放管理系统 | FISCO BCOS应用案例

目前业内的碳排放核查方式主要依靠于第三方人工核查、手动填报数据&#xff0c;然后由具备有认证资质的机构进行核验 盖章。但在此过程中存在数据造假的情况&#xff0c;给碳排放量核算的准确性、可靠性带来挑战。 中科易云采用国产开源联盟链 FISCO BCOS&#xff0c;推出基于…

搭建博客系统#Golang

WANLI 博客系统 项目介绍 基于vue3和gin框架开发的前后端分离个人博客系统&#xff0c;包含md格式的文本编辑展示&#xff0c;点赞评论收藏&#xff0c;新闻热点&#xff0c;匿名聊天室&#xff0c;文章搜索等功能。 项目已经部署并运行&#xff0c;快速开发可以查看博客&am…

培训第十一天(nfs与samba共享文件)

上午 1、环境准备 &#xff08;1&#xff09;yum源 &#xff08;一个云仓库pepl仓库&#xff09; [rootweb ~]# vim /etc/yum.repos.d/hh.repo [a]nameabaseurlfile:///mntgpgcheck0[rootweb ~]# vim /etc/fstab /dev/cdrom /mnt iso9660 defaults 0 0[rootweb ~]# mount -a[…

JavaSE--基础语法--继承和多态(第三期)

一.继承 1.1我们为什么需要继承? 首先&#xff0c;Java中使用类对现实世界中实体来进行描述&#xff0c;类经过实例化之后的产物对象&#xff0c;则可以用来表示现实中的实体&#xff0c;但是 现实世界错综复杂&#xff0c;事物之间可能会存在一些关联&#xff0c;那在设计程…

Java之数组应用-冒泡排序-二分查找

冒泡排序 冒泡(Bubble Sort)排序是一种简单排序算法&#xff0c;它通过依次比较交换两个相邻元素实现功能。每一次冒泡会让至少一个元素移动到它应该在的位置上&#xff0c;这样 n 次冒泡就完成了 n 个数据的排序工作。 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”…

实在智能RPA助力三大运营商用“AI+RPA”打造新质生产力!

近年来&#xff0c;人工智能及自动化技术的突破性进展&#xff0c;正深刻地影响和重塑全球的生活生产模式。 作为我国现代化和数字化进程中的先行军的运营商行业&#xff0c;以中国电信、中国联通和中国移动等为代表的运营商企业&#xff0c;正致力于把握这一历史机遇&#xff…

SpringBoot项目配置多环境env

javaSpringBoot项目多环境配置 为什么maven Profiles 救命项目的pom文件管理 为什么 项目里面需要集成测试环境、开发、生产、多云环境&#xff0c;不仅需要application.yml,还需要加载别的config配置文件 故&#xff0c;我需要便捷多环境配置管理 maven Profiles 救命 项目的…

MySQL练手 --- 1934. 确认率

题目链接&#xff1a;1934. 确认率 思路 由题可知&#xff0c;两个表&#xff0c;一个表为Signups注册表&#xff0c;另一个表为Confirmations信息确认表&#xff0c;表的关联关系为 一对一&#xff0c;且user_id作为两个表的连接条件&#xff08;匹配字段&#xff09;&#…

【C# WInForm】将TextBox从输入框设置为文本框

1.需求情形&#xff1a; textbox作为最常用的控件之一&#xff0c;通常是用来输入文本信息或者显示文字&#xff0c;但是如果要在界面中显示大段文本&#xff0c;一个带有边框、可选中的文本样式似乎不合适。像这样&#xff1a; 我需要的是这段文字不仅能跨行&#xff0c;而且…

c++笔记2

目录 2.2 栈底&#xff08;bottom&#xff09; } 大数乘大数 节点&#xff1a;包含一个数据元素及若干指向子树分支的信息 。 节点的度&#xff1a;一个节点拥有子树的数目称为节点的度 。 叶子节点&#xff1a;也称为终端节点&#xff0c;没有子树的节点或者度为零的节点…

elmentui this.$confirm使用模板字符串构建HTML结构

tip(){const checkingList [];const findList[入会1,入会2,入会3] //数组const sueccList [{name:入会,suecc:1000,numcot:1000},{name:aaaaa,suecc:222,numcot:3333}] //数组对象var message// 使用模板字符串构建HTML结构if(sueccList.length>0){message <div>…

Apache ShardingSphere Proxy5.5.0实现MySQL分库分表与读写分离

1. 前提准备 1.1 主机IP:192.168.186.77 version: 3.8services:mysql-master:image: mysql:latestcontainer_name: mysql-masterenvironment:MYSQL_ROOT_PASSWORD: 123456MYSQL_USER: masterMYSQL_PASSWORD: 123456MYSQL_DATABASE: db1 ports:- "3306:3306&quo…

ModuleNotFoundError: No module named ‘scrapy.utils.reqser‘

在scrapy中使用scrapy-rabbitmq-scheduler会出现报错 ModuleNotFoundError: No module named scrapy.utils.reqser原因是新的版本的scrapy已经摒弃了该方法,但是scrapy-rabbitmq-scheduler 没有及时的更新,所以此时有两种解决方法 方法一.将scrapy回退至旧版本,找到对应的旧版…

android13 Settings动态显示隐藏某一项

总纲 android13 rom 开发总纲说明 目录 1.前言 2.确定目标设置项 3.修改参考 3.1 方法1 3.2 方法2 4.编译测试 5.彩蛋 1.前言 在Android 13系统中,动态显示或隐藏Settings应用中的某一项通常涉及到对Settings应用的内部逻辑进行修改。由于Settings应用是一个系统应用…

Mybatis——快速入门

介绍 MyBatis是一款优秀的持久层&#xff08;Dao层&#xff09;框架&#xff0c;用于简化JDBC的开发。MyBatis 底层是基于 JDBC 实现的&#xff0c;它封装了 JDBC 的大部分功能&#xff0c;使得数据库操作更加便捷和高效。同时&#xff0c;MyBatis 也保留了 JDBC 的灵活性&…

通信原理-思科实验五:家庭终端以太网接入Internet实验

实验五 家庭终端以太网接入Internet实验 一实验内容 二实验目的 三实验原理 四实验步骤 1.按照上图选择对应的设备&#xff0c;并连接起来 为路由器R0两个端口配置IP 为路由器R1端口配置IP 为路由器设备增加RIP&#xff0c;配置接入互联网的IP的动态路由项 5.为路由器R1配置静…

锁相环 vivado FPGA

原理 同步状态/跟踪状态&#xff1a;相位差在2kπ附近&#xff0c;频率差为0到达上述状态的过程称为捕获过程锁相环的捕获带&#xff1a;delta w的最大值&#xff0c;大于这个值的话就不能捕获鉴相器&#xff08;PD-phase discriminator&#xff09;&#xff1a;相乘加LPF&…

Vue3 FileReader:readAsBinaryString() 过时,要使用readAsArrayBuffer来代替。

1、先上张图&#xff1a; 2、官网 developer.mozilla.org https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsBinaryString ​​​​​​​FileReader接口的 readAsBinaryString() 方法用于开始读取指定 Blob 或 File 对象的内容。当读操作完成后&#xff0…

免杀笔记 -->API的整理Shellcode加密(过DeFender)

最近更新频率明显下降我懒&#xff0c;那么今天就来记录一下我们的一些常用的API的整理以及ShellCode的加密。 1.WinAPI整理 问我为什么要整理&#xff1f; 就是用起来的时候要左翻右翻 &#xff1a;&#xff1a; 烦死了 1.VirtualAlloc VirtualAlloc(NULL,sizeof(buf),MEM_…

Redis 7.x 系列【29】集群原理之自动故障转移

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 案例演示3. 工作原理3.1 故障检测3.2 排名3.3 延迟等待3.4 投票3.5 上位 1.…