Qt WebEngine(02):Qt WebEngine 特性【官翻】
文章目录
- 一、前言
- 二、音频和视频编解码器
- 三、Chromium DevTools
- 四、客户证书
- 五、定制方案
- 六、拖放
- 七、全屏
- 八、HTML5 DRM
- 九、HTML5地理定位
- 十、HTTP/2 Protocol
- 十一、本地对话框
- 十二、Pepper插件API
- 12.1 Pepper Flash Player插件支持
- 十三、查看PDF文件
- 十四、页面生命周期API
- 14.1 生命周期状态概述
- 14.2 lifecycleState和recommendationState属性
- 14.3 DOM扩展
- 十五、打印成PDF
- 十六、进程模型
- 十七、拼写检查器
- 十八、触摸
- 十九、查看源代码
- 二十、WebRTC
- 二十一、网页通知
- 二十二、 总结
一、前言
原文链接
Qt WebEngine支持以下功能:
- 音频和视频编解码器
- Chromium DevTools
- Client Certificates 客户证书
- Custom Schemes 定制方案
- Drag and Drop 拖放
- Fullscreen 全屏
- HTML5 DRM
- HTML5 Geolocation HTML5地理定位
- HTTP/2 Protocol
- Native Dialogs 本地对话框
- Pepper Plugin API
- PDF File Viewing 查看PDF文件
- Page Lifecycle API 页面生命周期API
- Print to PDF 打印成PDF
- Process Models 进程模型
- Spellchecker 拼写检查器
- Touch 触摸
- View Source 查看源代码
- WebRTC 实时通信
- Web Notifications 网页通知
二、音频和视频编解码器
仅当启用了必需的专有音频和视频编解码器(例如H.264和MPEG layer-3(MP3))时,Qt WebEngine才支持MPEG-4 Part 14(MP4)文件格式。 可以在配置Qt时通过将以下选项传递给配置工具来启用专有编解码器:
-webengine-proprietary-codecs
例如,在配置Qt以在顶层构建它时,可以传递以下选项:
configure -webengine-proprietary-codecs
有关更多信息,请参见Qt配置选项。
当使用qmake仅构建Qt WebEngine模块时,可以使用以下命令(在本示例中,Qt WebEngine源代码位于C:\qt\qtwebengine中):
qmake C:\qt\qtwebengine -- -webengine-proprietary-codecs
警告:分发专有编解码器库时,必须为其获取许可证。
FFmpeg是一种跨平台的解决方案,用于记录,转换和流式传输音频和视频。 可以将其配置为与多个编解码器一起使用,这会在分发编解码器库时引发许可问题。 对于某些编解码器,可以使用开源实现,例如OpenH264。
三、Chromium DevTools
Chromium DevTools可以检查和调试任何Web内容的布局和性能问题。
可以通过使用命令行选项–remote-debugging-port = [your-port]启动Qt Web Engine应用程序或通过设置环境变量QTWEBENGINE_REMOTE_DEBUGGING来测试该功能,然后使用基于Chromium的浏览器(例如Simple Browser或 Nano浏览器)以连接到http:// localhost:[您的端口]。
Chromium DevTools页面也可以在应用程序中显示。 要进行设置,您可以调用QWebEnginePage :: setInspectedPage()到要检查的页面,这会将DevTools隐式加载到此页面中,也可以调用QWebEnginePage :: setDevToolsPage()来检查该页面。
各自的QML属性是WebEngineView.devToolsView和WebEngineView.inspectedView。
有关更多信息,请参见Qt WebEngine调试和分析。
四、客户证书
某些Web服务器,尤其是许多Intranet站点,要求客户端使用称为客户端证书的证书对自身进行身份验证。 Qt WebEngine将读取在macOS和Windows中的系统设置中安装的客户端证书,以及在Linux上安装在NSS数据库中的客户端证书。 可以使用pk12util工具将证书安装到NSS数据库中。
默认情况下,Qt WebEngine不会向服务器提供任何客户端证书,因为这样做会唯一标识用户,并且可能违反隐私期望。
要激活对客户端证书的支持,应用程序需要侦听QWebEnginePage :: selectClientCertificate或WebEngineView.selectClientCertificate信号并选择提供的证书之一。 对于可以导航到不受信任网站的应用程序,建议始终向用户提供选择,然后再将其唯一标识给远程服务器。
五、定制方案
Qt WebEngine使应用程序可以使用专门的安全策略和传输机制定义自己的自定义URL方案。
可以使用自定义方案来实现具有所有常规Web安全策略的替代网络协议,用于显示用户界面组件或调试信息的特权内部方案,具有额外限制的沙盒方案等等。
有关更多信息,请参见QWebEngineUrlScheme和QWebEngineUrlSchemeHandler。
六、拖放
Qt WebEngine支持HTML5拖放。
通过在简单浏览器或Nano浏览器中打开HTML5拖放演示,例如HTML5演示-拖放,HTML5演示-简单拖放,或HTML5演示-拖放,自动上传,可以测试此功能。
将文件拖到浏览器中实际上不是HTML5的一部分,但它受支持。 可以通过打开HTML5演示-文件API进行测试。
Qt 5.7.0中添加了对此功能的支持。
七、全屏
Qt WebEngine支持以全屏模式查看Web内容。 有关更多信息,请参见WebEngineSettings.fullscreenSupportEnabled,WebEngineView.fullScreenRequested,QWebEngineSettings :: FullScreenSupportEnabled和QWebEnginePage :: fullScreenRequested。
可以通过在视频播放器或Nano浏览器中播放YouTube视频,然后单击全屏图标进入全屏模式来测试此功能。
Qt 5.6.0中添加了对此功能的支持。
八、HTML5 DRM
如果已安装Widevine DRM插件,则Qt WebEngine支持查看受DRM保护的视频。
DRM服务最常使用的视频格式H.264需要专有的音频和视频编解码器。 有关启用编解码器的更多信息,请参见音频和视频编解码器。
可以通过在castLabs,Swank Motion Pictures,Inc.或Shaka Player的Simple Browser或Nano Browser中播放视频来测试此功能。
Qt 5.7.0中添加了对此功能的支持。
数字版权管理(Digital Rights Management,即DRM)
九、HTML5地理定位
Qt WebEngine支持以Qt Location为后端的JavaScript Geolocation API。 应用程序必须使用QWebEnginePage :: Geolocation或WebEngineView.Feature明确允许该功能。
如果Qt位置是在Qt WebEngine之前构建的,则可以通过使用地图并允许其查找用户的当前位置来测试此功能。 请注意,在Windows上,必须将外部GPS接收器连接到应用程序。 有关更多信息,请参见Qt定位。
Qt 5.5.0中添加了对此功能的支持。
十、HTTP/2 Protocol
Qt WebEngine支持HTTP / 2协议的Chromium实现。
可以通过在Simple Browser或Nano Browser中打开HTTP/2演示(例如Akamai HTTP/2演示)来测试此功能。
十一、本地对话框
网页可能会为以下功能请求对话框:
- 为HTTP和代理身份验证输入用户凭证
- 显示JavaScript警告、确认对话框和提示
- 挑选颜色
- 选择文件
- 显示表单验证消息
Qt WebEngine为这些功能提供了标准对话框。在基于widget的应用程序中,标准对话框基于QDialog,而在Qt Quick应用程序中,它们可以基于Qt Quick Controls 1或Qt Quick Controls 2(从Qt 5.8开始)。后者仅在eglfs平台上使用。
要显式地强制基于QtQuickControls1或QtQuickControls2的对话框,请将QTWEBENGINE_DIALOG_SET环境变量设置为QtQuickControls1或QtQuickControls2。
Qt WebEngine Widgets对话框可以通过重新实现QWebEnginePage::chooseFiles(), QWebEnginePage::javaScriptAlert(), QWebEnginePage::javaScriptConfirm(),和QWebEnginePage::javaScriptPrompt()函数来定制。
自Qt 5.8以来,通过连接到WebEngineView::authenticationDialogRequested(), WebEngineView::javaScriptDialogRequested(), WebEngineView::colorDialogRequested(), WebEngineView::fileDialogRequested(),和WebEngineView::formValidationMessageRequested()信号,可以定制Qt的快速对话框。例如,请参阅WebEngine Qt快速自定义对话框示例。
十二、Pepper插件API
如果设置了WebEngineSettings :: pluginsEnabled或QWebEngineSettings :: PluginsEnabled,则Qt WebEngine支持加载Pepper插件API(PPAPI)插件。
除Adobe Flash Player插件外,必须使用Chromium命令行语法以及–register-pepper-plugins参数手动加载这些插件。 参数值是一个条目列表,以逗号分隔,包含文件路径和一个或多个MIME类型,以分号分隔:
<file-path-plugin1>;<mime-type-plugin1>,<file-path-plugin2>;<mime-type1-plugin2>;<mime-type2-plugin2>
例如:
--register-pepper-plugins="libppapi_example.so;application/x-ppapi-example"
MIME类型很重要,因为它可以确定插件用于哪个嵌入。
Qt 5.6.0中添加了对此功能的支持。
12.1 Pepper Flash Player插件支持
如果安装在以下位置之一(取决于平台),则可以自动加载Pepper Flash Player插件:
- Windows
C:\Windows\SysWOW64\Macromed\Flash\pepflashplayer*.dll
C:\Windows\System32\Macromed\Flash\pepflashplayer*.dll - OS X
/Library/Internet Plug-Ins/PepperFlashPlayer/PepperFlashPlayer.plugin - Linux
/usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so
/usr/lib/adobe-flashplugin/libpepflashplayer.so
/usr/lib/PepperFlash/libpepflashplayer.so
/usr/lib64/chromium/PepperFlash/libpepflashplayer.so
您还可以使用命令行参数从特定位置加载Pepper Flash播放器:
--ppapi-flash-path=./libpepflashplayer.so
默认情况下,Flash版本设置为11.2.999.999。 您可以使用ppapi-flash-version =参数以major.minor.build.revision格式设置另一个Flash版本:
--ppapi-flash-version=16.0.0.235
如果已安装Adobe Flash PPAPI插件并在浏览器中启用了插件,则可以在简单浏览器或Nano浏览器中测试此功能。 要测试该功能,可以在浏览器中打开https://helpx.adobe.com/flash-player.html页面。
十三、查看PDF文件
Qt WebEngine支持通过导航到PDF文档来查看它们。 此功能使用Chromium扩展API和PDF查看器插件来显示PDF文档。 可以在简单浏览器或Nano浏览器中对其进行测试。
要使用此功能,需要使用QWebEngineSettings :: PluginsEnabled或WebEngineSettings :: pluginsEnabled启用加载插件。
可以通过QWebEngineSettings :: PdfViewerEnabled或WebEngineSettings :: pdfViewerEnabled设置打开(默认)此功能。
Qt 5.13.0中添加了对此功能的支持。
十四、页面生命周期API
Qt WebEngine支持Page Lifecycle API规范,这是HTML标准的正在进行中的扩展,用于允许用户代理通过冻结或丢弃后台页面来减少其资源消耗。 该功能在Widgets和QML API中均已公开。
有关正在使用的QML API的示例,请参见WebEngine生命周期示例。
Qt 5.14.0中添加了对此功能的支持。
14.1 生命周期状态概述
每个WebEngineView项(或QWebEnginePage对象)可以处于以下三种生命周期状态之一:活动,冻结或废弃。这些状态(如CPU的睡眠状态)控制着Web视图的资源使用情况。
活动状态是Web视图的正常,不受限制的状态。所有可见的Web视图始终处于活动状态,所有尚未完成加载的Web视图也始终处于活动状态。只有不可见的空闲Web视图可以转换为其他生命周期状态。
冻结状态是低CPU使用状态。在这种状态下,大多数HTML任务源都被挂起(冻结),因此,大多数DOM事件处理和JavaScript执行也将被挂起。 Web视图必须不可见以便冻结,因为在此状态下无法进行渲染。
丢弃状态是一种极端的资源节省状态。在这种状态下,Web视图的浏览上下文将被丢弃,并且相应的渲染器子进程将关闭。在这种状态下,CPU和内存使用量实际上减少为零。退出此状态后,网页将自动重新加载。进入和退出废弃状态的过程类似于序列化Web视图的浏览历史记录并销毁该视图,然后创建一个新视图并恢复其历史记录。
另请参见WebEngineView :: LifecycleState。 Widgets API中的等效项是QWebEnginePage :: LifecycleState。
14.2 lifecycleState和recommendationState属性
WebEngineView类型的lifecycleState属性是一个读写属性,用于控制Web视图的当前生命周期状态。此属性旨在对可以转换到哪些状态的限制尽可能少。例如,允许冻结当前正在后台播放音乐的Web视图,从而停止播放音乐。为了实现一种不太激进的资源节省策略,以避免中断用户可见的后台活动,必须使用RecommendationState属性。
WebEngineView类型的RecommendationState属性是一个只读属性,考虑到Web视图的当前活动,该属性计算lifecycleState属性的安全限制。因此,在网络视图在后台播放音乐的示例中,建议状态为“活动”,因为更具攻击性的状态将停止音乐。如果应用程序要避免中断后台活动,则应避免将Web视图置于比RecommendationState所提供的状态更积极地节省资源的生命周期状态。
另请参见WebEngineView :: lifecycleState和WebEngineView :: recommendedState。 Widgets API中的等效项是QWebEnginePage :: lifecycleState和QWebEnginePage :: recommendedState。
14.3 DOM扩展
lifecycleState属性连接到Page Lifecycle API规范,该规范指定两个新的DOM事件(冻结和恢复),并添加一个新的Document.wasDiscarded布尔属性。 从活动状态转换为冻结状态时,将触发冻结和恢复事件,反之亦然。 从Discarded状态转换为Active状态时,Document.wasDiscarded属性设置为true。
十五、打印成PDF
Qt WebEngine支持将网页打印为PDF文件。 有关更多信息,请参见QWebEnginePage::printToPdf()和WebEngineView.printToPdf。
可以使用Html2Pdf测试此功能。
Qt 5.7.0中添加了对此功能的支持。
十六、进程模型
Qt WebEngine使用多个OS进程将网站彼此隔离以及与客户端应用程序隔离,从而提高了安全性和鲁棒性。 支持以下过程模型或在OS进程之间划分网站的方式:
Process per Site Instance
这是默认模型。来自不同站点的页面被置于不同的过程中,并且也隔离了对同一站点的单独访问。如果两个网页来自相同的注册域名(例如wikipedia.org)和方案(例如https),则认为它们属于同一站点。这类似于同源策略,但是子域将被忽略。例如,https://en.wikipedia.org/和https://de.wikipedia.org/都属于同一个站点。
网站实例是属于同一网站的网页的集合。当应用程序将URL明确地加载到Qt WebEngine中时(例如,通过QWebEnginePage :: setUrl),将为该页面创建一个新的站点实例。但是,当用户单击页面上的相同站点链接时,现有站点实例仅扩展了更多页面。
例如,在“简单浏览器”示例中,当用户打开两个选项卡并在URL栏中明确输入https://en.wikipedia.org/时,两个选项卡将具有各自独立的OS进程(因为明确输入URL会创建一个新的网站实例)。但是,当用户在中间单击某些相同站点的链接以打开更多选项卡时,这些新的选项卡将共享相同的OS进程(因为用户交互扩展了现有站点实例)。
Process per Site
来自不同站点的页面被置于单独的过程中。 与“按站点实例处理”不同,对同一站点的所有访问将共享一个OS进程。该模型的好处是减少了内存消耗,因为更多的网页将共享进程。 缺点包括降低的安全性,健壮性和响应性。
要启用此模型,请使用命令行参数–process-per-site。 请参阅使用命令行参数。
Single Process
仅出于调试目的,可以使用命令行参数–single-process启用单个进程模式。 请参阅使用命令行参数和Qt WebEngine调试和分析。
十七、拼写检查器
Qt WebEngine支持将拼写检查支持集成到HTML表单中,以使用户能够提交拼写检查的消息。 当用户单击带下划线的拼写错误的单词时,默认的上下文菜单最多显示四个建议。 选择一个将替换拼写错误的单词。
为了能够检查拼写,拼写检查器需要词典。 它支持来自Hunspell项目的词典,但是必须将其编译为特殊的二进制格式。 Hunspell词典包含两个文件:
- .dic文件,是包含该语言单词的字典
- .aff文件,它定义字典中特殊标志的含义
可以使用Qt附带的qwebengine_convert_dict工具将这两个文件转换为bdic格式。 当Qt WebEngine拼写检查器初始化时,它将尝试加载bdict词典并检查它们的一致性。
如果设置了QTWEBENGINE_DICTIONARIES_PATH,则拼写检查器将使用指定目录中的字典,而无需查找其他字典。 否则,它将使用相对于可执行文件的qtwebengine_dictionaries目录(如果存在)。 如果不存在,它将在QT_INSTALL_PREFIX / qtwebengine_dictionaries中查找。
在macOS上,取决于在构建时如何配置Qt WebEngine,有两种可能性可以找到拼写检查数据:
- Hunspell词典(默认)-使用.bdic词典,就像在其他平台上一样
- 本机词典-使用macOS拼写检查API(这意味着结果将取决于安装的OS词典)
因此,在macOS Hunspell情况下,Qt WebEngine将在位于应用程序包Resources目录内的qtwebengine_dictionaries子目录中,以及在位于Qt框架包内的Resources目录中查找。
总而言之,在使用Hunspell的情况下,应考虑以下路径:
- QTWEBENGINE_DICTIONARIES_PATH(如果已设置)
- QCoreApplication :: applicationDirPath()/qtwebengine_dictionaries或QCoreApplication :: applicationDirPath()/…/Contents / Resources / qtwebengine_dictionaries(在macOS上)
- [QLibraryInfo :: DataPath] /qtwebengine_dictionaries或path/to/QtWebEngineCore.framework /Resources / qtwebengine_dictionaries(macOS上的Qt框架包)
默认情况下,拼写检查是禁用的,并且可以使用基于窗口小部件的应用程序中的QWebEngineProfile :: setSpellCheckEnabled()方法和Qt Quick应用程序中的WebEngineProfile.spellCheckEnabled属性针对每个配置文件启用拼写检查。
用于拼写检查的当前语言是针对每个配置文件定义的,可以使用QWebEngineProfile :: setSpellCheckLanguages()方法或WebEngineProfile.spellCheckLanguages属性进行设置。
可以通过构建并运行拼写检查器示例来测试此功能。Qt 5.8.0中添加了对此功能的支持。
十八、触摸
Qt WebEngine支持用于浏览网页并与之交互的触摸设备。
应用程序可以通过以下方式禁止使用触摸事件:
- 在命令行中传递–touch-events = disabled标志将禁用JavaScript API中的触摸事件支持(这意味着ontouchstart和相关处理程序将不会出现在document.window对象中)。 触摸事件仍将传递到网页。
- 使用WebEngine视图焦点代理对象上的QObject :: installEventFilter安装事件过滤器对象,并过滤掉所有触摸事件。
十九、查看源代码
Qt WebEngine支持查看网页的HTML源。
可从自定义菜单使用此功能或将其分配给自定义事件。 有关更多信息,请参见WebEngineView :: WebAction和QWebEnginePage :: WebAction。
可以通过在Simple Browser或Nano Browser中打开网页,然后在上下文菜单中选择Page Source来测试此功能。 页面源上下文菜单项在新选项卡中打开源视图。
为了在当前选项卡中打开源视图,还支持带有视图源URI方案的URL。 例如,您可以在URL栏中键入以下URL以查看qt.io网页的HTML源:
view-source:https://www.qt.io/
使用视图源URI方案自动完成不完整的URL,使使用此功能更加舒适。 例如,以下不完整的URL也会加载qt.io网页的源视图:
view-source:qt.io
Qt 5.8.0中添加了对此功能的支持。
二十、WebRTC
WebRTC通过简单的API为浏览器提供实时通信(RTC)功能。 有关更多信息,请参见WebEngineView.Feature和QWebEnginePage :: Feature。
可以通过设置网络摄像头或麦克风,然后在Simple Browser或Nano Browser中打开https://test.webrtc.org/来测试此功能。
二十一、网页通知
Qt WebEngine支持JavaScript Web Notifications API。 应用程序必须通过使用QWebEnginePage :: Notifications或WebEngineView.Notifications明确允许该功能。
Qt 5.13.0中添加了对此功能的支持。
二十二、 总结
本文概述了QWebEngine的功能和特性,作为web嵌入的指导性质的文章。
Qt WebEngine(02):Qt WebEngine 特性【官翻】相关推荐
- Qt WebEngine(01):Qt WebEngine 概述【官翻】
文章目录 一.前言 二.Qt WebEngine架构 2.1 Qt WebEngine 小部件模块 2.2 Qt WebEngine 模块 2.3 Qt WebEngine Core 模块 2.4 Q ...
- 样式表(05):【纲】Qt Style Sheets Reference [官翻]
文章目录 定制样式的小部件列表 属性列表 图标列表 属性类型列表 伪状态列表 子控件列表 Qt Style Sheets Reference Qt样式表支持各种属性.伪状态和子控件,使得定制小部件的外 ...
- 基本Widgets(02):【类】QWidget [官翻]
文章目录 详细说明 顶层和子级小部件 组合小部件 自定义小部件和绘画 大小提示和大小策略 事件 函数和属性组 小部件样式表 透明度和双缓冲 创建半透明窗口 本地小部件与外来部件 公共类型 enum R ...
- 图形视图(02):【类】QGraphicsScene [官翻]
文章目录 详述 事件处理和传播 公共类型 enum ItemIndexMethod enum SceneLayer 属性 backgroundBrush: QBrush bspTreeDepth: i ...
- 为什么要用Qt开发(Qt跨平台应用开发)
一.为什么选择qt 1.跨平台,一次写代码多个平台编译.使跨平台应用达到各个平台原生应用的体验与流畅度.相比与java或c#在开发图形计算方面的软件时有非常好的使用体验与流畅度. 2.使用C++编程虽 ...
- 01-为什么要用Qt开发(Qt跨平台应用开发)
一.为什么选择qt 跨平台,一次写代码多个平台编译.使跨平台应用达到各个平台原生应用的体验与流畅度.相比与java或c#在开发图形计算方面的软件时有非常好的使用体验与流畅度. 使用C++编程虽然没有j ...
- QT简介及QT环境搭建
QT简介及QT环境搭建 文章目录 QT简介及QT环境搭建 一.QT简介 1. 什么是QT? 2. QT的发展史 3. QT支持的平台 4. QT的优点 5. QT开发工具 二.QT环境搭建(CentO ...
- Qt 学习(三) —— Qt 模块
1. Qt 模块简介 Qt由许多模块组成,分别支持不同领域的功能,主要分为 Essentials 和 Add-On. Qt Essential 是基本模块,它们可以在所有受支持的开发平台和经过测试的目 ...
- 二选一的时候到了,Qt Widgets 还是 Qt Quick ? 致Qt开发伙伴
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.Qt QWidgets 和 Qt Quick 各自有什么特性.特点? 1.Qt QWidgets 2.Qt Qui ...
最新文章
- easyui展示年月
- RDKit | 基于SMILES查找化合物的MACCS密钥
- webservice发送xml报文_海关总署公告2020年第120号(关于发布进出境公路运输工具货运舱单电子传输报文格式V1.1的公告)...
- lucene.net 某些类的介绍
- 一个抓取电脑屏幕的小控件台程序
- 743. 网络延迟时间
- CSS进阶(十)position:relative
- java连接mysql实现增删改查_JDBC之Java连接mysql实现增删改查
- POJ1067 取石子游戏 跪跪跪,很好的博弈论
- 程序员疯狂记事:如何利用众多技术栈构建一个 Web 应用程序?!
- 用mobiscroll.js的treelist实现弹出下拉效果
- linux内核教学的全套视频,中科大Linux内核分析视频教程下载,共计23集
- 丁昊 北大计算机,北大清华17人!2018自主招生等类型入选名单公示,苏州333人!...
- White Sheet(面积法)
- c++ mfc加载图片jpg,png,GIF格式
- 计算机专业学生进行职业决策,计算机专业学生职业生涯规划书.doc
- 疫情下的情人节 餐饮业再亏700亿!
- Java——Map集合
- 求解n阶方阵的行列式
- 遮罩层——通过阴影弱化背景的四种方案
热门文章
- 产能节拍php,优化加工节拍实现高效加工
- 如何用excel制作图表?
- RobotFramework-SeleniumLibrary库缺少open brower、input等关键字
- 如何放大图片而不影响清晰度?图片无损放大这样做
- java计算机毕业设计社区流浪猫狗救助网站源码+系统+数据库+lw文档+mybatis+运行部署
- 华为HG522无线路由猫破解开启路由功能
- Git 客户端 - 可视化工具 Fork 使用
- [642]CherryTree for Windows中文版 v0.38.8
- C# IO流读写文件操作
- AI 人工智能药物设计