图片来源自网络,保持更新;更多内容请关注 cnblogs.com/xuyaowen
IO流 第一部分 (OutputStreamWriter BufferOutputStream) 转换流 超类为Reader和Writer 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节 InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("d://deo2. txt")); char[] b = new char[2]; int len = 0; bos.write(bytes); bos.write(bytes, 3, 2)
传统 IO:场景:将磁盘上的文件读取出来,然后通过网络协议发送给客户端。传统文件IO:产生4次用户上下文切换,4次拷贝。 DMA (Direct Memory Access,直接内存存取,即不使用 CPU 拷贝数据到内存,而是 DMA 引擎传输数据到内存,用于解放 CPU)2、第二次数据拷贝:CPU 将内核缓冲区的数据拷贝到用户缓冲区 想要优化文件传输的性能就两个方向,因为这两个是最耗时的1、减少上下文切换次数2、减少数据拷贝次数
得益于程序访问的局部性原理[2],这种节省成本的做法也能取得不俗的运行效率。从存储器的层次结构以及计算机对数据的处理方式来看,上层一般作为下层的Cache层来使用(广义上的Cache)。 所以后面的讨论基本上是讨论IO相关的系统调用和文件系统Page Cache的一些机制。 Linux内核中的IO栈 这一小节来看Linux内核的IO栈的结构。 先上一张全貌图[4]: 由图可见,从系统调用的接口再往下,Linux下的IO栈致大致有三个层次: 文件系统层,以 write 为例,内核拷贝了write参数指定的用户态数据到文件系统Cache中,并适时向下层同步 设备层,通过DMA与内存直接交互,完成数据和具体设备之间的交互 结合这个图,想想Linux系统编程里用到的Buffered IO、mmap、Direct IO,这些机制怎么和Linux IO栈联系起来呢 比如我们知道机械磁盘的连续读写性能一般不会超过120M/s,而普通的SSD磁盘随意就能超过机械盘几倍(商用SSD的连续读写速率达到2G+/s不是什么新鲜事)。
字节流,字符流基本概念 File类不支持文件内容处理,如果要处理文件内容,必须要通过流的操作模式来完成 在java.io包中,流分为两种:字节流与字符流 字节流:读写数据以字节为基本单位(处理二进制文件 /数据的时候使用) 字符流:独写数据以字符为基本单位(处理文本文档/数据的时候使用) 2. 示例:复制图片 1)初阶: package dqy0305; import java.io.FileInputStream; import java.io.FileNotFoundException ; import java.io.FileOutputStream; import java.io.IOException; public class IODemo2 { //实现文件的复制 缓冲区就是byte[] 字符流的读写操作以char为单位,缓冲区就是char[] 示例: 1)不带缓冲区 import java.io.FileReader; import java.io.FileWriter
,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对他们做相应的计算(栈顶元素和次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式结果。 计算出3+4的值,得7,再将7入栈 接下来时*运算符,因此弹出7和5,计算出7 * 5 = 35,将35入栈 最后时 - 运算符,计算出35 - 6的值,即29,由此得出最终结果 中缀表达式 (1)中缀表达式就是常见的运算表达式 ,用运算符对他们做相应的计算(次顶元素和栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果 例如:(3+4)* 5 - 6 对应的前缀表达式就是3 4 + 5 * 6 -,针对后缀表达式求值步骤如下: (1)从左往右扫描,将3和4压入堆栈; (2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈; (3)将5入栈; ( 4)接下来是*运算符,因此弹出5和7,计算出7 * 5 = 35,将35入栈; (5)将6入栈; (6)最后是 - 运算符,计算出35 - 6的值,即29,由此得出最终结果 接下来我们按照这个理论通过代码实现逆波兰计算器
如果它被设为2,那么该文件的末尾将作为参考位置。 例子: 就用我们上面创建的文件foo.txt。 #! 语法: os.remove(file_name) 例子: 下例将删除一个已经存在的文件test2.txt。 #! /usr/bin/python # -*- coding: UTF-8 -*- import os # 删除一个已经存在的文件test2.txt os.remove("test2.txt") Python
话接上回,继续java IO部分的学习。上一次说完了字节流的读写数据,这次介绍一下字符流的读写数据。 new String(bys,"GBK"); // bys用UTF-8编码,却用GBK解码,所以输出会乱码 String ss3=new String(bys2,"GBK"); // bys2 该方法返回实际读取的字符数,如果返回 -1,则表示已经到了输入流的末尾 示例 import java.io.FileInputStream; import java.io.IOException; import ; import java.io.FileWriter; import java.io.IOException; // FileReader和FileWriter类分别为InputStreamReader ; import java.io.IOException; import java.io.OutputStreamWriter; // OutputStreamWrite类:将字节输出流转换为字符输出流
由图可见,从系统调用的接口再往下,Linux下的IO栈致大致有三个层次: 文件系统层,以 write(2) 为例,内核拷贝了write(2)参数指定的用户态数据到文件系统Cache中,并适时向下层同步 设备层,通过DMA与内存直接交互,完成数据和具体设备之间的交互 结合这个图,想想Linux系统编程里用到的Buffered IO、mmap(2)、Direct IO,这些机制怎么和Linux IO栈联系起来呢 传统的Buffered IO使用read(2)读取文件的过程什么样的? 而mmap(2)做了什么?mmap(2)直接把Page Cache映射到了用户态的地址空间里了,所以mmap(2)的方式读文件是没有第二次拷贝过程的。那Direct IO做了什么? 除了传统的Buffered IO可以比较自由的用偏移+长度的方式读写文件之外,mmap(2)和Direct IO均有数据按页对齐的要求,Direct IO还限制读写必须是底层存储设备块大小的整数倍(甚至
综上,采用转换流把字节流转成字符流处理比较合理,即使用InputStreamReader 要求2的设计分析: 1)需要把字符数据按行保存到字节流文件 ; 2)字符流采用BufferedWriter比较合适 ; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter ; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader ; import java.io.OutputStreamWriter; public class TranStreamDemo2 { public static void main(String
2、重定向 2、1、文件描述符的分配规则 进程会查询自己的文件描述表,分配最小的没有被使用的fd(没有实现的难度,就相当于是遍历数组,找最小下表)。 2、2、实现重定向(dup2) 如果我们知道了上面的文件描述符的分配规则的情况下的话,如果我们关闭了fd=1的情况,并且在下面printf或者是fprintf的时候还是照样的是一个默认,另一个指向的还是 介绍系统调用接口dup2。 要知道dup2不只是两个整数之间的拷贝,而是文件下标是代表的文件内容的拷贝。 除此之外还不建议多次的调用系统调用,因为系统调用也是需要消耗时间的,所以放在语言层的缓冲区,就会积攒一些之后然后再开始刷新缓冲区,启动系统调用,这是提高IO刷新的效率。 2、宏函数在处理的时候会直接替换,这样的话能够减少变量创建,缩短一点时间。
IO的类型: 平均响应时间直接关联到具体的IO类型: 1. 读或写 2. 单块或多块 单块IO,指一次只读一个块。 多块读指的是一次读多个块,从2到128个Oracle块不等,依赖于块的大小与操作系统设置。通常一个多块请求容量上有1MB的限制。 2. 单块读至少应该和多块读一样快,甚至还要更快。 3. 2. 单块同步读时间是5毫秒。 3. 'log file parallel write'时间是3毫秒。 以上是基于多块IO比单块IO需要更多的IO子系统资源的前提。 确认IO响应时间: Oracle记录特定的等待事件与统计信息的IO操作响应时间作为”Elapsed Time“。”
栈 入栈顺序1 出栈顺序N 队列 如队列顺序1 出队列顺序1 队列的作用是用来保持公平性 Queue.h typedef int QDataType; typedef struct QueueNode
3138 栈练习2 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description (此题与栈练习1相比改了2处:1加强了数据 2不保证栈空时不会出栈) 给定一个栈(初始为空,元素类型为整数,且小于等于100),只有两个操作:入栈和出栈。 操作解释:1表示入栈,2表示出栈 输入描述 Input Description N(操作个数) N个操作(如果是入栈则后面还会有一个入栈元素) 具体见样例(输入不保证栈空时不会出栈) 输出描述 Output Description 最终栈顶元素,若最终栈空,或栈空时有出栈操作,输出”impossible!” (不含引号) 样例输入 Sample Input 3 1 2 2 2 样例输出 Sample Output impossible!
CopyFile.java b0.jpg 运行程序后文件: CopyFile.java b0.jpg Hongten.jpg CopyFile.java 代码: import java.io.FileInputStream ; import java.io.FileOutputStream; import java.io.IOException; /** * @author Hongten * * @time 2011 } 测试二: 源文件: Test.java b0.jpg 运行程序后文件: Test.java b0.jpg Hongten.jpg Test.java 代码: import java.io.FileInputStream ; import java.io.FileOutputStream; import java.io.IOException; /** * @author Hongten * * @time 2011 ; import java.io.FileOutputStream; import java.io.IOException; /** * @author Hongten * * @time 2011
getTemporaryDirectBuffer和SocketChannelImpl值得分析
2-1-2、Chat模型的少样本示例Demo1: 使用Ai&Human Message交替形成历史记录ChatPromptTemplate: 是 LangChain 库中用于生成与语言模型进行对话式交互提示的类 2-1-7、连接特征存储开源的特征存储框架: feast,详细介绍见附录2-2、Predict(LLM调用,以Chat 模型为主)2-2-1、概要1、模型设置: 这里我们依旧使用智谱AI来设置模型from 2-2、MessagePromptTemplateMessagePromptTemplate: 如何从一个或多个 MessagePromptTemplates 构建一个 ChatPromptTemplate 2-4、流式响应Stream: 一些聊天模型提供流式响应。 4、灵活性:支持多种存储后端和数据源,可以适应不同的技术栈和基础设施需求。5、开源生态:作为一个活跃的开源项目,Feast 拥有庞大的社区支持和持续的功能更新 。1-3、如何使用?
JZGKCHINA 工控技术分享平台 AB刚刚发布两款远程IO模块,一款是FLEX5000用于极端环境IO和安全IO,并替代1794FLEXIO,另外一款是可以部署在EX防爆区的1719防爆远程IO ,同时这两款远程IO模块也支持DLR环网并且速率达到1G。 5094 Filler Module 1719EX 本质安全分布式 1719 Ex I/O 解决方案可装于区域 2 或分区 2 环境,可帮助客户通过EtherNet/IP 集成危险区域(区域 0、1 Ex I/O 2 Point Digital Output 23V 1719-OB2L Ex I/O 2 Point Digital Output 16.5V 1719-IJ Ex I/O 2x8 Pole Screw Terminal 1719-TB8SX2 Ex I/O 2x8 Pole Spring Terminal 1719-TB6
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。 二、创建一个我们自己的队列 1.前置准备 1.1需要的三个文件 在开始之前,我们最好创建三个文件,一个放栈函数的实现,一个用来测试栈函数,最后一个放栈函数的引用和头文件的引用,这样到时侯想要使用栈函数直接包这一个头文件即可 typedef struct QueueInformation { Quenode* head;//存放头节点 Quenode* tail;//存放尾节点 int sz;//存放个数 }Que; 2. : #include"queue.h" void test1() { Que q1; init_queue(&q1); push_queue(&q1, 1); push_queue(&q1, 2) Quenode* cur = q1->head; while (cur) { Quenode* next = cur->next; free(cur); cur = next; } } 2.
利用栈检测括号符号的匹配 我们知道我们在编程中,如果我们的括号符不匹配的话,编译器会报错,检测原理就是通过栈的机制。 检测通过相同符号的数量以及符号是否匹配 比如我们有一个字符串"[()]" 遇到开放符号就push,遇到闭合符号就看栈顶是不是与这个闭合符号相匹配 如果一个'['在(没有闭合的话,那么这个符号就是错误的。 } int Judge(char top,char str) { if (str-top ==1) { return 0; } else if (str - top ==2) = '}') { return 1; } return 0; } 我这里检测开放符号和闭合符号是用ascall码的值,如果他们的差为1或者2说明这俩个括号匹配 这样就可以少写很多判断代码 ,当判断栈顶元素和当前闭合符号是否匹配(在栈不为空的情况下),不匹配直接返回不匹配,如果匹配则弹出栈,之后再次进入循环判断。