C++音视频04:音视频编码、生成图片

视频编码

#include <libavutil/log.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) {int ret = -1;ret = avcodec_send_frame(ctx, frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_packet(ctx, pkt);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}fwrite(pkt->data, 1, pkt->size, out);av_packet_unref(pkt);}
_END:return 0;
}int main(int argc, char *argv[]) {char *dst = NULL;char *codecName = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;int ret = -1;FILE *f = NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;av_log_set_level(AV_LOG_DEBUG);// 1. 输入参数if (argc < 3) {av_log(NULL, AV_LOG_ERROR, "arguments must more than 3\n");goto _ERROR;}dst = argv[1];codecName = argv[2];// 2. 查找编码器codec = avcodec_find_encoder_by_name(codecName);if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec name %s\n", codecName);goto _ERROR;}// 3. 创建编码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 4. 设置编码器参数ctx->width = 640;ctx->height = 480;ctx->bit_rate = 500000;// 时间基和帧率ctx->time_base = (AVRational){1, 25};ctx->framerate = (AVRational){25, 1};// 设置每10帧一个gopctx->gop_size = 10;// 设置一个gop中最多有一个b帧ctx->max_b_frames = 1;// 设置yuv格式ctx->pix_fmt = AV_PIX_FMT_YUV422P;if (codec->id == AV_CODEC_ID_H264) {av_opt_set(ctx->priv_data, "preset", "slow", 0);}// 5. 编码器与编码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}// 6. 创建输出文件f = fopen(dst, "wb");if (!f) {av_log(NULL, AV_LOG_ERROR, "Don't open file %s\n", dst);goto _ERROR;}// 7. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 必须赋值才能获取到bufferframe->width = ctx->width;frame->height = ctx->height;frame->format = ctx->pix_fmt;// frame中真正存储数据的位置不会被av_frame_alloc生成,还需要调用av_frame_get_buffer获取ret = av_frame_get_buffer(frame, 0);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Could't not allocate the video frame\n");goto _ERROR;}// 8. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 9. 生成视频内容// 这里是虚拟生成25帧,即一秒钟的数据for (int i = 0; i < 25; ++i) {// 确保av_frame中的空间data可用,如果当前data域被锁定了,就会自动指定一个新的dataret = av_frame_make_writable(frame);if (ret < 0) {break;}// Y分量for (int y = 0; y < ctx->height; y++) {for (int x = 0; x < ctx->width; x++) {// data[0] 指的是yuv中的y,[frame->linesize[0] 指的是行的大小, x表示横轴位移]// x + y + i * 3表示Y分量随着x和y变化而渐变frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;}}// UV分量for (int y = 0; y < ctx->height; y++) {// 对应uv分量 422中都是y分量的一半,所以除以2for (int x = 0; x < ctx->width / 2; x++) {// U分量 128在U分量代表黑色, 后面的2是任意的frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;// V分量 64在V分量中代表黑色, 后面的5是任意的frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;}}frame->pts = i;// 10. 编码ret = encode(ctx, frame, pkt, f);if (ret == -1) {goto _ERROR;}}// 输出一个空包,用于刷新剩余数据encode(ctx, NULL, pkt, f);
_ERROR:if (ctx) {avcodec_free_context(&ctx);}if (frame) {av_frame_free(&frame);}if (pkt) {av_packet_free(&pkt);}if (f) {fclose(f);}return 0;
}
gcc -g -o encode_video encode_video.c `pkg-config --libs libavutil libavformat`./encode_video 1.h264 libx264

音频编码

