首页 文章 精选 留言 我的

精选列表

搜索[java],共10000篇文章
优秀的个人博客,低调大师

Java ByteArrayInputStream ByteArrayOutputStream类源码解析

ByteArrayOutputStream ByteArrayOutputStream继承了抽象类OutputStream,本质是一个存在于堆内存中的可扩展byte数组,因为所有操作都在内存中所以flush()也什么都没做。 该类实现了一个输出流,数据写入一个byte数组,缓冲区随着写入的数据自动增大。数据可以通过toByteArray()和toString()重新取回。 关闭ByteArrayOutputStream没有影响,类中的方法可以在流被关闭后调用而不抛出IOException,因为close()实际上什么也没做。 从下面的代码中可以看出,所有涉及到输出流内容读写的操作,包括write、reset、toByteArray、size和toString都加了synchronized关键字,因为grow操作只改变数组大小不改变有效内容所以不需要加synchronized,因为要避免输出内容产生错乱。 从内部变量中可以看到,底层是一个byte数组,一个统计比特数的计数器 //存储数据的缓冲区 protected byte buf[]; //缓冲区内的有效byte protected int count; 无参构造时数组大小初始设为32,也可以指定size大小,size为负数时抛出IllegalArgumentException //创建一个新的ByteArrayOutputStream,初始缓冲区大小为32 public ByteArrayOutputStream() { this(32); } //创建一个新的ByteArrayOutputStream,初始缓冲区大小为size public ByteArrayOutputStream(int size) { if (size < 0) { throw new IllegalArgumentException("Negative initial size: " + size); } buf = new byte[size]; } 输入前要检查空间大小是否足够,下面一系列函数都是用于检查大小和进行扩大,数组大小存在上限,太大时会出现OOM错误。每次进行扩展时大小变为当前容量*2和需要的最小容量参数中的较大值,除非minCapacity>MAX_ARRAY_SIZE,否则不会突破这个大小,MAX_ARRAY_SIZE //在必要时增加容量来确保足够持有minCapacity表明的最小数目的元素 private void ensureCapacity(int minCapacity) { // overflow-conscious code if (minCapacity - buf.length > 0) grow(minCapacity); } //数组的最大大小,一些虚拟机保留了数组头部的一些位置。试图分配更大的数组会导致OutOfMemoryError:请求的数组大小超过了虚拟机的限制 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = buf.length;//当前数组大小 int newCapacity = oldCapacity << 1;//新容量=当前容量*2 if (newCapacity - minCapacity < 0) newCapacity = minCapacity;//新容量为当前容量*2和minCapacity中的较大值 if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity);//当前容量*2>MAX_ARRAY_SIZE是要做处理 buf = Arrays.copyOf(buf, newCapacity);//新分配一个数组把数据复制过去 } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // 负数代表minCapacity超过正数所能表示的范围了,所以内存溢出 throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE ://minCapacity在Integer.MAX_VALUE到Integer.MAX_VALUE-8范围内,大小为Integer.MAX_VALUE MAX_ARRAY_SIZE;//小于MAX_ARRAY_SIZE时为MAX_ARRAY_SIZE } 每次的写入操作需要先确保数组大小足够,然后将内容复制到数组中 //将特定的byte写入到这个输出流中 public synchronized void write(int b) { ensureCapacity(count + 1);//确保数组还能再多存储一个 buf[count] = (byte) b;//int转为byte保存到数组中 count += 1;//计数器+1 } //将从off开始长度为len的bytes写入到输出流中 public synchronized void write(byte b[], int off, int len) { if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) - b.length > 0)) { throw new IndexOutOfBoundsException(); } ensureCapacity(count + len); System.arraycopy(b, off, buf, count, len);//复制内容到数组中 count += len; } writeTo是将当前输出流中的内容全部写入到参数中的输出流中去,相当于调用out.write(buf, 0, count) public synchronized void writeTo(OutputStream out) throws IOException { out.write(buf, 0, count); } reset将count设为0,当前累计的输出都被丢弃了,这个输出流可以被重新使用,再次利用已经分配好的缓冲区空间,因为没有可以直接更改count的方法,所以相当于旧的内容无法再被访问了 public synchronized void reset() { count = 0; } toByteArray创建一个新的byte数组,大小为当前输出流中的byte大小,将其中的byte内容复制到新的数组中 public synchronized byte toByteArray()[] { return Arrays.copyOf(buf, count); } size返回当前流中的byte大小 public synchronized int size() { return count; } toString将输出流中的内容重新解码为String,可以指定字符集也可以直接默认使用平台字符集 //将缓冲区中的内容通过平台的默认字符集转换成string解码。新的String长度是字符集的函数,所以可能不等于buffer的大小,这个方法总是用平台的默认字符集中的默认替代字符串来替代畸形输入和非图形化表示字符序列 public synchronized String toString() { return new String(buf, 0, count); } //跟上面方法相比指定了字符集 public synchronized String toString(String charsetName) throws UnsupportedEncodingException { return new String(buf, 0, count, charsetName); } close可以看到什么都没做,所以一切照常,原因是该类操作都在堆内存中,不需要关闭一些句柄、套接字之类的东西所以什么都不用做 public void close() throws IOException { } ByteArrayInputStream ByteArrayInputStream是和ByteArrayOutputStream对应的输入流,继承了抽象类InputStream,本质上也是一个存储在堆内存中的byte数组,这个数组必须在构造时传入并直接被使用而不是复制,之后大小无法改变,可以通过直接对数组中的内容进行修改改变流中的内容。可以标记一个位置,通过reset重置回去来进行重复读取。 public static void main(String args[]) throws IOException{ ByteArrayOutputStream out = new ByteArrayOutputStream(); out.write("1234567890".getBytes()); byte buf[] = out.toByteArray(); ByteArrayInputStream in = new ByteArrayInputStream(buf); byte res[] = new byte[10]; in.read(res); System.out.println(new String(res));//1234567890 buf[0] = '4'; in.reset(); in.read(res); System.out.println(new String(res));//4234567890 } ByteArrayInputStream含有一个内部缓冲区包含了可能从流中读取的比特,一个内部计数器用来保持对下一个read方法读取的byte的跟踪。 关闭ByteArrayInputStream没有作用,所有方法都可以继续使用不会出现IOException,因为全部操作都在堆内存中不存在要关闭的句柄等。 从内部变量中可以看出,底层通过buf[]来存储流中的内容 /** * 构造时提供一个数组,buf中的比特是唯一能够从流中读取的,buf[pos]是下一个要被读取的byte */ protected byte buf[]; /** * 下一个要被读取的byte的下标,总是非负数,不能超过count,buf[pos]是下一个要被读取的byte */ protected int pos; /** * 流中当前标记的位置,ByteArrayInputStream在构造时默认标记位置是0。可以通过mark()方法标记缓冲区中的其他位置,能够通过reset()回到当前标记的位置 * 如果没有设置过mark,他的值会是传递给构造器的值,如果没有的话是0 */ protected int mark = 0; /** * 比当前有效字符的index大1,总是非负数,不超过buf数组的长度。比buf数组中最后一个能读取的byte的下标大1 */ protected int count; 构造函数必须要传入buf[],传入后对于buf的引用无法改变,但可以通过缓存引用来直接修改其中的内容 //创建一个ByteArrayInputStream,使用buf作为缓冲区,缓冲区没有拷贝而是直接引用这个数组。pos初始值为0,count的初始值是buf的数组大小 public ByteArrayInputStream(byte buf[]) { this.buf = buf; this.pos = 0; this.count = buf.length; } //创建一个ByteArrayInputStream,使用buf作为缓冲区,pos初始值是offset,count的初始值是offset+length和buf.length中的较小值。缓冲区没有拷贝,直接引用了buf,mark设为offset public ByteArrayInputStream(byte buf[], int offset, int length) { this.buf = buf; this.pos = offset; this.count = Math.min(offset + length, buf.length); this.mark = offset; } 读取单个byte时,读取输入流中的下一个byte,返回值是0-255的int,已经到达末端没有可读的byte返回-1 public synchronized int read() { return (pos < count) ? (buf[pos++] & 0xff) : -1;//pos==count时到达末端返回-1 } 从流中读取最多len长度的bytes。如果pos==count,返回-1表示已经到达了文件末端,否则返回读取到的bytes数量k,k是len和count-pos中的较小值。如果k是正数,buf[pos]~buf[pos+k-1]将通过ystem.arraycopy被复制到b[off]~b[off+k-1]中,pos增加k,k被返回。 public synchronized int read(byte b[], int off, int len) { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } if (pos >= count) { return -1; } int avail = count - pos; if (len > avail) { len = avail;//最多读取到流中数据末端 } if (len <= 0) { return 0; } System.arraycopy(buf, pos, b, off, len);//复制数据到b中 pos += len;//增加pos return len; } skip跳过输入流中的n个bytes,如果到达了末端跳过的bytes会少于n。实际跳过的bytes数量k等于n和count-pos中的较小值,pos增加k,k被返回 public synchronized long skip(long n) { long k = count - pos; if (n < k) { k = n < 0 ? 0 : n; } pos += k; return k; } available返回输入流中剩余可以读取或者跳过的bytes数量,等于count-pos,也就是缓冲区中剩余的可被读取的数量 public synchronized int available() { return count - pos; } markSupported测试这个InputStream是否支持mark/reset操作,ByteArrayInputStream总是支持该操作所以直接返回true public boolean markSupported() { return true; } mark将当前的位置标记,ByteArrayInputStream的标记位再构造时默认值是0,可以通过这个方法标记到缓冲区的其他位置,在构造时也可以通过传入offset设置其他mark,若没有传入则标记0。readAheadLimit这个参数在这里没有实际作用,InputStream中加这个参数是留给其他类中mark使用指出mark位置开始能读取的最大bytes数量。 public void mark(int readAheadLimit) { mark = pos; } reset将位置重置到mark的位置 public synchronized void reset() { pos = mark; } close方法什么都没做,所以依然可以照常使用,不会产生IOException public void close() throws IOException { }

