Google Earth Engine(GEE)深度学习入门教程-Python数据读入篇

Python数据读入篇

前置条件:

  • GEE预处理影像导出保存为tfrecord的数据包,并下载到本地
  • tensorflow的深度学习环境

本篇文章的目的主要是把Tfrecord格式的数据加载为tf可使用的数据集格式

设定超参数

首先需要设定导出时的波段名称和数据格式,用于解析数据。

变量名:

  • KERNEL_SIZE :单个patch的大小
  • FEATURES:波段的名称
  • dtype=tf.float32 :数据格式
# 所有波段的名称
BANDS = ["B2","B3","B4","B5","B6","B7","B8","B8A","B11","B12"]
TIMES = 12 
ALLBANDS = [ "%d_"%(i)+s for i in range(TIMES) for s in BANDS ]
print('所有的波段名称为:',ALLBANDS)
RESPONSE = 'soya'
FEATURES = ALLBANDS + [RESPONSE]
#输出:
#所有的波段名称为: ['0_B2', '0_B3', '0_B4', '0_B5', '0_B6', '0_B7', '0_B8', '0_B8A', '0_B11', '0_B12', '1_B2', '1_B3', '1_B4', '1_B5', '1_B6', '1_B7', '1_B8', '1_B8A', '1_B11', '1_B12', '2_B2', '2_B3', '2_B4', '2_B5', '2_B6', '2_B7', '2_B8', '2_B8A', '2_B11', '2_B12', '3_B2', '3_B3', '3_B4', '3_B5', '3_B6', '3_B7', '3_B8', '3_B8A', '3_B11', '3_B12', '4_B2', '4_B3', '4_B4', '4_B5', '4_B6', '4_B7', '4_B8', '4_B8A', '4_B11', '4_B12', '5_B2', '5_B3', '5_B4', '5_B5', '5_B6', '5_B7', '5_B8', '5_B8A', '5_B11', '5_B12', '6_B2', '6_B3', '6_B4', '6_B5', '6_B6', '6_B7', '6_B8', '6_B8A', '6_B11', '6_B12', '7_B2', '7_B3', '7_B4', '7_B5', '7_B6', '7_B7', '7_B8', '7_B8A', '7_B11', '7_B12', '8_B2', '8_B3', '8_B4', '8_B5', '8_B6', '8_B7', '8_B8', '8_B8A', '8_B11', '8_B12', '9_B2', '9_B3', '9_B4', '9_B5', '9_B6', '9_B7', '9_B8', '9_B8A', '9_B11', '9_B12', '10_B2', '10_B3', '10_B4', '10_B5', '10_B6', '10_B7', '10_B8', '10_B8A', '10_B11', '10_B12', '11_B2', '11_B3', '11_B4', '11_B5', '11_B6', '11_B7', '11_B8', '11_B8A', '11_B11', '11_B12','soya']# 单个patch的大小和数据类型
KERNEL_SIZE = 64
KERNEL_SHAPE = [KERNEL_SIZE, KERNEL_SIZE]
COLUMNS = [tf.io.FixedLenFeature(shape=KERNEL_SHAPE, dtype=tf.float32) for k in FEATURES
]
FEATURES_DICT = dict(zip(FEATURES, COLUMNS))# 单个数据包中样本的数量
BUFFER_SIZE = 160

解析数据

编写解析数据包的函数

parse_tfrecord( )和get_dataset( )函数是基本固定的

to_HWTCtuple(inputs)函数可根据自己的数据格式进行修改。数据的归一化和标准化、拓展特征等处理操作都可以放在此函数里。本文此处仅仅将折叠120维的数据展开为12(时相)×10(波段),数据集单个样本(HWTC格式)的大小为此时64×64×12×10。