#include <libavutil/log.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/samplefmt.h>static int select_best_sample_rate(const AVCodec *codec) {const int *p;int best_sample_rate = 0;if (!codec->supported_samplerates) {return 44100;}p = codec->supported_samplerates;// 找到一个离44100最近的采样率while (*p) {if (!best_sample_rate || abs(44100 - *p) < abs(44100 - best_sample_rate)) {best_sample_rate = *p;}p++;}return best_sample_rate;
}// ffmpeg源码自带
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{const enum AVSampleFormat *p = codec->sample_fmts;while (*p != AV_SAMPLE_FMT_NONE) {if (*p == sample_fmt)return 1;p++;}return 0;
}static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) {int ret = -1;ret = avcodec_send_frame(ctx, frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_packet(ctx, pkt);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}fwrite(pkt->data, 1, pkt->size, out);av_packet_unref(pkt);}
_END:return 0;
}int main(int argc, char *argv[]) {char *dst = NULL;char *codecName = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;int ret = -1;FILE *f = NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;uint16_t *samples = NULL;av_log_set_level(AV_LOG_DEBUG);// 1. 输入参数if (argc < 2) {av_log(NULL, AV_LOG_ERROR, "arguments must more than 2\n");goto _ERROR;}dst = argv[1];// codecName = argv[2];// 2. 查找编码器:两种方式,by_name可以使用外部的库,通过CODEC_ID的则使用FFMpeg自带的库// codec = avcodec_find_encoder_by_name("libx264");codec = avcodec_find_encoder_by_name("libfdk_aac");// codec = avcodec_find_encoder(AV_CODEC_ID_AAC); // 用这个会涉及下面注释的一系列修改if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec name %s\n", codecName);goto _ERROR;}// 3. 创建编码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 4. 设置编码器参数ctx->bit_rate = 64000;ctx->sample_fmt = AV_SAMPLE_FMT_S16;// AV_SAMPLE_FMT_FLTP,对于ffmpeg内部的编码器 用这个格式ret = check_sample_fmt(codec, AV_SAMPLE_FMT_S16); if (ret == 0) {av_log(NULL, AV_LOG_ERROR, "encoder do not support sample format\n");goto _ERROR;}// 自定义函数找到最接近44100的采样率ctx->sample_rate = select_best_sample_rate(codec);// 设置声道布局为立体声stereoav_channel_layout_copy(&ctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); // AV_CHANNEL_LAYOUT_MONO ffmpeg内部编码器修改成这个// 5. 编码器与编码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}// 6. 创建输出文件f = fopen(dst, "wb");if (!f) {av_log(NULL, AV_LOG_ERROR, "Don't open file %s\n", dst);goto _ERROR;}// 7. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 必须赋值才能获取到bufferframe->nb_samples = ctx->frame_size;frame->format = ctx->sample_fmt;av_channel_layout_copy(&frame->ch_layout, &ctx->ch_layout);// frame中真正存储数据的位置不会被av_frame_alloc生成,还需要调用av_frame_get_buffer获取ret = av_frame_get_buffer(frame, 0);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Could't not allocate the video frame\n");goto _ERROR;}// 8. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 9. 生成音频内容float t = 0.0;// 有空了解一下这个值float tincr = 2 * M_PI * 440 / ctx->sample_rate;for (int i = 0; i < 200; ++i) {ret = av_frame_make_writable(frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "do not allocate space\n");goto _ERROR;}samples = (uint16_t*)frame->data[0]; // FLTP是32位的 所以改成uint32, 下面所有2都得改成4// 2字节一个数据for (int j = 0; j < ctx->frame_size; ++j) {samples[2 * j] = (sin(t) * 10000);// 多声道的处理for (int k = 1; k < ctx->ch_layout.nb_channels; ++k) {samples[2 * j + k] = samples[2 * j];}t += tincr;}encode(ctx, frame, pkt, f);}// 输出一个空包,用于刷新剩余数据encode(ctx, NULL, pkt, f);
_ERROR:if (ctx) {avcodec_free_context(&ctx);}if (frame) {av_frame_free(&frame);}if (pkt) {av_packet_free(&pkt);}if (f) {fclose(f);}return 0;
}
gcc -g -o encode_audio encode_audio.c `pkg-config --libs libavutil libavformat`./encode_audio 1.aac

由于ffmpeg自带的aac格式是32位的AV_SAMPLE_FMT_FLTP,如果由libfdk_aac转成ffmpeg自带的aac,需要进行重采样成FLTP才能继续其他操作

生成图片

生成黑白色图片

先把视频解码成帧序列,然后将帧保存为图片

