学校做网站方案wordpress仿站视频教程

pingmian/2026/1/23 23:48:30/文章来源:
学校做网站方案,wordpress仿站视频教程,自己编程制作app软件,游戏网站域名一、NIO三大组件 NIO的三大组件分别是Channel#xff0c;Buffer与Selector Java NIO系统的核心在于#xff1a;通道(Channel)和缓冲区(Buffer)。通道表示打开到 IO 设备(例如#xff1a;文件、套接字)的连接。若需要使用 NIO 系统#xff0c;需要获取用于连接 IO 设备的通…一、NIO三大组件 NIO的三大组件分别是ChannelBuffer与Selector Java NIO系统的核心在于通道(Channel)和缓冲区(Buffer)。通道表示打开到 IO 设备(例如文件、套接字)的连接。若需要使用 NIO 系统需要获取用于连接 IO 设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区对数据进行处理 简而言之通道负责传输缓冲区负责存储 常见的Channel有以下四种其中FileChannel主要用于文件传输其余三种用于网络通信 FileChannelDatagramChannelSocketChannelServerSocketChannel Buffer有以下几种其中使用较多的是ByteBuffer ByteBuffer MappedByteBufferDirectByteBufferHeapByteBufferShortBufferIntBufferLongBufferFloatBufferDoubleBufferCharBuffer 1、Selector 在使用Selector之前处理socket连接还有以下两种方法 1.使用多线程技术 为每个连接分别开辟一个线程分别去处理对应的socke连接 这种方法存在以下几个问题 内存占用高 每个线程都需要占用一定的内存当连接较多时会开辟大量线程导致占用大量内存线程上下文切换成本高只适合连接数少的场景 连接数过多会导致创建很多线程从而出现问题 2.使用线程池技术 使用线程池让线程池中的线程去处理连接 这种方法存在以下几个问题 阻塞模式下线程仅能处理一个连接 线程池中的线程获取任务task后只有当其执行完任务之后断开连接后才会去获取并执行下一个任务若socke连接一直未断开则其对应的线程无法处理其他socke连接仅适合短连接场景 短连接即建立连接发送请求并响应后就立即断开使得线程池中的线程可以快速处理其他连接 3.使用选择器 selector 的作用就是配合一个线程来管理多个 channelfileChannel因为是阻塞式的所以无法使用selector获取这些 channel 上发生的事件这些 channel 工作在非阻塞模式下当一个channel中没有执行任务时可以去执行其他channel中的任务。适合连接数多但流量较少的场景 若事件未就绪调用 selector 的 select() 方法会阻塞线程直到 channel 发生了就绪事件。这些事件就绪后select 方法就会返回这些事件交给 thread 来处理 2、ByteBuffer 使用案例 使用方式 向 buffer 写入数据例如调用 channel.read(buffer)调用 flip() 切换至读模式 flip会使得buffer中的limit变为positionposition变为0从 buffer 读取数据例如调用 buffer.get()调用 clear() 或者compact()切换至写模式 调用clear()方法时position0limit变为capacity调用compact()方法时会将缓冲区中的未读数据压缩到缓冲区前面重复以上步骤 使用ByteBuffer读取文件中的内容 public class TestByteBuffer {public static void main(String[] args) {// 获得FileChanneltry (FileChannel channel new FileInputStream(stu.txt).getChannel()) {// 获得缓冲区ByteBuffer buffer ByteBuffer.allocate(10);int hasNext 0;StringBuilder builder new StringBuilder();while((hasNext channel.read(buffer)) 0) {// 切换模式 limitposition, position0buffer.flip();// 当buffer中还有数据时获取其中的数据while(buffer.hasRemaining()) {builder.append((char)buffer.get());}// 切换模式 position0, limitcapacitybuffer.clear();}System.out.println(builder.toString());} catch (IOException e) {}} } 打印结果 核心属性 0123456789abcdef 字节缓冲区的父类Buffer中有几个核心属性如下 // Invariants: mark position limit capacity private int mark -1; private int position 0; private int limit; private int capacity; capacity缓冲区的容量。通过构造函数赋予一旦设置无法更改limit缓冲区的界限。位于limit 后的数据不可读写。缓冲区的限制不能为负并且不能大于其容量position下一个读写位置的索引类似PC。缓冲区的位置不能为负并且不能大于limitmark记录当前position的值。position被改变后可以通过调用reset() 方法恢复到mark的位置。 以上四个属性必须满足以下要求 mark position limit capacity 核心方法 ut()方法 put()方法可以将一个数据放入到缓冲区中。进行该操作后postition的值会1指向下一个可以放入的位置。capacity limit 为缓冲区容量的值。 flip()方法 flip()方法会切换对缓冲区的操作模式由写-读 / 读-写进行该操作后 如果是写模式-读模式position 0 limit 指向最后一个元素的下一个位置capacity不变如果是读-写则恢复为put()方法中的值 get()方法 get()方法会读取缓冲区中的一个值进行该操作后position会1如果超过了limit则会抛出异常注意get(i)方法不会改变position的值 如果想通过get方法重复读取数据 可以调用rewind方法讲position重新置为0或者调用get(int i)方法获取索引 i 的内容它不会移动读指针 rewind()方法 该方法只能在读模式下使用rewind()方法后会恢复position、limit和capacity的值变为进行get()前的值 clean()方法 clean()方法会将缓冲区中的各个属性恢复为最初的状态position 0, capacity limit此时缓冲区的数据依然存在处于“被遗忘”状态下次进行写操作时会覆盖这些数据 mark()和reset()方法 mark()方法会将postion的值保存到mark属性中reset()方法会将position的值改为mark中保存的值 compact()方法 此方法为ByteBuffer的方法而不是Buffer的方法 compact会把未读完的数据向前压缩然后切换到写模式数据前移后原位置的值并未清零写时会覆盖之前的值 clear() VS compact() clear只是对position、limit、mark进行重置而compact在对position进行设置以及limit、mark进行重置的同时还涉及到数据在内存中拷贝会调用arraycopy。所以compact比clear更耗性能。但compact能保存你未读取的数据将新数据追加到为读取的数据之后而clear则不行若你调用了clear则未读取的数据就无法再读取到了 ByteBuffer.allocate() 与 ByteBuffer.allocateDirect()  allocate()方法返回类型是  class java.nio .HeapByteBuffer HeapByteBuffer 使用的是 java 堆内存读写效率较低受到GC的影响 allocateDirect() 方法返回类型是  class java.nio .DirectByteBufferDirectByteBuffer 使用的是直接内存 读写效率高(少一次拷贝)不会受GC影响但是分配的效率低因为需要调用系统的分配内存相关接口而且使用不当会造成内存泄漏 所以需要根据情况来判断使用哪种方法进行模式切换 方法调用及演示 ByteBuffer调试工具类 需要先导入netty依赖 dependencygroupIdio.netty/groupIdartifactIdnetty-all/artifactIdversion4.1.51.Final/version /dependency 创建一个工具类便于观察ByteBuffer的内部结构 import java.nio.ByteBuffer;import io.netty.util.internal.MathUtil; import io.netty.util.internal.StringUtil; import io.netty.util.internal.MathUtil.*;/*** author qingm* date 2024/1/12 15:59*/ public class ByteBufferUtil {private static final char[] BYTE2CHAR new char[256];private static final char[] HEXDUMP_TABLE new char[256 * 4];private static final String[] HEXPADDING new String[16];private static final String[] HEXDUMP_ROWPREFIXES new String[65536 4];private static final String[] BYTE2HEX new String[256];private static final String[] BYTEPADDING new String[16];static {final char[] DIGITS 0123456789abcdef.toCharArray();for (int i 0; i 256; i) {HEXDUMP_TABLE[i 1] DIGITS[i 4 0x0F];HEXDUMP_TABLE[(i 1) 1] DIGITS[i 0x0F];}int i;// Generate the lookup table for hex dump paddingsfor (i 0; i HEXPADDING.length; i) {int padding HEXPADDING.length - i;StringBuilder buf new StringBuilder(padding * 3);for (int j 0; j padding; j) {buf.append( );}HEXPADDING[i] buf.toString();}// Generate the lookup table for the start-offset header in each row (up to 64KiB).for (i 0; i HEXDUMP_ROWPREFIXES.length; i) {StringBuilder buf new StringBuilder(12);buf.append(StringUtil.NEWLINE);buf.append(Long.toHexString(i 4 0xFFFFFFFFL | 0x100000000L));buf.setCharAt(buf.length() - 9, |);buf.append(|);HEXDUMP_ROWPREFIXES[i] buf.toString();}// Generate the lookup table for byte-to-hex-dump conversionfor (i 0; i BYTE2HEX.length; i) {BYTE2HEX[i] StringUtil.byteToHexStringPadded(i);}// Generate the lookup table for byte dump paddingsfor (i 0; i BYTEPADDING.length; i) {int padding BYTEPADDING.length - i;StringBuilder buf new StringBuilder(padding);for (int j 0; j padding; j) {buf.append( );}BYTEPADDING[i] buf.toString();}// Generate the lookup table for byte-to-char conversionfor (i 0; i BYTE2CHAR.length; i) {if (i 0x1f || i 0x7f) {BYTE2CHAR[i] .;} else {BYTE2CHAR[i] (char) i;}}}/*** 打印所有内容* param buffer*/public static void debugAll(ByteBuffer buffer) {int oldlimit buffer.limit();buffer.limit(buffer.capacity());StringBuilder origin new StringBuilder(256);appendPrettyHexDump(origin, buffer, 0, buffer.capacity());System.out.println(---------------------------- all ----------------------------------------);System.out.printf(position: [%d], limit: [%d]\n, buffer.position(), oldlimit);System.out.println(origin);buffer.limit(oldlimit);}/*** 打印可读取内容* param buffer*/public static void debugRead(ByteBuffer buffer) {StringBuilder builder new StringBuilder(256);appendPrettyHexDump(builder, buffer, buffer.position(), buffer.limit() - buffer.position());System.out.println(---------------------------- read ---------------------------------------);System.out.printf(position: [%d], limit: [%d]\n, buffer.position(), buffer.limit());System.out.println(builder);}private static void appendPrettyHexDump(StringBuilder dump, ByteBuffer buf, int offset, int length) {if (MathUtil.isOutOfBounds(offset, length, buf.capacity())) {throw new IndexOutOfBoundsException(expected: 0 offset( offset ) offset length( length ) buf.capacity( buf.capacity() ));}if (length 0) {return;}dump.append( ------------------------------------------------- StringUtil.NEWLINE | 0 1 2 3 4 5 6 7 8 9 a b c d e f | StringUtil.NEWLINE -------------------------------------------------------------------------);final int startIndex offset;final int fullRows length 4;final int remainder length 0xF;// Dump the rows which have 16 bytes.for (int row 0; row fullRows; row) {int rowStartIndex (row 4) startIndex;// Per-row prefix.appendHexDumpRowPrefix(dump, row, rowStartIndex);// Hex dumpint rowEndIndex rowStartIndex 16;for (int j rowStartIndex; j rowEndIndex; j) {dump.append(BYTE2HEX[getUnsignedByte(buf, j)]);}dump.append( |);// ASCII dumpfor (int j rowStartIndex; j rowEndIndex; j) {dump.append(BYTE2CHAR[getUnsignedByte(buf, j)]);}dump.append(|);}// Dump the last row which has less than 16 bytes.if (remainder ! 0) {int rowStartIndex (fullRows 4) startIndex;appendHexDumpRowPrefix(dump, fullRows, rowStartIndex);// Hex dumpint rowEndIndex rowStartIndex remainder;for (int j rowStartIndex; j rowEndIndex; j) {dump.append(BYTE2HEX[getUnsignedByte(buf, j)]);}dump.append(HEXPADDING[remainder]);dump.append( |);// Ascii dumpfor (int j rowStartIndex; j rowEndIndex; j) {dump.append(BYTE2CHAR[getUnsignedByte(buf, j)]);}dump.append(BYTEPADDING[remainder]);dump.append(|);}dump.append(StringUtil.NEWLINE -------------------------------------------------------------------------);}private static void appendHexDumpRowPrefix(StringBuilder dump, int row, int rowStartIndex) {if (row HEXDUMP_ROWPREFIXES.length) {dump.append(HEXDUMP_ROWPREFIXES[row]);} else {dump.append(StringUtil.NEWLINE);dump.append(Long.toHexString(rowStartIndex 0xFFFFFFFFL | 0x100000000L));dump.setCharAt(dump.length() - 9, |);dump.append(|);}}public static short getUnsignedByte(ByteBuffer buffer, int index) {return (short) (buffer.get(index) 0xFF);} } 调用ByteBuffer的方法 public class TestByteBuffer {public static void main(String[] args) {ByteBuffer buffer ByteBuffer.allocate(10);// 向buffer中写入1个字节的数据buffer.put((byte)97);// 使用工具类查看buffer状态ByteBufferUtil.debugAll(buffer);// 向buffer中写入4个字节的数据buffer.put(new byte[]{98, 99, 100, 101});ByteBufferUtil.debugAll(buffer);// 获取数据buffer.flip();ByteBufferUtil.debugAll(buffer);System.out.println(buffer.get());System.out.println(buffer.get());ByteBufferUtil.debugAll(buffer);// 使用compact切换模式buffer.compact();ByteBufferUtil.debugAll(buffer);// 再次写入buffer.put((byte)102);buffer.put((byte)103);ByteBufferUtil.debugAll(buffer);} } 运行结果 // 向缓冲区写入了一个字节的数据此时postition为1 ---------------------------- all ---------------------------------------- position: [1], limit: [10]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 61 00 00 00 00 00 00 00 00 00 |a......... | -------------------------------------------------------------------------// 向缓冲区写入四个字节的数据此时position为5 ---------------------------- all ---------------------------------------- position: [5], limit: [10]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 61 62 63 64 65 00 00 00 00 00 |abcde..... | -------------------------------------------------------------------------// 调用flip切换模式此时position为0表示从第0个数据开始读取 ---------------------------- all ---------------------------------------- position: [0], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 61 62 63 64 65 00 00 00 00 00 |abcde..... | ------------------------------------------------------------------------- // 读取两个字节的数据 97 98// position变为2 ---------------------------- all ---------------------------------------- position: [2], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 61 62 63 64 65 00 00 00 00 00 |abcde..... | -------------------------------------------------------------------------// 调用compact切换模式此时position及其后面的数据被压缩到ByteBuffer前面去了 // 此时position为3会覆盖之前的数据 ---------------------------- all ---------------------------------------- position: [3], limit: [10]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 63 64 65 64 65 00 00 00 00 00 |cdede..... | -------------------------------------------------------------------------// 再次写入两个字节的数据之前的 0x64 0x65 被覆盖 ---------------------------- all ---------------------------------------- position: [5], limit: [10]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 63 64 65 66 67 00 00 00 00 00 |cdefg..... | ------------------------------------------------------------------------- 字符串与ByteBuffer的相互转换 方法一 编码字符串调用getByte方法获得byte数组将byte数组放入ByteBuffer中 解码先调用ByteBuffer的flip方法然后通过StandardCharsets的decoder方法解码 public class Translate {public static void main(String[] args) {// 准备两个字符串String str1 hello;String str2 ;ByteBuffer buffer1 ByteBuffer.allocate(16);// 通过字符串的getByte方法获得字节数组放入缓冲区中buffer1.put(str1.getBytes());ByteBufferUtil.debugAll(buffer1);// 将缓冲区中的数据转化为字符串// 切换模式buffer1.flip();// 通过StandardCharsets解码获得CharBuffer再通过toString获得字符串str2 StandardCharsets.UTF_8.decode(buffer1).toString();System.out.println(str2);ByteBufferUtil.debugAll(buffer1);} } 运行结果 ---------------------------- all ---------------------------------------- position: [5], limit: [16]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 |hello...........| ------------------------------------------------------------------------- hello ---------------------------- all ---------------------------------------- position: [5], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 68 65 6c 6c 6f 00 00 00 00 00 00 00 00 00 00 00 |hello...........| -------------------------------------------------------------------------Copy 方法二 编码通过StandardCharsets的encode方法获得ByteBuffer此时获得的ByteBuffer为读模式无需通过flip切换模式 解码通过StandardCharsets的decoder方法解码 public class Translate {public static void main(String[] args) {// 准备两个字符串String str1 hello;String str2 ;// 通过StandardCharsets的encode方法获得ByteBuffer// 此时获得的ByteBuffer为读模式无需通过flip切换模式ByteBuffer buffer1 StandardCharsets.UTF_8.encode(str1);ByteBufferUtil.debugAll(buffer1);// 将缓冲区中的数据转化为字符串// 通过StandardCharsets解码获得CharBuffer再通过toString获得字符串str2 StandardCharsets.UTF_8.decode(buffer1).toString();System.out.println(str2);ByteBufferUtil.debugAll(buffer1);} } 运行结果 ---------------------------- all ---------------------------------------- position: [0], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 68 65 6c 6c 6f |hello | ------------------------------------------------------------------------- hello ---------------------------- all ---------------------------------------- position: [5], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 68 65 6c 6c 6f |hello | -------------------------------------------------------------------------Copy 方法三 编码字符串调用getByte()方法获得字节数组将字节数组传给ByteBuffer的wrap()方法通过该方法获得ByteBuffer。同样无需调用flip方法切换为读模式 解码通过StandardCharsets的decoder方法解码 public class Translate {public static void main(String[] args) {// 准备两个字符串String str1 hello;String str2 ;// 通过StandardCharsets的encode方法获得ByteBuffer// 此时获得的ByteBuffer为读模式无需通过flip切换模式ByteBuffer buffer1 ByteBuffer.wrap(str1.getBytes());ByteBufferUtil.debugAll(buffer1);// 将缓冲区中的数据转化为字符串// 通过StandardCharsets解码获得CharBuffer再通过toString获得字符串str2 StandardCharsets.UTF_8.decode(buffer1).toString();System.out.println(str2);ByteBufferUtil.debugAll(buffer1);} } 运行结果 ---------------------------- all ---------------------------------------- position: [0], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 68 65 6c 6c 6f |hello | ------------------------------------------------------------------------- hello ---------------------------- all ---------------------------------------- position: [5], limit: [5]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 68 65 6c 6c 6f |hello | ------------------------------------------------------------------------- 粘包与半包 现象 网络上有多条数据发送给服务端数据之间使用 \n 进行分隔 但由于某种原因这些数据在接收时被进行了重新组合例如原始数据有3条为 Hello,world\nI’m Nyima\nHow are you?\n 变成了下面的两个 byteBuffer (粘包半包) Hello,world\nI’m Nyima\nHow are you?\n 出现原因 粘包 发送方在发送数据时并不是一条一条地发送数据而是将数据整合在一起当数据达到一定的数量后再一起发送。这就会导致多条信息被放在一个缓冲区中被一起发送出去 半包 接收方的缓冲区的大小是有限的当接收方的缓冲区满了以后就需要将信息截断等缓冲区空了以后再继续放入数据。这就会发生一段完整的数据最后被截断的现象 解决办法 通过get(index)方法遍历ByteBuffer遇到分隔符时进行处理。注意get(index)不会改变position的值 记录该段数据长度以便于申请对应大小的缓冲区将缓冲区的数据通过get()方法写入到target中调用compact方法切换模式因为缓冲区中可能还有未读的数据 public class ByteBufferDemo {public static void main(String[] args) {ByteBuffer buffer ByteBuffer.allocate(32);// 模拟粘包半包buffer.put(Hello,world\nIm Nyima\nHo.getBytes());// 调用split函数处理split(buffer);buffer.put(w are you?\n.getBytes());split(buffer);}private static void split(ByteBuffer buffer) {// 切换为读模式buffer.flip();for(int i 0; i buffer.limit(); i) {// 遍历寻找分隔符// get(i)不会移动positionif (buffer.get(i) \n) {// 缓冲区长度int length i1-buffer.position();ByteBuffer target ByteBuffer.allocate(length);// 将前面的内容写入target缓冲区for(int j 0; j length; j) {// 将buffer中的数据写入target中target.put(buffer.get());}// 打印查看结果ByteBufferUtil.debugAll(target);}}// 切换为写模式但是缓冲区可能未读完这里需要使用compactbuffer.compact();} } 运行结果 ---------------------------- all ---------------------------------------- position: [12], limit: [12]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 48 65 6c 6c 6f 2c 77 6f 72 6c 64 0a |Hello,world. | ------------------------------------------------------------------------- ---------------------------- all ---------------------------------------- position: [10], limit: [10]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 49 27 6d 20 4e 79 69 6d 61 0a |Im Nyima. | ------------------------------------------------------------------------- ---------------------------- all ---------------------------------------- position: [13], limit: [13]-------------------------------------------------| 0 1 2 3 4 5 6 7 8 9 a b c d e f | ------------------------------------------------------------------------- |00000000| 48 6f 77 20 61 72 65 20 79 6f 75 3f 0a |How are you?. | ------------------------------------------------------------------------- 二、文件编程 1、FileChannel 工作模式 FileChannel只能在阻塞模式下工作所以无法搭配Selector 获取 不能直接打开 FileChannel必须通过 FileInputStream、FileOutputStream 或者 RandomAccessFile 来获取 FileChannel它们都有 getChannel 方法 通过 FileInputStream 获取的 channel 只能读通过 FileOutputStream 获取的 channel 只能写通过 RandomAccessFile 是否能读写根据构造 RandomAccessFile 时的读写模式决定 读取 通过 FileInputStream 获取channel通过read方法将数据写入到ByteBuffer中 read方法的返回值表示读到了多少字节若读到了文件末尾则返回-1 int readBytes channel.read(buffer);Copy 可根据返回值判断是否读取完毕 while(channel.read(buffer) 0) {// 进行对应操作... } 写入 因为channel也是有大小的所以 write 方法并不能保证一次将 buffer 中的内容全部写入 channel。必须需要按照以下规则进行写入   // 通过hasRemaining()方法查看缓冲区中是否还有数据未写入到通道中 while(buffer.hasRemaining()) {channel.write(buffer); } 关闭 通道需要close一般情况通过try-with-resource进行关闭最好使用以下方法获取strea以及channel避免某些原因使得资源未被关闭   public class TestChannel {public static void main(String[] args) throws IOException {try (FileInputStream fis new FileInputStream(stu.txt);FileOutputStream fos new FileOutputStream(student.txt);FileChannel inputChannel fis.getChannel();FileChannel outputChannel fos.getChannel()) {// 执行对应操作...}} } 位置 position channel也拥有一个保存读取数据位置的属性即position long pos channel.position(); 可以通过position(int pos)设置channel中position的值 long newPos ...; channel.position(newPos); 设置当前位置时如果设置为文件的末尾 这时读取会返回 -1这时写入会追加内容但要注意如果 position 超过了文件末尾再写入时在新内容和原末尾之间会有空洞00 强制写入 操作系统出于性能的考虑会将数据缓存不是立刻写入磁盘而是等到缓存满了以后将所有数据一次性的写入磁盘。可以调用 force(true) 方法将文件内容和元数据文件的权限等信息立刻写入磁盘

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

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