def parse_tfrecord(example_proto):"""The parsing function.Read a serialized example into the structure defined by FEATURES_DICT.Args:example_proto: a serialized Example.Returns:A dictionary of tensors, keyed by feature name."""return tf.io.parse_single_example(example_proto, FEATURES_DICT)
def to_HWTCtuple(inputs):"""Function to convert a dictionary of tensors to a tuple of (inputs, outputs).Turn the tensors returned by parse_tfrecord into a stack in HWCT shape.Args:inputs: A dictionary of tensors, keyed by feature name.Returns:A tuple of (inputs, outputs)."""# 读取出多时相多波段影像inputsList = [inputs.get(key) for key in ALLBANDS]label = inputs.get(RESPONSE)stacked = tf.stack(inputsList, axis=0)# 从通道维展开出时间维,TIMES在前,len(BANDS)在后,不可以反#stacked = tf.reshape(stacked, [12,10,KERNEL_SIZE, KERNEL_SIZE])stacked = tf.reshape(stacked, [TIMES,len(BANDS),KERNEL_SIZE, KERNEL_SIZE])# Convert from TCHW to HWTCstacked = tf.transpose(stacked, [2,3,0,1])return stacked, label
def get_dataset(namelist):"""Function to read, parse and format to tuple a set of input tfrecord files.Get all the files matching the pattern, parse and convert to tuple.Args:namelist: A file list in a Cloud Storage bucket.Returns:A tf.data.Dataset"""dataset = tf.data.TFRecordDataset(namelist, compression_type='GZIP')dataset = dataset.map(parse_tfrecord, num_parallel_calls=5)dataset = dataset.map(to_HWTCtuple, num_parallel_calls=5)return dataset

编写训练集和验证机的加载函数,根据自己的需求加载指定路径的数据包。BATCH_SIZE可根据自己GPU显存设置,此处为8

trainPath = 'data/guoyang/training_patches_g%d.tfrecord.gz'
trainIndex = [14,20,19,25,13,31,24,15,18,7,30,26,21,29,16,8,28,27,12,11,17,33,4,32,9,10,22]
training_patches_size = 27
BATCH_SIZE = 8
def get_training_dataset():"""Get the preprocessed training datasetReturns: A tf.data.Dataset of training data."""namelist = [trainPath%(i) for i in trainIndex]dataset = get_dataset(namelist)dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE,drop_remainder=True).repeat()return datasetevalPath = 'data/guoyang/eval_patches_g%d.tfrecord.gz'
evalIndex = [9,12,13,3,5,1,6,4,2]
eval_patches_size = 9
EVAL_BATCH_SIZE = 8
def get_eval_dataset():"""Get the preprocessed evaluation datasetReturns: A tf.data.Dataset of evaluation data."""namelist = [evalPath%(i) for i in evalIndex]dataset = get_dataset(namelist)dataset = dataset.batch(EVAL_BATCH_SIZE,drop_remainder=True).repeat()return datasetevaluation = get_eval_dataset()training = get_training_dataset()

读取单个样本,测试数据集是否加载成功。

data,label = iter(training.take(1)).next()
i = 3
print(data.shape)
#(8, 64, 64, 12, 10)

可视化

首先编写并测试显示所需要的函数。