优秀的个人博客,低调大师

Java 面向对象 之 接口 interface

http://www.verejava.com/?id=16992815279749 /** 知识点: 接口 interface (重点中的重点) 面向接口的编程 接口的定义: 接口就是一个约定 题目: 主席说要建立和谐社会,温家宝说要为人民服务 思路: 1. 抽象出类: 主席(ChairMan), 省长(Governer) 2. 找出关系: 各省省长传达并实现 主席讲话方针 */ /** 注意: 1. 声明一个接口关键字为 interface 2. 接口中不允许定义方法的实现,只能是声明, 跟抽象类有所不同, 抽象类是 允许定义具体方法的. 所以接口有的时候也称为特殊的抽象类 3. 接口中方法的声明可以省略关键字 abstract ,抽象类中的抽象方法不能省略 4. 接口中方法默认都是public 的 5. 接口中的属性都是静态常量 static final 关键字可以省略,接口中属性默认 是public 的并且可以省略public ,不允许有private,protected 关键字修饰 6. 实现接口的类用关键字 implements 7. 实现类中必须 实现接口中的所有声明方法, 跟抽象类一样 8. 不能实例化接口, 必须有其实现类间接实例化, 跟抽象类一样 9. 如果要实现多个接口用, 隔开, 并且实现类要实现所有接口的方法, 而 抽象类不能多继承 10. 接口可以继承多个接口, 抽象类不行(这个就是为什么流行用面向接口编程的原因) 11. 类可以同时继承一个类和实现多个接口 */ public class TestInterface { public static void main(String[] args) { //输出主席名称 System.out.println(ChairMan.name); //实例化接口 //ChairMan chair=new ChairMan(); System.out.println("开各省大会了..."); Governer g1 = new Governer("北京市市长"); g1.buildHarmonyCommunity("教育"); g1.serviceForPeople("慈善"); Governer g2 = new Governer("河北省省长"); g2.buildHarmonyCommunity("联谊晚会"); g2.serviceForPeople("尊老爱幼"); g2.service(); } } interface ChairMan { String name = "主席"; //声明要建立和谐社会 public void buildHarmonyCommunity(String method); } interface PrimeMinister { String name = "总理"; //声明为人民服务 public void serviceForPeople(String method); } interface Leader extends ChairMan, PrimeMinister { } class LeiFeng { public void service() { System.out.println("全心全意为人民服务"); } } class Governer extends LeiFeng implements Leader { private String name;//省长名 public Governer(String name) { this.name = name; } //实现主席建立和谐社会的方针 public void buildHarmonyCommunity(String method) { System.out.println(name + " 我们是通过 " + method + " 来实现和谐社会"); } //实现总理为人民服务的方针 public void serviceForPeople(String method) { System.out.println(name + " 我们是通过 " + method + " 来为人民服务的"); } public String getName() { return this.name; } } http://www.verejava.com/?id=16992815279749