相关文章

河南网站建设37518外贸局合并到哪个局

一、源码特点 JSP康养小镇管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&a…

织梦怎么用框架实现在浏览器的地址栏只显示网站的域名而不显示出文件名企业网站策划过程

不同于 java 中的反射,Rust 没有提供以往意义上的运行时反射,取而代之的是 “编译期反射”,如 类型分析、类型转换、类型签名。但即便如此,也已经能对 Rust元编程 提供很多助力了。 这种操作,主要通过 Any 来实现&…

网站建设设计企业西安网站优化效果

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程。 一、内省是什么、实现方式: 内省(Introspector)是Java语言对Bean类属性、事件的一种缺省处理方法。…

永久免费个人网站注册厦门网站建设模拟平台

近日,全球领先的物联网整体解决方案供应商移远通信宣布,其旗下符合3GPP R17标准的新一代5G-A模组RG650V-NA成功通过了北美两家重要运营商认证。凭借高速度、大容量、低延迟、高可靠等优势,该模组可满足CPE、家庭/企业网关、移动热点、高清视频…

有口碑的宁波网站建设信息流优化师招聘

确保代码完整性 在撸业务代码时候,经常面对的是接口的设计,在设计之初,我们必然要先想好入参,之后自然会有参数的校验过程,此时我们需要把可能的输入都想清楚,从而避免在程序中出现各种纰漏。但是难免面面…