#测试显示函数
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from matplotlib.colors import ListedColormapdef show_image(tensor,index ,savename =None):# 从HWTC到THWCtensor = np.transpose(tensor, (2, 0,1,3))# 获取 tensor 中每个通道的数据r_channel = tensor[:, :, :, index[0]-2]  # 红色通道g_channel = tensor[:, :, :, index[1]-2]  # 绿色通道b_channel = tensor[:, :, :, index[2]-2]  # 蓝色通道# 将通道的数据拼接成一个 RGB 图像image = np.stack([r_channel, g_channel, b_channel], axis=3)# 定义一个变量来保存图片数量num_images = image.shape[0]# 定义每行显示的图片数量num_images_per_row = 4# 计算行数和列数num_rows = int(np.ceil(num_images / num_images_per_row))num_columns = num_images_per_row# 定义画布的大小fig, axes = plt.subplots(num_rows, num_columns, figsize=(15, 15))# 展示每张图片for i, ax in enumerate(axes.flat):# 如果图片数量不足,则跳过if i >= num_images:break# 分别计算每个波段的%2的像素值img = image[i]vmin_b1, vmax_b1 = np.percentile(img[:, :, 0], (2, 98))vmin_b2, vmax_b2 = np.percentile(img[:, :, 1], (2, 98))vmin_b3, vmax_b3 = np.percentile(img[:, :, 2], (2, 98))# 线性拉伸每个波段并合并为RGB彩色图像image_r = np.interp(img[:, :, 0], (vmin_b1, vmax_b1), (0, 1))image_g = np.interp(img[:, :, 1], (vmin_b2, vmax_b2), (0, 1))image_b = np.interp(img[:, :, 2], (vmin_b3, vmax_b3), (0, 1))image_rgb = np.dstack((image_r, image_g, image_b))# 显示图片ax.imshow(image_rgb)if savename:Image.fromarray(np.uint8(image_rgb*255)).save(f"img/{savename}_{i}.png")  #.resize((512,512),resample = Image.NEAREST)ax.set_title('TimeSeries Image%d'%(i))# 关闭刻度线ax.axis('off')# 展示所有图片plt.show()
def show_label(tensor , savename =None):# 创建一个浅绿色的 colormapcmap = ListedColormap(['white', 'palegreen'])# 显示二值化图像fig, ax = plt.subplots()ax.imshow(tensor, cmap=cmap)if savename:Image.fromarray(np.uint8(tensor*255)).save(f"img/{savename}.png")   #.resize((512,512),resample = Image.NEAREST)# 隐藏坐标轴ax.axis('off')ax.set_title('Label Image')plt.show()# 随机生成一个大小为 [2, 128, 128, 10] 的张量
tf.random.set_seed(0)
tensor = tf.random.normal([128, 128,4,10])# 调用 show_image 函数进行展示
show_image(tensor.numpy(),[2,3,4])# 随机生成一个 8x8 的二值化图像
image = np.random.randint(2, size=(8, 8))
show_label(image)

image-20240114084045901

编写区块拼接函数,测试区块通常是通过滑窗的方式裁切出多个样本,因此在导出最终结果的时候需要将整个区块拼接起来并保存。

此函数部分需要根据实际情况进行具体调整,因为GEE导出时边缘似乎是不太固定的(未解决的问题),所以导出的时候需要增加缓冲区,在此处再将缓冲区裁剪掉。num_rows 和 num_cols代表区块内patch的行列数,可以从GEE导出的json格式文件中获取,num_rows和num_cols不一致是因为GEE导出坐标系为默认EPSG:4326(地理坐标系),作者后来更改为EPSG:32650(投影坐标系),num_rows和num_cols就相同了(区块为矩形)。