#include <libavformat/avformat.h>
#include <libavutil/log.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>static void savePic(unsigned char *buf, int lineSize, int width, int height, char *name) {FILE *f;f = fopen(name, "wb");// 写入头信息fprintf(f, "P5\n%d %d\n%d\n", width, height, 255);for (int i = 0; i < height; ++i) {fwrite(buf + i *lineSize, 1, width, f);}fclose(f);
}static int decode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, const char *fileName) {int ret = -1;char buf[1024];ret = avcodec_send_packet(ctx, pkt);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_frame(ctx, frame);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}snprintf(buf, sizeof(buf), "%s-%d", fileName, ctx->frame_num);savePic(frame->data[0], frame->linesize[0], frame->width, frame->height, buf);if (pkt) {av_packet_unref(pkt);}}
_END:return 0;
}int main (int argc, char *argv[]) {// 1. 处理参数char *src;char *dst;int ret;int idx = -1;AVFormatContext *pFmtCtx = NULL;AVPacket *pkt = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;AVFrame *frame = NULL;AVStream *inStream = NULL;av_log_set_level(AV_LOG_DEBUG);if (argc < 3) {av_log(NULL, AV_LOG_ERROR, "argument must be more than 3\n");exit(-1);}src = argv[1];dst = argv[2];// 2. 打开多媒体文件ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));exit(-1);}// 3. 从多媒体文件中找到音频流idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if (idx < 0) {av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio stream\n");goto _ERROR;}inStream = pFmtCtx->streams[idx];// 4. 查找解码器codec = avcodec_find_decoder(inStream->codecpar->codec_id);if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec\n");goto _ERROR;}// 5. 创建解码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 拷贝编码参数到上下文对象avcodec_parameters_to_context(ctx, inStream->codecpar);// 5. 解码器与解码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}// 6. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 7. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 8. 从源多媒体文件中读数据到目的文件中while (av_read_frame(pFmtCtx, pkt) >= 0) {if (pkt->stream_index == idx) {decode(ctx, frame, pkt, dst);}}decode(ctx, frame, NULL, dst);// 9. 将申请的资源释放掉
_ERROR:if (pFmtCtx) {avformat_close_input(&pFmtCtx);pFmtCtx = NULL;}    if (ctx) {avcodec_free_context(&ctx);ctx = NULL;}if (frame) {av_frame_free(&frame);frame = NULL;}if (pkt) {av_packet_free(&pkt);pkt = NULL;}return 0;
}
gcc -g -o gen_pic gen_pic.c `pkg-config --libs libavutil libavformat`./gen_pic ~/resource/1.mp4 out/out

生成彩色图片BMP

代码目前有bug尚未找出