优秀的个人博客,低调大师

正则表达式(java

语法 正则.png 正则.png 正则.png 典型例子 ^\d+$ //匹配非负整数(正整数 + 0) ^[0-9][1-9][0-9]$ //匹配正整数 ^((-\d+)|(0+))$ //匹配非正整数(负整数 + 0) ^-[0-9][1-9][0-9]$ //匹配负整数 ^-?\d+$ //匹配整数 ^\d+(.\d+)?$ //匹配非负浮点数(正浮点数 + 0) ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$ //匹配正浮点数 ^((-\d+(.\d+)?)|(0+(.0+)?))$ //匹配非正浮点数(负浮点数 + 0) ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$ //匹配负浮点数 ^(-?\d+)(.\d+)?$ //匹配浮点数 ^[A-Za-z]+$ //匹配由26个英文字母组成的字符串 ^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串 ^[a-z]+$ //匹配由26个英文字母的小写组成的字符串 ^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串 ^\w+$ //匹配由数字、26个英文字母或者下划线组成的字符串 ^[\w-]+(.[\w-]+)*@[\w-]+(.[\w-]+)+$ //匹配email地址 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空行的正则表达式:\n[\s| ]*\r 匹配HTML标记的正则表达式:/<(.)>.</\1>|<(.*) />/ 匹配首尾空格的正则表达式:(^\s)|(\s$) 正则表达式用例 1、^\S+[a-z A-Z]$ 不能为空 不能有空格 只能是英文字母 2、\S{6,} 不能为空 六位以上 3、^\d+$ 不能有空格 只能是数字 4、(.*)(.jpg|.bmp)$ 只能是jpg和bmp格式 5、^\d{4}-\d{1,2}-\d{1,2}$ 只能是2004-10-22格式 6、^0$ 至少选一项 7、^0{2,}$ 至少选两项 8、^[\s|\S]{20,}$ 不能为空 二十字以上 9、^+?a-z0-9*@([a-z0-9]+(.|-))+[a-z]{2,6}$邮件 10、\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)([,;]\s\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)) 输入多个地址用逗号或空格分隔邮件 11、^(([0-9]+))?[0-9]{7,8}$电话号码7位或8位或前面有区号例如(022)87341628 12、^[a-z A-Z 0-9 *]+@[a-z A-Z 0-9 *]+(.[a-z A-Z 0-9 *]+)+(,[a-z A-Z 0-9 *]+@[a-z A-Z 0-9 *]+(.[a-z A-Z 0-9 ]+)+)$ 只能是字母、数字、下划线;必须有@和.同时格式要规范 邮件 13 ^\w+@\w+(.\w+)+(,\w+@\w+(.\w+)+)*$上面表达式也可以写成这样子,更精练。 14 ^\w+((-\w+)|(.\w+))@\w+((.|-)\w+).\w+$ [/size]

优秀的个人博客,低调大师

Java 面向对象 之 对象数组

http://www.verejava.com/?id=16992784958543 /** 知识点: 对象数组 1. 对象数组的使用 2. 对象数组的foreach 增强for循环 3. 可变参数 题目:乘客一次只能带2个箱子免费上飞机 思路: 1. 抽象出类 乘客(Customer) , 箱子(Box) 2. 乘客和箱子的关系 1对2的关系 Box->Customer */ public class ObjectArray { public static void main(String[] args) { //实例化一个乘客 Customer c = new Customer("黎明"); //实例化两个箱子一个装衣服, 一个装书 Box clothBox = new Box("装衣服"); clothBox.setId(1); clothBox.setWeight(20); Box bookBox = new Box("装书"); bookBox.setId(2); bookBox.setWeight(30); //将箱子添加到乘客 c.addBox(clothBox); c.addBox(bookBox); //打印该乘客的信息 System.out.println("乘客姓名: " + c.getName()); System.out.println("箱子编号, 箱子重量, 箱子描述"); Box[] boxes = c.getBoxes(); for (Box box : boxes) { System.out.println(box.getId() + "," + box.getWeight() + "," + box.getDescription()); } //测试可变参数 Box[] boxes2 = { clothBox, bookBox }; c.setBoxes();//不传参数 c.setBoxes(clothBox);//传一个参数 c.setBoxes(boxes2);//传一个数组 boxes = c.getBoxes(); for (Box box : boxes) { System.out.println(box.getId() + "," + box.getWeight() + "," + box.getDescription()); } } } class Customer { private String name;//乘客名字 private Box[] boxes = new Box[2];//箱子属于乘客, 添加箱子引用 public Customer(String name) { this.name = name; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Box[] getBoxes() { return this.boxes; } //乘客携带添加的箱子 //返回值: 如果添加成功返回true 否则false public boolean addBox(Box box) { for (int i = 0; i < boxes.length; i++) { if (boxes[i] == null) { boxes[i] = box; return true; } } return false; } public void setBoxes(Box... boxes) { this.boxes = boxes; } } class Box { private float weight;//箱子的重量 private int id;//箱子的编号 private String description;//描述 public Box(String description) { this.description = description; } public String getDescription() { return this.description; } public void setDescription(String description) { this.description = description; } public int getId() { return this.id; } public void setId(int id) { this.id = id; } public float getWeight() { return this.weight; } public void setWeight(float weight) { this.weight = weight; } } http://www.verejava.com/?id=16992784958543

优秀的个人博客,低调大师

Java 面向对象 之 代码块

http://www.verejava.com/?id=16992781354342 /** 知识点: 代码块 1. 普通代码块 2. 构造代码块 3. 静态代码块 */ public class CodeBlock { //写在构造方法里的叫 构造代码块 public CodeBlock() { System.out.println("CodeBlock 初始化"); } //写在 static 块里的叫 静态代码块 static { System.out.println("static 执行"); } public static void main(String[] args) { //写在方法里的叫 普通代码块 System.out.println("hello"); new CodeBlock(); } } /** 注意: 静态代码块是在程序编译期运行 所以静态代码块会在构造方法前调用 */ http://www.verejava.com/?id=16992781354342

优秀的个人博客,低调大师

Java 面向对象 之 引用传递

http://www.verejava.com/?id=16992763271038 /** 知识点内容: 引用传递 1. 方法参数引用传递 2. 对象与对象之间的引用传递 3. this指针 本对象引用传递 */ public class Refenrence { public static void main(String[] args) { //实例化 工具类 Utils Utils utils = new Utils(); //定义一个计数器个变量 int count = 1; System.out.println(count); utils.increment(count); System.out.println(count); //定义一个计数器数组变量 int[] counts = { 1 }; System.out.println(counts[0]); utils.increment(counts); System.out.println(counts[0]); //定义一个计数器类变量 Count value = new Count(); value.setValue(1); System.out.println(value.getValue()); utils.increment(value); System.out.println(value.getValue()); } } //建一个工具类 class Utils { public void increment(int count) { count++; } public void increment(int[] counts) { counts[0]++; } public void increment(Count count) { count.setValue(count.getValue() + 1); } } class Count { private int value; public int getValue() { return this.value; } public void setValue(int value) { this.value = value; } } http://www.verejava.com/?id=16992763271038

优秀的个人博客,低调大师

Java 面向对象 之 封装方法

http://www.verejava.com/?id=16992728331734 /** 测试类的封装特性 类的封装特性就是, 将类的属性私有化private 然后提供公有的方法去访问 */ public class Encapsulation { public static void main(String[] args) { //实例化Person 类 //1. 引用对象不能访问类的私有属性 //2. 如果要访问私有属性, 一般类中要另外提供访问私有属性的公有方法 Person p = new Person(); //p.name="李明"; //p.age=22; p.setName("李明"); p.setAge(22); p.say(); System.out.println(p); System.out.println(p.getName() + " " + p.getAge()); } } class Person { //实现类属性的封装 前面加 private 关键字 private String name; private int age; //定义访问私有属性的公有方法 //括号中 String name 是 方法setName 的传入参数 public void setName(String name) { //this 代表当前对象的引用, 哪个对象引用该类,就是指的哪个引用 System.out.println(this); this.name = name; } //String 是方法getName 的返回值的类型 输出返回值 public String getName() { return this.name; } public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } public void say() { System.out.println("我的名字叫:" + name + ",今年 " + age + " 岁"); } } /* 回顾总结 1. 在类当中定义的变量叫成员变量, 属性就是成员变量, 可以在整个类当中访问 2. 在方法中定义的变量叫局部变量, 只能在定义的方法当中访问 注意: 当局部变量和成员变量同名的时候, 局部变量回覆盖掉成员变量,所以当两个变量同名时 要区分成员变量必须加上 this */ http://www.verejava.com/?id=16992728331734

优秀的个人博客,低调大师

Java----------LeetCode----------46. 全排列

说起回溯算法,渊源颇深,我上次做过一道,本应该这次能拿下但是,又没拿下,不过这次有点理解它的思想了, 每次的回溯就是一个二叉树,简单的说,就是你执行的操作需要回溯时它会返回调用它的方法哪里的状态,进行下一步的执行。 public List<List<Integer>> permute(int[] nums) { List<List<Integer>> temp = new ArrayList<>(20); zuhe(temp,0,nums); return temp; } private void zuhe(List<List<Integer>> temp, int n, int[] nums) { /* * 每次让其加一个就行了,就空了, * */ if (nums.length == n) { List<Integer> integers =new ArrayList<>(20); for (int r:nums){ integers.add(r); } temp.add(integers); } for (int i = n, length = nums.length; i <length ; i++) { change(nums,i,n); zuhe(temp,n+1,nums); change(nums,i,n); } } public void change(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } 这个需要多练,具体自己体会

优秀的个人博客,低调大师

Java 目录和文件的复制

1.复制一个目录及其子目录、文件到另外一个目录 //复制一个目录及其子目录、文件到另外一个目录 public void copyFolder(File src, File dest) throws IOException { if (src.isDirectory()) { if (!dest.exists()) { dest.mkdir(); } String files[] = src.list(); for (String file : files) { File srcFile = new File(src, file); File destFile = new File(dest, file); // 递归复制 copyFolder(srcFile, destFile); } } else { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest); byte[] buffer = new byte[1024]; int length; while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); out.close(); } } private void copyFolder(File src, File dest) throws IOException { if (src.isDirectory()) { if (!dest.exists()) { dest.mkdir(); } String files[] = src.list(); for (String file : files) { File srcFile = new File(src, file); File destFile = new File(dest, file); // 递归复制 copyFolder(srcFile, destFile); } } else { InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dest); byte[] buffer = new byte[ 1024]; int length; while ((length = in.read(buffer)) > 0) { out.write(buffer, 0, length); } in.close(); out.close(); } }

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册