PHP SM4 加密
PHP SM4 加密
sm4基类
class Sm4
{private $ck = [0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279];private $Sbox = [0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48];private $fk = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC];private $rk = [];private $b = '';private $len = 16;/*** Sm4 constructor.* @param string $key 秘钥长度16位* @param string $b 不是16的倍数 需要的补码* @throws \Exception*/public function __construct($key, $b = ' '){$this->ck16($key);$this->crk($key);}private function dd(&$data){$n = strlen($data) % $this->len;$data = $data . str_repeat($this->b, $n);}private function ck16($str){if (strlen($str) !== $this->len) {throw new \Exception('秘钥长度为16位');}}private function add($v){$arr = unpack('N*', $v);$max = 0xffffffff;$j = 1;for ($i = 4; $i > 0; $i--) {if ($arr[$i] > $max - $j) {$j = 1;$arr[$i] = 0;} else {$arr[$i] += $j;break;}}return pack('N*', ...$arr);}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function deDataCtr($str, $iv){return $this->enDataCtr($str, $iv);}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function enDataCtr($str, $iv){$this->ck16($iv);$r = '';$this->dd($str);$l = strlen($str) / $this->len;for ($i = 0; $i < $l; $i++) {$s = substr($str, $i * $this->len, $this->len);$tr = [];$this->encode(array_values(unpack('N*', $iv)), $tr);$s1 = pack('N*', ...$tr);$s1 = $s1 ^ $s;$iv = $this->add($iv);$r .= $s1;}return $r;}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function enDataOfb($str, $iv){$this->ck16($iv);$r = '';$this->dd($str);$l = strlen($str) / $this->len;for ($i = 0; $i < $l; $i++) {$s = substr($str, $i * $this->len, $this->len);$tr = [];$this->encode(array_values(unpack('N*', $iv)), $tr);$iv = pack('N*', ...$tr);$s1 = $s ^ $iv;$r .= $s1;}return $r;}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function deDataOfb($str, $iv){return $this->enDataOfb($str, $iv);}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function deDataCfb($str, $iv){$this->ck16($iv);$r = '';$this->dd($str);$l = strlen($str) / $this->len;for ($i = 0; $i < $l; $i++) {$s = substr($str, $i * $this->len, $this->len);$tr = [];$this->encode(array_values(unpack('N*', $iv)), $tr);$s1 = pack('N*', ...$tr);$s1 = $s ^ $s1;$iv = $s;$r .= $s1;}return $r;}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function enDataCfb($str, $iv){$this->ck16($iv);$r = '';$this->dd($str);$l = strlen($str) / $this->len;for ($i = 0; $i < $l; $i++) {$s = substr($str, $i * $this->len, $this->len);$tr = [];$this->encode(array_values(unpack('N*', $iv)), $tr);$s1 = pack('N*', ...$tr);$iv = $s ^ $s1;$r .= $iv;}return $r;}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function enDataCbc($str, $iv){$this->ck16($iv);$r = '';$this->dd($str);$l = strlen($str) / $this->len;for ($i = 0; $i < $l; $i++) {$s = substr($str, $i * $this->len, $this->len);$s = $iv ^ $s;$tr = [];$this->encode(array_values(unpack('N*', $s)), $tr);$iv = pack('N*', ...$tr);$r .= $iv;}return $r;}/*** @param string $str 加密字符串* @param string $iv 初始化字符串16位* @return string* @throws \Exception*/public function deDataCbc($str, $iv){$this->ck16($iv);$r = '';$this->dd($str);$l = strlen($str) / $this->len;for ($i = 0; $i < $l; $i++) {$s = substr($str, $i * $this->len, $this->len);$tr = [];$this->decode(array_values(unpack('N*', $s)), $tr);$s1 = pack('N*', ...$tr);$s1 = $iv ^ $s1;$iv = $s;$r .= $s1;}return $r;}/*** @param string $str 加密字符串* @return string*/public function enDataEcb($str){$r = [];$this->dd($str);$ar = unpack('N*', $str);do {$this->encode([current($ar), next($ar), next($ar), next($ar)], $r);} while (next($ar));return pack('N*', ...$r);}/*** @param string $str 解密字符串* @return string*/public function deDataEcb($str){$r = [];$this->dd($str);$ar = unpack('N*', $str);do {$this->decode([current($ar), next($ar), next($ar), next($ar)], $r);} while (next($ar));return pack('N*', ...$r);}private function encode($ar, &$r){for ($i = 0; $i < 32; $i++) {$ar[$i + 4] = $this->f($ar[$i], $ar[$i + 1], $ar[$i + 2], $ar[$i + 3], $this->rk[$i]);}$r[] = $ar[35];$r[] = $ar[34];$r[] = $ar[33];$r[] = $ar[32];}private function decode($ar, &$r){for ($i = 0; $i < 32; $i++) {$ar[$i + 4] = $this->f($ar[$i], $ar[$i + 1], $ar[$i + 2], $ar[$i + 3], $this->rk[31 - $i]);}$r[] = $ar[35];$r[] = $ar[34];$r[] = $ar[33];$r[] = $ar[32];}private function crk($key){$keys = array_values(unpack('N*', $key));$keys = [$keys[0] ^ $this->fk[0],$keys[1] ^ $this->fk[1],$keys[2] ^ $this->fk[2],$keys[3] ^ $this->fk[3]];for ($i = 0; $i < 32; $i++) {$this->rk[] = $keys[] = $keys[$i] ^ $this->t1($keys[$i + 1] ^ $keys[$i + 2] ^ $keys[$i + 3] ^ $this->ck[$i]);}}private function lm($a, $n){return ($a >> (32 - $n) | (($a << $n) & 0xffffffff));}private function f($x0, $x1, $x2, $x3, $r){return $x0 ^ $this->t($x1 ^ $x2 ^ $x3 ^ $r);}private function s($n){return $this->Sbox[($n & 0xff)] | $this->Sbox[(($n >> 8) & 0xff)] << 8 | $this->Sbox[(($n >> 16) & 0xff)] << 16 | $this->Sbox[(($n >> 24) & 0xff)] << 24;}private function t($n){$b = $this->s($n);return $b ^ $this->lm($b, 2) ^ $this->lm($b, 10) ^ $this->lm($b, 18) ^ $this->lm($b, 24);}private function t1($n){$b = $this->s($n);return $b ^ $this->lm($b, 13) ^ $this->lm($b, 23);}}
调用类
class RtSm4
{protected $sm4;protected $keyLen = 16;protected $ivLen = 16;function __construct($key){$this->sm4 = new Sm4($key);}public function encrypt($data, $type = 'sm4', $iv = '', $formatOut = 'hex'){if ($type != 'sm4-ecb') {$this->check_iv($iv);}$ret = '';switch ($type) {case 'sm4':case 'sm4-cbc':$data = $this->mystr_pad($data, $this->keyLen); //需要补齐$ret = $this->sm4->enDataCbc($data, $iv);break;case 'sm4-ecb':$data = $this->mystr_pad($data, $this->keyLen); //需要补齐$ret = $this->sm4->enDataEcb($data);break;case 'sm4-ctr':$ret = $this->sm4->enDataCtr($data, $iv);break;case 'sm4-ofb':$ret = $this->sm4->enDataOfb($data, $iv);break;case 'sm4-cfb':$ret = $this->sm4->enDataCfb($data, $iv);break;default:throw new Exception('bad type');}if ($formatOut == 'hex') {return bin2hex($ret);} else if ($formatOut == 'base64') {return base64_encode($ret);}return $ret;}public function decrypt($data, $type = 'sm4', $iv = '', $formatInput = 'hex'){if ($type != 'sm4-ecb') {$this->check_iv($iv);}if ($formatInput == 'hex') {$data = hex2bin($data);} else if ($formatInput == 'base64') {$data = base64_decode($data);}//else is rawswitch ($type) {case 'sm4':case 'sm4-cbc':$ret = $this->sm4->deDataCbc($data, $iv);$ret = $this->mystr_unpad($ret);break;case 'sm4-ecb':$ret = $this->sm4->deDataEcb($data);$ret = $this->mystr_unpad($ret);break;case 'sm4-ctr':$ret = $this->sm4->deDataCtr($data, $iv);break;case 'sm4-ofb':$ret = $this->sm4->deDataOfb($data, $iv);break;case 'sm4-cfb':$ret = $this->sm4->deDataCfb($data, $iv);break;default:throw new Exception('bad type');}return $ret;}//加密前补齐,特定后缀不适用全部的对接方protected function mystr_pad($data, $len = 16){$n = $len - strlen($data) % $len;$tmpString = $this->strToHex($data) . "80";$tmpString .= str_repeat("00", $n - 1);return $this->hexToStr($tmpString);}// 解密后去掉补齐,特定后缀不适用全部的对接方protected function mystr_unpad($data){$tmp = $this->strToHex($data);$lastIndex = strrpos($tmp, '80');if ($lastIndex !== false) {$tmp = substr($tmp, 0, $lastIndex);}return $this->hexToStr($tmp);}//加密前补齐,通用代码,无特定需求可用这个protected function mystr_pad_bak($data, $len = 16){$n = $len - strlen($data) % $len;return $data . str_repeat(chr($n), $n);}// 解密后去掉补齐 通用的代码,无特定需求可用这个protected function mystr_unpad_bak($data){$n = ord(substr($data, -1));return substr($data, 0, -$n);}protected function check_iv($iv){if (strlen($iv) != $this->ivLen) {throw new Exception('bad iv');}}protected function strToHex($string){$hex = unpack('H*', $string);return $hex[1];}protected function hexToStr($hex){$string = pack('H*', $hex);return $string;}
}
调用
$key = hex2bin('660e5d5xxxxxxx714f346e');
$iv = hex2bin('abcd0863xxxxxf67');
$sm4 = new RtSm4($key);
$string = 'xxxx';
$encodeText = $sm4->encrypt($string, 'sm4-cbc', $iv);
echo $encodeText . PHP_EOL;
echo $sm4->decrypt($encodeText, 'sm4-cbc', $iv). PHP_EOL;相关文章:
PHP SM4 加密
PHP SM4 加密 sm4基类 class Sm4 {private $ck [0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,0xc0c7ced5, 0xdce3ea…...
leetcode - 2825. Make String a Subsequence Using Cyclic Increments
Description You are given two 0-indexed strings str1 and str2. In an operation, you select a set of indices in str1, and for each index i in the set, increment str1[i] to the next character cyclically. That is ‘a’ becomes ‘b’, ‘b’ becomes ‘c’, an…...
工业—使用Flink处理Kafka中的数据_ChangeRecord1
使用 Flink 消费 Kafka 中 ChangeRecord 主题的数据,当某设备 30 秒状态连续为 “ 预警 ” ,输出预警 信息。当前预警信息输出后,最近30...
探索嵌入式硬件设计:揭秘智能设备的心脏
目录 引言 嵌入式系统简介 嵌入式硬件设计的组成部分 设计流程 微控制器选择 原理图设计 PCB布局 编程与调试 系统集成与测试 深入理解微控制器 存储器管理 输入/输出接口 通信接口 电源管理 硬件抽象层(HAL) 操作系统(OS&am…...
数据结构-最小生成树
一.最小生成树的定义 从V个顶点的图里生成的一颗树,这颗树有V个顶点是连通的,有V-1条边,并且边的权值和是最小的,而且不能有回路 二.Prim算法 Prim算法又叫加点法,算法比较适合稠密图 每次把边权最小的顶点加入到树中࿰…...
mac启动jmeter
// 设置使用java8,使用21版本会有问题 export JAVA_HOME/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home/ export PATH$JAVA_HOME/bin:$PATH cd /Users/user/software/apache-jmeter-5.1.1 //设置不使用代理 sh jmeter -Jhttp.proxyHost -J…...
spring学习笔记之静态代理和动态代理
在 Spring 开发中,静态代理和动态代理是实现面向切面编程(AOP)的两种常见方式。两者的主要区别在于代理类的生成时间和方式。 静态代理 定义 静态代理是由开发者或工具在编译期明确创建代理类的方式,代理类和目标类在程序运行前就已经存在。 特点 代理类明确存在:需要…...
qemu搭建aarch64
qemu工具搭建aarch64系统 下载准备 下载qemu: https://qemu.weilnetz.de/w64/2022/qemu-w64-setup-20220831.exe 下载固件:https://publishing-ie-linaro-org.s3.amazonaws.com/releases/components/kernel/uefi-linaro/16.02/release/qemu64/QEMU_EFI.fd?Signat…...
delphi IDE 插件DelphiIDEPlugin_SearchProject,用于从项目组中查找项目
delphi IDE 插件DelphiIDEPlugin_SearchProject,用于从项目组中查找项目 安装后在菜单Tools下第一个子菜单项查找项目 delphiIDE插件DelphiIDEPlugin-SearchProject,用于从项目组中查找项目资源-CSDN文库...
【Vue】Scoped、组件间通信、Props检验
目录 Scoped 作用 *原理 组件通信 前置知识 什么是组件通信 为什么需要组件通信 如何进行组件通信 如何辨别两个组件的关系 父子组件通信 父传子 子传父 非父子组件通信 祖先传后代 语法 任意两个组件通信 步骤 Props校验 props是什么 作用 语法 组件的…...
openbmc dbus架构简析(二)
1.说明 以前看内核代码觉得难,是因为内核代码涉及到硬件原理与算法结构和层次递进的代码逻辑,现在的应用层因为业务的复杂与代码和内核的交互接口复杂,也变得有些难度了。 这篇文章是继:openbmc dbus架构简析的第二篇文章。 首先贴出来前篇…...
【二分查找】Leetcode例题
【1】69. x 的平方根 - 力扣(LeetCode) 🍡解题思路:首先想到的是暴力查找,从1开始依次比较x与num*num的大小,然后找出满足num*num<x且(num1)*(num1)>x的num值;再来看看能不能优化一下&…...
gitlab配置调试minio
官方文档 rails console 调试 查看配置Settings.uploads.object_store加载minio clientrequire fog/awsfog_connection Fog::Storage.new(provider: AWS,aws_access_key_id: 你的MINIO_ACCESS_KEY,aws_secret_access_key: 你的MINIO_SECRET_KEY,region: <S3 region>,e…...
Vue实战技巧:如何展示附件(PDF、MP4、Excel、Zip等)并修改名称下载
大家好,今天给大家分享一篇关于在Vue项目中展示附件(PDF、MP4、Excel、Zip等)并修改名称下载的教程。在实际开发过程中,这个功能非常实用,下面我们就一起来学习一下。 一、准备工作 首先,确保你的项目中已经…...
AI证件照制作 API 对接说明
AI证件照制作 API 对接说明 本文将介绍一种 AI证件照制作 API 对接说明,它是可以通过输入人像照片URL以及自己喜欢的模板来制作各种风格的证件照。 接下来介绍下 AI证件照制作 API 的对接说明。 申请流程 要使用 API,需要先到 AI证件照制作 API?inv…...
Macos用brew安装Nodejs亲手教程
首先确保brew已安装,搜索node资源,命令如下: brew search nodejs 演示结果如下: 安装nodejs brew install node22 或 brew install node 出现如下界面 表示正在安装,安装成功后,提示如下信息࿱…...
Node.js 新手教程
1、nodejs简介 Node.js 是一个开源和跨平台的 JavaScript 运行时环境。它是几乎所有类型项目的流行工具! Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的核心)。这使得 Node.js 的性能非常出色。 Node.js 应用程序在单个进…...
Latex转word(docx)或者说PDF转word 一个相对靠谱的方式
0. 前言 投文章过程中总会有各种各样的要求,其中提供word格式的手稿往往是令我头疼的一件事。尤其在多公式的文章中,其中公式转换是一个头疼的地方,还有很多图表,格式等等,想想就让人头疼欲裂。实践中摸索出一条相对靠…...
前端热门面试题目——React、Node
img 标签的 srcset 属性的作用 srcset 属性允许开发者为不同设备或分辨率提供多个图像选项,优化加载的图片以适应设备的屏幕大小和分辨率。这提高了性能和用户体验。 示例: <img src"default.jpg" srcset"small.jpg 480w, medium.j…...
Ansible自动化一键部署单节点集群架构
自动化部署利器:Ansible 一键部署脚本 在现代IT基础设施管理中,Ansible以其简洁、强大的自动化能力脱颖而出。以下是精心打造的Ansible自动化一键部署脚本,旨在简化部署流程,提升效率,确保一致性和可靠性。 通过这个…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