def mosicImage(data,core_size = 32,num_rows = 15,num_cols = 18):buffer = int(core_size/2)# 创建大图的空数组big_image = np.zeros(((num_rows+1) * core_size, (num_cols+1) * core_size, 12, 10))# 遍历原始数据index = 0for i in range(num_rows):for j in range(num_cols):# 计算当前核心区域的索引范围start_row = i * core_size  end_row = (i + 1) * core_size start_col = j * core_sizeend_col = (j + 1) * core_size# 提取当前核心区域的数据core_data = data[index,buffer:buffer+core_size, buffer:buffer+core_size,:,:]# 将核心区域的数据放入大图的对应位置big_image[start_row:end_row, start_col:end_col,:,:] = core_dataindex = index +1 index = index - num_cols#拼接完(480*608)还要拼接最后一列#拼接最后一边缘行    拼接完(16*608)for j in range(num_cols):# 计算当前核心区域的索引范围start_row = num_rows * core_size end_row = (num_rows) * core_size +  bufferstart_col = j * core_sizeend_col = (j + 1) * core_size# 提取当前核心区域的数据core_data = data[index,buffer+core_size:, buffer:buffer+core_size,:,:]# 将核心区域的数据放入大图的对应位置big_image[start_row:end_row, start_col:end_col,:,:] = core_dataindex = index +1 index = 1for j in range(num_rows):# 计算当前核心区域的索引范围start_col = num_cols * core_size end_col = (num_cols) * core_size +  bufferstart_row = j * core_sizeend_row = (j + 1) * core_size# 提取当前核心区域的数据core_data = data[index*num_cols-1,buffer:buffer+core_size,buffer+core_size:,:,:]# 将核心区域的数据放入大图的对应位置big_image[start_row:end_row, start_col:end_col,:,:] = core_dataindex = index +1 #拼接完(496*608)#根据实际情况调整big_image = big_image[8:8+500,8:8+500]big_image = tf.constant(big_image)return big_image
def mosicLabel(data,core_size = 32,num_rows = 15,num_cols = 18):buffer = int(core_size/2)# 创建大图的空数组big_image = np.zeros(((num_rows+1) * core_size, (num_cols+1) * core_size))# 遍历原始数据index = 0for i in range(num_rows):for j in range(num_cols):# 计算当前核心区域的索引范围start_row = i * core_size  end_row = (i + 1) * core_size start_col = j * core_sizeend_col = (j + 1) * core_size# 提取当前核心区域的数据core_data = data[index,buffer:buffer+core_size, buffer:buffer+core_size]# 将核心区域的数据放入大图的对应位置big_image[start_row:end_row, start_col:end_col] = core_dataindex = index +1 index = index - num_cols#拼接完(480*608)还要拼接最后一列#拼接最后一边缘行    拼接完(16*608)for j in range(num_cols):# 计算当前核心区域的索引范围start_row = num_rows * core_size end_row = (num_rows) * core_size +  bufferstart_col = j * core_sizeend_col = (j + 1) * core_size# 提取当前核心区域的数据core_data = data[index,buffer+core_size:, buffer:buffer+core_size]# 将核心区域的数据放入大图的对应位置big_image[start_row:end_row, start_col:end_col] = core_dataindex = index +1 #拼接完(496*608)index = 1for j in range(num_rows):# 计算当前核心区域的索引范围start_col = num_cols * core_size end_col = (num_cols) * core_size +  bufferstart_row = j * core_sizeend_row = (j + 1) * core_size# 提取当前核心区域的数据core_data = data[index*num_cols-1,buffer:buffer+core_size,buffer+core_size:]# 将核心区域的数据放入大图的对应位置big_image[start_row:end_row, start_col:end_col] = core_dataindex = index +1 #根据实际情况调整big_image = big_image[8:8+500,8:8+500]big_image = tf.constant(big_image)return big_image

设置数据包路径,拼接、显示并保存区块。

directory = 'data/yangfang/'  # 替换为你要列出文件的目录路径
files = ['2022training_patches_g2.tfrecord.gz']
# 遍历多个样方
for file in files:data = []labels = []dataset = get_dataset([directory+file])for example in dataset:data.append(example[0])labels.append(example[1])   data = tf.stack(data)labels = tf.stack(labels)print(data.shape)     # 拼接数据 big_image = mosicImage(data)big_label = mosicLabel(labels)#显示 并保存savename =  file.split('.')[0]savePath = f"yangfang/{savename}/"if not os.path.exists('img/'+savePath):os.makedirs('img/'+savePath)print(f'{savePath}文件夹已创建!')show_image(big_image.numpy(),[8,4,3],savePath+f"{savename}")show_label(big_label.numpy(),savePath+f"{savename}-label")

image-20240522105539515

文件夹内保存的文件:

image-20240523124743711

其他

数据增广