商丘网站制作推广网站建设是指

通过上一篇文章的介绍,我们已经了解到了在CorelDRAW中如何自定义设置默认字体,相关阅读可参阅:CDR X8设置文字为默认字体。其实在CorelDRAW软件中给用户提供方式不止是一种,本文将介绍更多关于设置默认字体的方法。1. 打开CorelDR…

自己怎么用h5做网站国家信息公示系统

glibc提供了backtrace这个库函数,可以用来打印call stack。比如我们可以在程序中注册常见的一些signal,比如SIGSEGMENT, SIGPIPE,然后在这些信号的回调函数中,利用backtrace打印出call stack,这样debug就非常的方便。 …

网站开发系统设计苏州网站制作计划

文章目录 生成随机值生成随机数生成范围内随机数生成自定义类型随机值从一组字母数字字符创建随机密码从一组用户定义字符创建随机密码 总结 生成随机值 rust中官方并没有像以他语言一样,rust并没有官方并没有提供生成随机数的工具,所以我们要借助rand包…

电子政务和网站建设工作的总结seo关键词优化平台

测量矩阵的基本概念 在压缩感知(Compressed Sensing,CS)理论中,测量矩阵(也称为采样矩阵)是实现信号压缩采样的关键工具。它是一个通常为非方阵的矩阵,用于将信号从高维空间映射到低维空间&…