#include <libavformat/avformat.h>
#include <libavutil/log.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>#define WORD uint64_t
#define DWORD uint32_t
#define LONG int32_t
// 去网站上拷贝对应定义:https://learn.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader
typedef struct tagBITMAPINFOHEADER {DWORD biSize;LONG  biWidth;LONG  biHeight;WORD  biPlanes;WORD  biBitCount;DWORD biCompression;DWORD biSizeImage;LONG  biXPelsPerMeter;LONG  biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} BITMAPINFOHEADER, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;typedef struct tagBITMAPFILEHEADER {WORD  bfType;DWORD bfSize;WORD  bfReserved1;WORD  bfReserved2;DWORD bfOffBits;
} BITMAPFILEHEADER, *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;static void saveBMP(struct SwsContext *swsCtx,AVFrame *frame, int w, int h, char *name) {FILE *f = NULL;// 3是因为转换成24位的帧,刚好3个字节int dataSize = w * h * 3;// 1. 进行转换,将yuv frame 转成 BRG24 FrameAVFrame *frameBGR = av_frame_alloc();frameBGR->width = w;frameBGR->height = h;frameBGR->format = AV_PIX_FMT_BGR24;av_frame_get_buffer(frameBGR, 0);sws_scale(swsCtx, (const uint8_t *const *)frame->data,frame->linesize,0,frame->height,frameBGR->data, frameBGR->linesize);// 2. 构造 BITMAP INFO HEADERBITMAPINFOHEADER infoHeader;infoHeader.biSize = sizeof(BITMAPINFOHEADER);infoHeader.biWidth = w;infoHeader.biHeight = h * (-1); // 坐标与正常坐标相反infoHeader.biBitCount = 24;infoHeader.biCompression = 0;infoHeader.biSizeImage = 0;infoHeader.biClrImportant = 0;infoHeader.biClrUsed = 0;infoHeader.biXPelsPerMeter = 0;infoHeader.biYPelsPerMeter = 0;infoHeader.biPlanes = 0;// 3. 构造 BITMAP FILE HEADERBITMAPFILEHEADER fileHeader;fileHeader.bfType = 0x4d42; //  表示两个字符‘BM’fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dataSize;fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);// 4. 将数据写到文件f = fopen(name, "wb");fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, f);fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, f);fwrite(&frame->data[0], 1, dataSize, f);// 5. 释放资源   fclose(f);av_freep(&frameBGR->data[0]);av_free(frameBGR);}static void savePic(unsigned char *buf, int lineSize, int width, int height, char *name) {FILE *f;f = fopen(name, "wb");// 写入头信息fprintf(f, "P5\n%d %d\n%d\n", width, height, 255);for (int i = 0; i < height; ++i) {fwrite(buf + i *lineSize, 1, width, f);}fclose(f);
}static int decode(AVCodecContext *ctx, struct SwsContext *swsCtx,AVFrame *frame, AVPacket *pkt, const char *fileName) {int ret = -1;char buf[1024];ret = avcodec_send_packet(ctx, pkt);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_frame(ctx, frame);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}snprintf(buf, sizeof(buf), "%s-%d.bmp", fileName, ctx->frame_num);// savePic(frame->data[0], frame->linesize[0], frame->width, frame->height, buf);saveBMP(swsCtx, frame, frame->width, frame->height, buf);// 释放前需要判空if (pkt) {av_packet_unref(pkt);}}
_END:return 0;
}int main (int argc, char *argv[]) {// 1. 处理参数char *src;char *dst;int ret;int idx = -1;AVFormatContext *pFmtCtx = NULL;AVPacket *pkt = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;AVFrame *frame = NULL;AVStream *inStream = NULL;struct SwsContext *swsCtx = NULL;av_log_set_level(AV_LOG_DEBUG);if (argc < 3) {av_log(NULL, AV_LOG_ERROR, "argument must be more than 3\n");exit(-1);}src = argv[1];dst = argv[2];// 2. 打开多媒体文件ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));exit(-1);}// 3. 从多媒体文件中找到音频流idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if (idx < 0) {av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio stream\n");goto _ERROR;}inStream = pFmtCtx->streams[idx];// 4. 查找解码器codec = avcodec_find_decoder(inStream->codecpar->codec_id);if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec\n");goto _ERROR;}// 5. 创建解码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 拷贝编码参数到上下文对象avcodec_parameters_to_context(ctx, inStream->codecpar);// 5. 解码器与解码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}av_log(NULL, AV_LOG_INFO, "scale: %d, %d\n", ctx->width, ctx->height);// 5.1 获得SWS上下文sws_getCachedContext(NULL, ctx->width,         // src widthctx->height,        // src height AV_PIX_FMT_YUV420P,       // src pix fmt 有时候ctx->pix_fmt的格式是不对的640,         // dst width   这里的640 x 360 是因为需要按比例360,        // dst heightAV_PIX_FMT_BGR24,   // dst pix fmtSWS_BICUBIC,        // 后面研究NULL, NULL, NULL);// 6. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 7. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 8. 从源多媒体文件中读数据到目的文件中while (av_read_frame(pFmtCtx, pkt) >= 0) {if (pkt->stream_index == idx) {decode(ctx, swsCtx, frame, pkt, dst);}}decode(ctx, swsCtx, frame, NULL, dst);// 9. 将申请的资源释放掉
_ERROR:if (pFmtCtx) {avformat_close_input(&pFmtCtx);pFmtCtx = NULL;}    if (ctx) {avcodec_free_context(&ctx);ctx = NULL;}if (frame) {av_frame_free(&frame);frame = NULL;}if (pkt) {av_packet_free(&pkt);pkt = NULL;}return 0;
}

gcc -g -o gen_pic gen_pic.c pkg-config --libs libavutil libavformat libswscale

./gen_pic ~/resource/1.mp4 out/out


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

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