数据增广是一种有用的技术,可以增加训练数据的数量和多样性。首先将原始瓷砖图像顺时针随机旋转 90°、180° 或 270° ;然后,将旋转的图像乘以 0.9 和 1.1 之间的随机值(波段间相同,时相间不同),以增加样本数据时间序列曲线的波动。此外,每个原始平铺图像被垂直或水平翻转,随后将翻转的图像乘以0.9和1.1之间的随机数。训练数据集增广为原来的4倍。

image-20240523131502429

trainPath = 'data/guoyang/training_patches_g%d.tfrecord.gz'
trainIndex = [14,20,19,25,13,31,24,15,18,7,30,26,21,29,16,8,28,27,12,11,17,33,4,32,9,10,22]
training_patches_size = 27
BATCH_SIZE = 8
def to_HWTCtuple(inputs):# 读取出多时相多波段影像inputsList = [inputs.get(key) for key in ALLBANDS]label = inputs.get(RESPONSE)stacked = tf.stack(inputsList, axis=0)# 从通道维展开出时间维,TIMES在前,len(BANDS)在后,不可以反#stacked = tf.reshape(stacked, [12,10,KERNEL_SIZE, KERNEL_SIZE])stacked = tf.reshape(stacked, [TIMES,len(BANDS),KERNEL_SIZE, KERNEL_SIZE])# Convert from TCHW to HWTCstacked = tf.transpose(stacked, [2,3,0,1])   return stacked, label
def generate_augment():#生成增强函数#method = 1      2      3       4       5 #对应    旋转90°、 180°、 270°、水平翻转、竖直翻转 #用法:dataset = dataset.map(generate_augment(), num_parallel_calls=5)def augment_data(time_series,label):label = tf.expand_dims(label, -1)        #(H,W)-->(H,W,1)# 旋转 90°、180°、 270°、水平翻转、数值翻转 time_series = tf.transpose(time_series, perm=[2, 0, 1, 3])   #(T ,H ,W,C)# 生成1到5之间的整数 [1,6)method = np.random.randint(1,6)if method <=3:time_series = tf.image.rot90(time_series, k=method)label = tf.image.rot90(label, k=method)elif method == 4:time_series = tf.image.flip_left_right(time_series)label = tf.image.flip_left_right(label)elif method == 5:time_series = tf.image.flip_up_down(time_series)label = tf.image.flip_up_down(label)else:raise ValueError("没有此类数据增广方法")time_series = tf.transpose(time_series, perm=[1, 2, 0, 3])   #(H ,W, T,C) # 随机选择时间序列缩放因子scale_factor = tf.random.uniform(shape=(12,), minval=0.9, maxval=1.1,seed = 0)scale_factor = tf.expand_dims(scale_factor, 0)     #(1,12)scale_factor = tf.expand_dims(scale_factor, 0)     #(1,1,12)scale_factor = tf.expand_dims(scale_factor, -1)     #(1,1,12,1)# 时间序列缩放time_series *= scale_factorlabel = tf.squeeze(label)return time_series,labelreturn augment_data
def get_augment_training_dataset():namelist = [trainPath%(i) for i in trainIndex]dataset = get_dataset(namelist)augment_dataset1 = dataset.map(generate_augment(), num_parallel_calls=5)augment_dataset2 = dataset.map(generate_augment(), num_parallel_calls=5)augment_dataset3 = dataset.map(generate_augment(), num_parallel_calls=5)   dataset = dataset.concatenate(augment_dataset1).concatenate(augment_dataset2).concatenate(augment_dataset3)dataset = dataset.shuffle(BUFFER_SIZE).batch(BATCH_SIZE,drop_remainder=True).repeat()return dataset

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

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

相关文章

Spring Security实现用户认证三:结合MySql数据库对用户进行认证

Spring Security实现用户认证三&#xff1a;结合MySql数据库对用户进行认证 1 原理2 基于内存的认证&#xff08;默认方式&#xff09;2.1 依赖2.2 WebSecurityConfig配置类添加配置 3 为下一步准备数据源3.1 依赖3.2 创建表users和authorities3.3 配置DruidDataSource数据源3.…