企业网站网上推广的途径网站开发有哪些类型

一、 数据规范化 1.1 数据规范化的概念 定义 数据规范化是数据库设计中的一种方法,通过组织表结构,减少数据冗余,提高数据一致性和降低更新异常的过程。这一过程确保数据库中的数据结构遵循一定的标准和规范,使得数据存储更加高…

网站建设所用软件手机网页游戏排行榜2021前十名

总览 Exchanger类在线程之间传递工作和回收使用的对象方面非常有效。 AFAIK,它也是最少使用的并发类之一。 但是,如果您不需要GC,则使用ArrayBlockingQueue进行日志记录会更简单。 交换器类 Exchanger类对于在两个线程之间来回传递数据很有…

网站搭建南京微信平台商城开发

背景:润乾报表 win上面的项目直接上传到linux 上,但预览&下载报表时乱码如果含有斜线的单元格或统计图的报表在网页上发布时,统计图或斜线单元格里的汉字会变成小方框,此时往往是服务器端操作系统的中文安装包没有装全&#x…

如何做网站规范网站升级中

前言 在很多第一人称或者第三人称射击游戏的单人模式中,玩家的乐趣往往来源于和各式各样的AI敌人的战斗。而战斗的爆发很多时候是因为这些AI在“看见”玩家后就会立即做出反应,比如开火、呼叫同伴、躲藏或者逃跑等。 所以这些AI到底是如何探测&#xff0…