相关文章

QT界面开发--我的第一个windows窗体【菜单栏、工具栏、状态栏、铆接部件、文本编辑器、按钮、主界面】

经过前面的铺垫&#xff0c;今天我们就开始我们图形化界面之旅了&#xff0c;我们的第一个窗体主要包括&#xff1a;菜单栏、状态栏、工具栏、铆接部件、还有Qt提供的一些主窗体的API。 第一部分&#xff1a;主界面(QMainWindow) 当创建好项目后&#xff0c;我们直接运行&…

logdata-anomaly-miner:一款安全日志解析与异常检测工具

关于logdata-anomaly-miner logdata-anomaly-miner是一款安全日志解析与异常检测工具&#xff0c;该工具旨在以有限的资源和尽可能低的权限运行分析&#xff0c;以使其适合生产服务器使用。 为了确保 logdata-anomaly-miner的正常运行&#xff0c;推荐安装了python > 3.6的…

Qt 文本文件读写与保存

Qt 文本文件读写与保存 开发工具&#xff1a;VS2013 QT5.8 设计UI界面&#xff0c;如下图所示 sample7_1QFile.h 头文件&#xff1a; #pragma once#include <QtWidgets/QMainWindow> #include "ui_sample7_1QFile.h"class sample7_1QFile : public QMainWin…

中国人寿财险青岛市分公司:保障民生,传递关爱

中国人寿财险青岛市分公司以保障民生为使命&#xff0c;传递关爱与温暖。 在健康险领域&#xff0c;公司为市民提供全面的医疗保障。从重大疾病保险到普通医疗保险&#xff0c;满足不同客户的需求。通过与医疗机构合作&#xff0c;为客户提供便捷的就医服务和理赔服务&#xf…

Linux下的文件IO操作

目录 1.前导 1.1文件知识 1.2对比一下文件操作和重定向 1.2.1输入重定向 1.2.2追加重定向 1.3当前路径 1.4stdin stdout stderr 2.文件操作的系统调用接口 2.1.open()打开文件 2.1.2.flags参数 2.1.3.mode参数 2.1.3 umask()函数 2.2.write()向文件写入 ​编辑 2…

【Kaggle | Pandas】练习1:创造、阅读和写作

文章目录 1. 创建DataFrame2. 创建数据表3. 创建可变Series表4. 读取csv 数据集5. 保存csv 文件 1. 创建DataFrame 在下面的单元格中&#xff0c;创建一个 DataFrame fruits &#xff0c;如下所示&#xff1a; import pandas as pd # Your code goes here. Create a datafr…

Javaee---多线程(一)

文章目录 1.线程的概念2.休眠里面的异常处理3.实现runnable接口4.匿名内部类子类创建线程5.匿名内部类接口创建线程6.基于lambda表达式进行线程创建7.关于Thread的其他的使用方法7.1线程的名字7.2设置为前台线程7.3判断线程是否存活 8.创建线程方法总结9.start方法10.终止&…

Spring《声明式事务》

知识点&#xff1a; Spring 声明式事务 1.基于注解和配置类的Spring-jdbc环境搭建 1. 准备项目&#xff0c;pom.xml <dependencies> <!--spring context依赖--> <!--当你引入Spring Context依赖之后&#xff0c;表示将Spring的基础依赖引入了--> …

七款主流图纸加密软件强力推荐|2024年CAD图纸加密保护指南

在当今信息化的设计行业&#xff0c;保护CAD图纸的知识产权和数据安全变得尤为重要。随着越来越多的企业采用数字化设计和共享文件&#xff0c;如何防止CAD图纸被未经授权的访问和窃取成为了许多设计师和企业关注的焦点。为此&#xff0c;选用合适的图纸加密软件是保护CAD文件安…

《数据结构》学习系列——树(下)

系列文章目录 目录 树和森林的遍历树的遍历森林的遍历基本算法递归先根遍历树迭代先根遍历树树和森林的层次遍历 压缩与哈夫曼树文件编码扩充二叉树哈夫曼树和哈夫曼编码哈夫曼树的基本思路哈夫曼编码 树和森林的遍历 树的遍历 先根遍历&#xff1a;先访问树的根结点&#x…