KDE-Ambari-Metrics-Collector问题排查解决手册

文档说明 本文档是为了解决KDE平台的Ambari-Metrics-Collector服务在运行时遇到的问题而提供的问题排查和解决方法的参考文档 说明: 当前的Ambari-Metrics-Collector服务包括了ams-collector和ams-hbase两个程序,在Ambari-Metrics-Collector安装的节点执行ps -elf|grep am…

【热门话题】一文带你读懂公司是如何知道张三在脉脉上发了“一句话”的

按理说呢&#xff0c;A公司和脉脉属于不同的平台&#xff0c;而且脉脉上大家可以匿名发言&#xff0c;所以&#xff0c;即便我坐在你边上&#xff0c;我发了一句话上去&#xff0c;你也不知道是谁发的。但通过一些技术&#xff0c;我们却可以分析出&#xff0c;公司是如何知道张…

2024 电工杯高校数学建模竞赛(A题)数学建模完整思路+完整代码全解全析

你是否在寻找数学建模比赛的突破点&#xff1f;数学建模进阶思路&#xff01; 作为经验丰富的数学建模团队&#xff0c;我们将为你带来2024电工杯数学建模竞赛&#xff08;B题&#xff09;的全面解析。这个解决方案包不仅包括完整的代码实现&#xff0c;还有详尽的建模过程和解…

AI网络爬虫:批量爬取电视猫上面的《庆余年》分集剧情

电视猫上面有《庆余年》分集剧情&#xff0c;如何批量爬取下来呢&#xff1f; 先找到每集的链接地址&#xff0c;都在这个class"epipage clear"的div标签里面的li标签下面的a标签里面&#xff1a; <a href"/drama/Yy0wHDA/episode">1</a> 这个…

玩转OpenHarmony PID:教你打造两轮平衡车

简介 此次为大家带来的是OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;系统与PID控制算法相结合并落地的平衡车项目。 PID控制算法是一种经典的&#xff0c;并被广泛应用在控制领域的算法。类似于这种&#xff1a;需要将某一个物理量保持稳定的场合&…

增强版 Kimi:AI 驱动的智能创作平台,实现一站式内容生成(图片、PPT、PDF)!

前言 基于扣子 Coze 零代码平台&#xff0c;我们从零到一轻松实现了专属 Bot 机器人的搭建。 AI 大模型&#xff08;LLM&#xff09;、智能体&#xff08;Agent&#xff09;、知识库、向量数据库、知识图谱&#xff0c;RAG&#xff0c;AGI 的不同形态愈发显现&#xff0c;如何…

Redis系统架构中各个处理模块是干什么的?no.19

Redis 系统架构 通过前面的学习&#xff0c;相信你已经掌握了 Redis 的原理、数据类型及访问协议等内容。本课时&#xff0c;我将进一步分析 Redis 的系统架构&#xff0c;重点讲解 Redis 系统架构的事件处理机制、数据管理、功能扩展、系统扩展等内容。 事件处理机制 Redis…

分布式限流总结

1、计数器 java内部可以使用原子计数器AtomicInteger\Semaphore信号量来做简单的限流 // 限流的个数private int maxCount 10;// 指定的时间内private long interval 60;// 原子类计数器private AtomicInteger atomicInteger new AtomicInteger(0);// 起始时间private lon…

【笔记】树(Tree)

一、树的基本概念 1、树的简介 之前我们都是在谈论一对一的线性数据结构&#xff0c;可现实中也有很多一对多的情况需要处理&#xff0c;所以我们就需要一种能实现一对多的数据结构--“树”。 2、树的定义 树&#xff08;Tree&#xff09;是一种非线性的数据结构&#xff0…

百度智能云参与信通院多项边缘计算标准编制,「大模型时代下云边端协同 AI 发展研讨会」成功召开