为什么做不了自己的网站y-m-d WordPress

AttributeError: ‘set’ object has no attribute ‘items’ 出现这个问题,原因可能是定义的header有问题 正确如下: header{“key”:“value”} 如果是直接在请求数据中复制,很有可能会忽略键和值的冒号。

电商的网站开发订单返利功能湖南外贸网站建设

文章目录一、前置准备1. 技术选型2. 创建vue项目二、Rem 布局适配2.1. px转rem2.2. 设置 rem 基准值2.3. 配置vue.config.js2.4. 重置样式表2.5. 配置样式表2.6. 安装less2.7. 注册less2.8. 代码中使用三、vant安装/配置/测试3.1. 安装vant-ui3.2. 引入与注册3.3. vant测试四、…

网站开发平面设计师岗位要求关键词推广和定向推广

简介: K8s 取其精华去其糟粕,是我们程序员应该做的事情。 K8s设计模式 Kubernetes是一个具有普遍意义的容器编排工具,它提供了一套基于容器构建分布式系统的基础依赖,其意义等同于Linux在操作系统中的地位,可以认为是…

创业网站怎么做域名注册哪个好

正常情况下是没有手机上画电子围栏的,公共平台上我也没找到,所以走了一个歪点子,就是给地图添加点击事件,记录点的位置,在画到电子围栏上就是添加电子围栏了,如果只是显示电子围栏就简单了 一、多边形电子…

购物网站开发所用技术台州网站建设方案咨询

数组结构赋值 let [a,b][1,2] //交换两个变量的值 let[a,b][b,a] //扩展运算符的运用 let[a,...b][1,2,3]  //有默认值 右侧的参数等于undefined,默认值生效 let[a3,b][1,2] 对象结构赋值 let {a:a,b:b}{a:1,b:2};let {a,b}{a:1,b:2}let{a,...b}{a:1,b:2,c:3}

行政审批网站建设规范软件开发3000人天报价标准

这三点是webpack优化策略的一部分,具体解释如下: 优化正则匹配(Test):在webpack的配置中,test属性是一个正则表达式,用于匹配需要应用该loader的文件的扩展名。在您提供的代码中,te…

网站制作学校要的相城区公司网站建设

0:前言 🪧 什么情况需要数据库? 1 大规模的数据需要处理(比如上千上万的数据量)2 需要把数据信息存储起来,无论是本地还是服务上,而不是断电后数据信息就消失了。 如果不是上面的原因化,一般…