想作弊❓用这个发起考试,根本没法作弊

&#x1f389; 推荐一款超实用的在线考试神器 —— 土著刷题✨ 如果你正在寻找一个既方便又高效的在线考试平台&#xff0c;那么“土著刷题”小&#x1f34a;序绝对值得一试&#xff01;它不仅完全免费&#xff0c;而且操作简单&#xff0c;非常适合用来组织线上测试。 &#x…

使用Angular构建动态Web应用

&#x1f496; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4bb; Gitee主页&#xff1a;瑕疵的gitee主页 &#x1f680; 文章专栏&#xff1a;《热点资讯》 使用Angular构建动态Web应用 1 引言 2 Angular简介 3 安装Angular 4 创建Angular项目 5 设计应用结构 6 创建组件 7 …

「Java SPI机制应用快速入门」: 一种JDK内置的服务提供发现机制

文章目录 什么是SPISPI机制的应用使用方法使用规范 入门案例 什么是SPI SPI首先是一种机制&#xff0c;这个机制叫&#xff1a;服务提供发现机制。那是谁来负责发现呢&#xff1f;当然是JDK内置的服务帮助我们发现啦。发现了帮助我们去调用&#xff0c;我们要做的就是在中间去…

2024护理类科技核心期刊汇总(最新版)

2024年9月中国科技核心期刊目录&#xff08;2024年版&#xff09;正式公布&#xff0c;13本护理类期刊入选。常笑医学整理了这13本护理类科技核心期刊的详细参数&#xff0c;以及投稿经验&#xff0c;供大家在论文投稿时参考&#xff0c;有需要的赶紧收藏&#xff01; 1.《中华…

SwiftUI(四)- 布局(VStack、HStack、ZStack)

引言 页面的搭建和布局在应用开发中几乎占据了一半的代码量。定于iOS开发而言&#xff0c;相较于其它平台&#xff0c;UIKit的布局方式显得相对局限&#xff0c;通常只有绝对布局和相对布局两种方案。而在Flutter或者Android开发中&#xff0c;布局选项更为丰富&#xff0c;比…

【mod分享】极品飞车9冬日mod,支持光追,想体验一把冬天的Rockport市吗

各位好&#xff0c;今天小编给大家带来一款新的高清重置魔改MOD&#xff0c;本次高清重置的游戏叫《极品飞车9最高通缉》。 《极品飞车&#xff1a;最高通缉》作为一款2005年的游戏&#xff0c;《极品飞车&#xff1a;最高通缉》的画面效果还是可以的&#xff0c;效果全开之后…

【状态机DP】力扣1186. 删除一次得到子数组最大和

给你一个整数数组&#xff0c;返回它的某个 非空 子数组&#xff08;连续元素&#xff09;在执行一次可选的删除操作后&#xff0c;所能得到的最大元素总和。换句话说&#xff0c;你可以从原数组中选出一个子数组&#xff0c;并可以决定要不要从中删除一个元素&#xff08;只能…

手机拍证件照,换正装有领衣服及底色的方法

证件照在我们的职业生涯的关键节点是经常会用到的&#xff0c;比如毕业入职、人事档案建立、升迁履历、执业资格考试和领证等&#xff0c;这些重要的证件照往往要求使用正装照&#xff0c;有时候手头没有合适的衣服&#xff0c;或者原先的证件照背景色不符合要求&#xff0c;就…

numpy——数学运算

一、标量——矢量 import numpy as npa 3.14 b np.array([[9, 5], [2, 7]])print(a) print(b)# ---------- 四则运算 ---------- print(a b) # np.add print(a - b) # np.subtract print(a * b) # np.multiply print(a / b) # np.divide 二、矢量——矢量 import nump…

优选算法精品课--双指针算法(2)

双指针算法&#xff08;2&#xff09; 1、有效三角形的个数1.1 题目解析1.2 思路解析1.3 代码实现 2、和为s的两个数2.1 题目解析2.2 思路解析2.3 代码实现 3、三数之和3.1 题目解析3.2 思路解析3.3 代码实现 4、四数之和4.1 题目解析4.2 思路解析4.3 代码实现 5 总结 1、有效三…