0
点赞
收藏
分享

微信扫一扫

NIO通道(Channel)分散读取

七千22 2023-09-21 阅读 43

package com.momo.util;

import com.momo.entity.Users;

import java.io.*;

import java.util.ArrayList;

import java.util.Scanner;

public class UserTool implements Serializable {

private ArrayList list = new ArrayList<>();

public void register() throws IOException {

try {

FileInputStream fis = new FileInputStream("users.txt");

ObjectInputStream ois = new ObjectInputStream(fis);

list = (ArrayList)ois.readObject();

}catch (FileNotFoundException e){

System.out.println("第一次文件是空。。。");

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Users u = new Users(); Scanner sc = new Scanner(System.in); Scanner sc1 = new Scanner(System.in); System.out.println("请输入你的名字:"); String s = sc.nextLine(); u.setName(s); System.out.println("请输入你的年龄:"); int age = sc1.nextInt(); u.setAge(age); System.out.println("请输入你的账户名"); String s1 = sc.nextLine(); u.setUser(s1); System.out.println("请输入你的密码:"); String s2 = sc.nextLine(); u.setPassword(s2); list.add(u); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("users.txt")); oos.writeObject(list); oos.close(); System.out.println("恭喜你注册成功!!!"); /* for (Users us : list) { System.out.println(us); }*/ } public void Input() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("users.txt")); list = (ArrayList<Users>) ois.readObject(); /* for (Users us : list) { System.out.println(us); }*/ Scanner sc = new Scanner(System.in); System.out.println("请输入账户名:"); String user = sc.nextLine(); System.out.println("请输入密码:"); String password =sc.nextLine(); for (Users uu : list) { if(uu.getUser().equals(user)&&uu.getPassword().equals(password)){ System.out.println("恭喜你登录成功!!!"); } } }

}

package com.momo.demo;

import com.momo.util.UserTool;

import java.io.IOException;

import java.util.Scanner;

public class Demo1 { public static void main(String[] args) throws IOException, ClassNotFoundException { Scanner sc = new Scanner(System.in); UserTool u = new UserTool(); aa: while(true) { System.out.println("请选择你要进行的操作:1--注册 2--登录 3--退出"); int i = sc.nextInt(); switch (i) { case 1: u.register(); break; case 2: u.Input(); break; case 3 : break aa; default: System.out.println("输入有误"); } } } }

1,多线程小结:

-进程?多进程意义?

-线程?多线程意义?

-多线程的实现方式一:继承Thread,重写run

启动线程是start方法

run方法是用来包裹需要被多线程执行的代码

Thread类中操作线程的方法

-多线程实现方式二:实现Runnable接口,重写run

优点:

-使用多线程模拟卖票,引出了线程安全问题

0票的负票

某一张被卖多次

-解决方案:同步机制

同步代码块

同步方法

-生产者和消费者

如果是生产者先获取了执行权,会不断生产

如果是消费者先获取了执行权,会不断消费。

引出了,等待唤醒机制

-为什么方法在Object中?

-线程组

-线程池

多线程实现方式三,实现Callable接口

-Timer和TimerTask

1,Files

-概述

该类只包含对文件,目录或其他类型文件进行操作的静态方法。

static long copy(Path source, OutputStream out)

将文件中的所有字节复制到输出流。

static Path write(Path path, Iterable lines, OpenOption... options)

将文本行写入文件。

package com.momo.demo;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.nio.charset.Charset;

import java.nio.file.Files;

import java.nio.file.Path;

import java.nio.file.Paths;

import java.nio.file.StandardCopyOption;

import java.util.ArrayList;

import java.util.Iterator;

/*

Files是操作File的工具类

Paths是操作Path的工具类

File和Path是可以相互转换

  • Files类中的方法
  • */

public class Demo2 {

public static void main(String[] args) throws IOException {

long l = Files.copy(Paths.get("笔记.txt"), new FileOutputStream("aaa.txt"));

System.out.println(l);

Path p = Files.copy(Paths.get("笔记.txt"), Paths.get("bbb.txt"), StandardCopyOption.REPLACE_EXISTING); System.out.println(p); ArrayList<String> list = new ArrayList<>(); list.add("小龙"); list.add("sdfd"); list.add("sdfsd"); Path pp = Files.write(Paths.get("code.txt"), list, Charset.forName("utf8")); System.out.println(pp);

}

}

一,NIO

1,概述

-可以理解是新io,new io。

-全称java non-blocking IO 非阻塞式io

-用来替代老io的,它和老io有一样的作用

-使用方式上有很多区别

-nio面向缓冲区的,基于通道的io操作。

-使用nio可以更加高效的进行读写操作。

2,主要区别

-io:面向流, 阻塞式

-nio:面向缓冲区,非阻塞式, 选择器

3,通道和缓冲区