1 中国信通院联合业界制定、发布多项标准化成果&#xff0c;推动产业发展 大模型开启了 AI 原生时代&#xff0c;云边端协同 AI 构建了「集中式大规模训练」、「边缘分布式协同推理」新范式&#xff0c;有效降低推理时延和成本&#xff0c;提升数据安全和隐私性&#xff0c;也…

基于Vue3 + js-tool-big-box工具库实现3个随机数字的小游戏动画,快来挑战你的非凡手气!

不知你是否和我一样&#xff0c;我曾有一个猜3个随机数字的梦&#xff0c;但通过多次的努力&#xff0c;梦想最终未能实现&#xff0c;而且还波多了我的饭票。所以&#xff0c;我要通过vue3 js-tool-big-box 这个工具库&#xff0c;来实现一个猜3个随机数字的小游戏动画&#…

学习通高分免费刷课实操教程

文章目录 概要整体架构流程详细步骤云上全平台登录步骤小结 概要 我之前提到过一个通过浏览器的三个脚本就可以免费高分刷课的文章&#xff0c;由于不方便拍视频进行实操演示&#xff0c;然后写下了这个实操教程&#xff0c;之前的三个脚本划到文章末尾 整体架构流程 整体大…

一键批量提取TXT文档前N行,高效处理海量文本数据,省时省力新方案!

大量的文本信息充斥着我们的工作与生活。无论是研究资料、项目文档还是市场报告&#xff0c;TXT文本文档都是我们获取和整理信息的重要来源。然而&#xff0c;面对成百上千个TXT文档&#xff0c;如何快速提取所需的关键信息&#xff0c;提高工作效率&#xff0c;成为了许多人头…

我的第一个JAVA程序IDEA版

目录 第一步 新建一个空项目第二步 新建模块第三步 新建包第四步 新建类第五步 新建main方法 第一步 新建一个空项目 第二步 新建模块 第三步 新建包 第四步 新建类 然后在包文件夹下新建类 第五步 新建main方法

Java开发之JDBC

JDBC 介绍JDBC程序&#xff08;Statement&#xff09;相关细节URLResultSet 连接池程序&#xff08;PreparedStatement&#xff09; 本文主要记录一下学习JDBC的一些知识点 介绍JDBC 首先谈谈什么是JDBC。下面放几张图&#xff0c;大致就可以清楚JDBC了。程序&#xff08;Sta…

RPC原理技术

RPC原理技术 背景介绍起源组件实现工作原理 背景 本文内容大多基于网上其他参考文章及资料整理后所得&#xff0c;并非原创&#xff0c;目的是为了需要时方便查看。 介绍 RPC&#xff0c;Remote Procedure Call&#xff0c;远程过程调用&#xff0c;允许像调用本地方法一样调…

bytebuddy入门

简介 Byte Buddy 是一个代码生成和操作库&#xff0c;用于在 Java 应用程序运行时创建和修改 Java 类&#xff0c;而无需编译器的帮助。除了 Java 类库附带的代码生成实用程序外&#xff0c;Byte Buddy 还允许创建任意类&#xff0c;并且不限于实现用于创建运行时代理的接口 核…

【信息安全】

信息安全 1.防火墙技术 防火墙是建立在内外网络边界上的过滤封锁机制。 补充内容 防火墙工作层次越低&#xff0c;工作效率越高&#xff0c;安全性越低DMZ的作用是保存一些公共服务器&#xff08;Web服务器、Eamil服务器&#xff09;防火墙的安全性从高到底&#xff1a;内网…

kafka Kerberos集群环境部署验证

背景 公司需要对kafka环境进行安全验证,目前考虑到的方案有Kerberos和SSL和SASL_SSL,最终考虑到安全和功能的丰富度,我们最终选择了SASL_SSL方案。处于知识积累的角度,记录一下kafka keberos安装部署的步骤。 机器规划 目前测试环境公搭建了三台kafka主机服务,现在将详细…