-java nio主要核心在于:通道(Channel) 和 缓冲区(Buffer)

-通道表示io设备的链接,要使用nio需要获取链接通道和用于

存取数据的缓冲区。然后操作缓冲区,对数据进行处理。

-简单的说:通道负责传输,缓冲区负责存取

4,缓冲区(Buffer)

-用于特定原始类型的数据的容器。 是一个抽象类

-所有的具体的缓冲区都是Buffer的子类。

-主要和nio通道交互,可以读,可以写。

package com.momo.demo;

import org.junit.Test;

import java.nio.ByteBuffer;

/*

  • Buffer缓冲区:nio中负责数据存取
  • 根据数据类型的不同,提供了对应的子类。(除了boolean)
  • ByteBuffer , CharBuffer , DoubleBuffer , FloatBuffer , IntBuffer , LongBuffer , ShortBuffer

都可以使用allocate方法,获取对象。

缓冲区中的存取数据的方法:

  • get() 从缓冲区中获取数据
  • put() 给缓冲区冲存入数据 flip() 切换模式

缓冲区中的核心属性:

  • capacity :容量 表示缓冲区最大可以存储的数量。一旦声明就不能改变。
  • limit: 界限 表示缓冲区中现在可操作的大小。 界限之后数据不能读写。
  • position: 位置 表示缓冲区中当前正在操作的位置

  • mark: 标记 记录当前position位置, 使用reset恢复到mark的位置。
  • */

public class Demo3 {

@Test

public void test2(){

String s = "world";

ByteBuffer buf = ByteBuffer.allocate(1024);

buf.put(s.getBytes());

buf.flip();

byte[] bys = new byte[buf.limit()];

buf.get(bys,0,2);

System.out.println(new String(bys,0,2));

System.out.println(buf.position());

buf.mark();//使用标记记录当前位置 //buf.clear(); buf.get(bys,2,2); System.out.println(new String(bys,2,2)); System.out.println(buf.position()); buf.reset();//恢复到标记位置 System.out.println(buf.position()); System.out.println("---------------"); boolean boo = buf.hasRemaining();//判断缓冲区中是否还有剩余数据 int i = buf.remaining();//获取剩余数据的数量 System.out.println(boo); System.out.println(i);

}

@Test

public void test1(){

//创建一个缓冲区

/* ByteBuffer buf = ByteBuffer.allocate(1024);

System.out.println(buf.capacity());

System.out.println(buf.limit());

System.out.println(buf.position());//

System.out.println(buf);

System.out.println(buf1);

System.out.println(buf==buf1);//

byte b = buf.get();

System.out.println(b);*/

ByteBuffer buf = ByteBuffer.allocate(1024); System.out.println(buf.capacity()); System.out.println(buf.limit()); System.out.println(buf.position()); System.out.println("--------------"); String s = "hello"; buf.put(s.getBytes()); System.out.println(buf.capacity()); System.out.println(buf.limit()); System.out.println(buf.position()); System.out.println("--------------"); //切换模式 buf.flip(); System.out.println(buf.capacity()); System.out.println(buf.limit()); System.out.println(buf.position()); System.out.println("--------------"); byte[] bys = new byte[buf.limit()]; ByteBuffer bb = buf.get(bys); System.out.println(new String(bys,0,bys.length)); System.out.println("--------------"); System.out.println(buf.capacity()); System.out.println(buf.limit()); System.out.println(buf.position()); System.out.println("--------------"); buf.rewind();//倒带这个缓冲区。 位置设置为零,标记被丢弃。 System.out.println(buf.capacity()); System.out.println(buf.limit()); System.out.println(buf.position()); System.out.println("--------------"); byte[] bys2 = new byte[buf.limit()]; buf.get(bys2); System.out.println(new String(bys2,0,bys2.length)); System.out.println("--------------"); buf.clear(); //清空缓冲区 重置缓冲区 数据还在,只是被遗忘了。 System.out.println(buf.capacity()); System.out.println(buf.limit()); System.out.println(buf.position()); System.out.println("--------------"); System.out.println((char)buf.get());

}

}

5,直接缓冲区和非直接缓冲区:

-直接缓冲区:allocateDirect方法获取的缓冲区。 把缓冲区建立在物理内存中

-非直接缓冲区:allocate方法获取的缓冲区。把缓冲区建立在jvm内存中。

-看图理解

package com.momo.demo;

import org.junit.Test;

import java.nio.ByteBuffer;

public class Demo4 { @Test public void test1(){ //获取直接缓冲区 ByteBuffer buf = ByteBuffer.allocateDirect(1024); System.out.println(buf.isDirect()); //非直接缓冲区 ByteBuffer buf2 = ByteBuffer.allocate(1024); System.out.println(buf2.isDirect()); } }

二,通道

1,通道(Channel):在Java.nio.channels包下

-表示io设备的链接。

-Channel本身不能直接访问数据,只能和Buffer进行交互。

package com.momo.demo;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

/*

  • 通道Channel: 接口
  • 主要实现类:
  • FileChannel
  • SocketChannel
  • ServerSocketChannel
  • DatagramChannel

  • 如何获取通道?
  • java本身对支持通道的类都提供了getChannel() 方法
  • 本地:
  • FileInputStream
  • FileOutputStream
  • 网络:
  • Socket
  • ServetSocket
  • DatagramSocket

  • 从jdk1.7之后 针对各个通道提供了静态的 open方法
  • 在Files工具类中也有 newByteChannel()
  • */

//利用通道复制文件

public class Demo5 {

public static void main(String[] args) throws IOException {

FileInputStream fis = new FileInputStream("111.jpg");

FileOutputStream fos = new FileOutputStream("123.jpg");

//获取通道 FileChannel inchannel = fis.getChannel(); FileChannel outchannel = fos.getChannel(); //创建缓冲区 ByteBuffer buf = ByteBuffer.allocate(1024); //把数据放入通道中的缓冲区 while (inchannel.read(buf)!=-1){ buf.flip(); outchannel.write(buf); buf.clear(); } //释放资源 fis.close(); fos.close(); inchannel.close(); outchannel.close();

}

}

package com.momo.demo;

import java.io.IOException;

import java.nio.MappedByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.file.Paths;

import java.nio.file.StandardOpenOption;

//使用直接缓冲区和open方法获取通道

/*

  • static FileChannel open(Path path, OpenOption... options)

打开或创建文件,返回文件通道以访问该文件。

  • StandardOpenOption 这个是OpenOption的具体子类

打开方式,在这个子类中有标准选项。

  • */

public class Demo6 {

public static void main(String[] args) throws IOException {

FileChannel inchannel = FileChannel.open(Paths.get("123.jpg"), StandardOpenOption.READ);

FileChannel outchannel = FileChannel.open(Paths.get("456.jpg"), StandardOpenOption.READ,StandardOpenOption.WRITE, StandardOpenOption.CREATE);

//内存映射方式。

MappedByteBuffer inmap = inchannel.map(FileChannel.MapMode.READ_ONLY, 0, inchannel.size());

MappedByteBuffer outmap = outchannel.map(FileChannel.MapMode.READ_WRITE, 0, inchannel.size());

//读写

byte[] bys = new byte[inmap.limit()];

inmap.get(bys);

outmap.put(bys);

inchannel.close(); outchannel.close();

}

}

package com.momo.demo;

import java.io.IOException;

import java.nio.channels.FileChannel;

import java.nio.file.Paths;

import java.nio.file.StandardOpenOption;

/*

long transferFrom(ReadableByteChannel src, long position, long count)

从给定的可读字节通道将字节传输到该通道的文件中。

long transferTo(long position, long count, WritableByteChannel target)

将该通道文件的字节传输到给定的可写字节通道。

  • */

public class Demo7 {

public static void main(String[] args) throws IOException {

FileChannel inchannel = FileChannel.open(Paths.get("123.mp3"), StandardOpenOption.READ);

FileChannel outchannel = FileChannel.open(Paths.get("456.mp3"), StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE);

// outchannel.transferFrom(inchannel,0,inchannel.size()); inchannel.transferTo(0,inchannel.size(),outchannel); inchannel.close(); outchannel.close();

}

}

三,分散读取和聚集写入

1,分散读取(Scattering Reads):

是指从 Channel 中读取的数据“分散”到多个 Buffer 中。

2,聚集写入(Gathering Writes)

是指将多个 Buffer 中的数据“聚集”到 Channel。

package com.momo.demo;

import org.junit.Test;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.RandomAccessFile;

import java.nio.ByteBuffer;

import java.nio.channels.FileChannel;

import java.nio.file.Paths;

import java.nio.file.StandardOpenOption;

/*

  • 分散读取和聚集写入
  • */

public class Demo8 {

//分散读取

@Test

public void test1() throws IOException {

RandomAccessFile raf = new RandomAccessFile("a.txt","rw");

FileChannel channel = raf.getChannel();

// FileChannel channel = FileChannel.open(Paths.get("a.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE); ByteBuffer buf1 = ByteBuffer.allocate(3); ByteBuffer buf2 = ByteBuffer.allocate(3); ByteBuffer buf3 = ByteBuffer.allocate(10); ByteBuffer[] bus = {buf1,buf2,buf3}; channel.read(bus); for (ByteBuffer bb : bus) { bb.flip(); System.out.println(new String(bb.array(),0,bb.limit())); } System.out.println("--------------------------------"); //聚集写入 RandomAccessFile raf2 = new RandomAccessFile("b.txt","rw"); FileChannel channel2 = raf2.getChannel(); channel2.write(bus);

}

}

举报

相关推荐

0 条评论