I/O流
I 是 input 输入, O 是output输出。
BIO
输入输出
CPU有输入输出、内存有输入输出、硬盘输入输出、网卡有输入输出…
每一个硬件都是以自己为基准。
JVM是一个程序,程序又都运行于内存之上。
文件操作
Java中需要使用 File 类来进行文件的CURD操作。
File file = new File(文件地址);
创建文件
public static void create() throws IOException {
File file = new File(地址);
file.createNewFile();
}
删除文件
public static void del() {
File file = new File(文件地址);
file.delete();
}
获取文件夹下的文件
public void show() {
File files =new File("C:\\Users\\xing\\Desktop\\210901班级事宜");
for(File file : files.listFiles()) {
System.out.println("file:"+file.getName());
}
}
输入字节流
第一步
打开一个文件。
File file_read =new File(地址);
第二步
把文件的内容输入到内存。
InputStream fileInputStream = new FileInputStream(file_read);
第三步
构建一个数组,准备使用这个数据获取输入流中的信息。
byte bytes[] = new byte[(int) file_read.length()];//拿到文件的长度并且建立一个字符串
第四步
使用刚才准备的数组获取输入流的数据。
fileInputStream.read(bytes);//使用刚才的字节组获取文件内容
第五步
输出到控制台。
String str =new String(bytes);//把字符组转换成String
System.out.println(str);
第六步
关闭。
fileInputStream.close();
案例
public void show1() throws Exception{
File file = new File("C:\\Users\\0924\\wenben.txt");
FileInputStream fileInputStream = new FileInputStream(file);
byte bytes[] = new byte[(int) file.length()];
fileInputStream.read(bytes);
String str =new String(bytes);//把字符组转换成String
System.out.println(str);
fileInputStream.close();
}
输出字节流
第一步
打开一个文件。
File file = new File("C:\\Users\\xing\\0924\\wenben.txt");
第二步
创建一个输出流,输出至刚才的文件。
FileOutputStream fileOutputStream = new FileOutputStream(file);
第三步
输出内容至文件。
String str = "输出这么一句话!";
fileOutputStream.write(str.getBytes());
第四步
关闭
fileOutputStream.close();
System.out.println("输出完毕!");
案例
public void show5() throws Exception{
File file = new File("C:\\Users\\xing\\0924\\wenben.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file);
String str = "输出这么一句话!";
fileOutputStream.write(str.getBytes());
fileOutputStream.close();
System.out.println("输出完毕!");
}
拷贝文件
第一步
下载一个图片存在一个文件夹。
第二步
创建一个File,使用这个 File 去读取存放的文件。
File file = new File("文件存放地址");
第三步
获取文件的字节输入流。
InputStream fileInputStream = new FileInputStream(file);
第四步
创建一个数组使用数组获取数据流的内容。
byte bytes[] = new byte[1024];
fileInputStream.read(bytes);
第五步
创建一个新的空的文件。
File file_write =new File(具体文件地址和名字);
注:同一个文件夹下不能有同名的文件
第六步
创建一个输出流,并且准备把刚才读取的数据输出出去。
OutputStream outputStream = new FileOutputStream(file_write);//
outputStream.write(bytes);//使用刚才已经有内容的字节组输出
第七步
关闭
outputStream.close();
fileInputStream.close();
注:先开后关
字符流
字符流操作与字节流类似。把字节的操作换成字符的类即可,流程步骤都是字节流的操作步骤。
public static void main(String[] args) throws Exception {
InputStream inpu;
char ch[] = new char[1024];
Reader reader = new FileReader("C:\\Users\\0924\\wenjian");
reader.read(ch);
Writer writer =new FileWriter("C:\\Users\\0924\\wenjian0");
writer.write(ch);
writer.close();
reader.close();
}
基本缓冲操作
基础
BufferedReader 是输入缓冲字符流。
BufferedInputStream 是输入缓冲字节流。
BufferedWriter 是输出缓冲字符流。
BufferedOutputStream 是输出缓冲字节流。
需要把对应的输入\输出流放到缓冲的构造方法中:
BufferedReader br = new BufferedReader(reader);
案例
/**
* @time: 2021年9月26日上午9:59:30
* @auth: xing
* @return:void
* @description:读取缓冲
*/
public static void main(String[] args) throws Exception {
Reader reader = new FileReader("C:\\Users\\0924\\wenjian");
BufferedReader br = new BufferedReader(reader);
String str = br.readLine();
System.out.println(str);
str = br.readLine();
System.out.println(str);
br.close();
reader.close();
//InputStream fileInputStream = new FileInputStream("C:\\Users\0924\\wenjian");
//BufferedInputStream bi = new BufferedInputStream(fileInputStream);
}
NIO
概念
NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性:
- NIO是基于块(Block)的,它以块为基本单位处理数据 (硬盘上存储的单位也是按Block来存储,这样性能上比基于流的方式要好一些)
- 为所有的原始类型提供(Buffer)缓存支持
- 增加通道(Channel)对象,作为新的原始 I/O 抽象
- 支持锁(我们在平时使用时经常能看到会出现一些.lock的文件,这说明有线程正在使用这把锁,当线程释放锁时,会把这个文件删除掉,这样其他线程才能继续拿到这把锁)和内存映射文件的文件访问接口
- 提供了基于Selector的异步网络I/O
操作
-
得到Channel(管道) -
申请Buffer(缓存空间) -
建立Channel和Buffer的读/写关系 -
关闭
管道案例
使用50MB内存操作5G的文件。
public static void main(String[] args) throws Exception {
FileInputStream fin = new FileInputStream("D:\\迅雷下载\\shipin.mkv");
FileChannel fch = fin.getChannel();
FileOutputStream fou = new FileOutputStream("C:\\Users\\xing\\Desktop\\222.mkv");
FileChannel foh =fou.getChannel();
ByteBuffer bf = ByteBuffer.allocateDirect(102400);
int i = 0;
while(true) {
bf.clear();
int r = fch.read(bf);
bf.flip();
if(r<0) {
break;
}
foh.write(bf);
Thread.sleep(1000);
System.out.println("第:"+(++i));
}
fou.close();
fin.close();
}
缓存的三个标识
public static void main(String[] args) throws Exception {
//读取文件
FileInputStream fin = new FileInputStream("C:\\Users\\xing\\Desktop\\新建文本文档.txt");
//创建通道
FileChannel fch = fin.getChannel();
//创建一个容器10个长度
ByteBuffer bf = ByteBuffer.allocate(10);
output( "1", bf);
//读取
fch.read(bf);
output( "2", bf);
//开始
bf.flip();
output( "3", bf);
//判断是否还有数据可以读取
System.out.println("b:"+new String(bf.array()));
output("4",bf);
//清空
bf.clear();
output("5",bf);
//关闭
fin.close();
}
AIO
AIO的特点:
-
读完了再通知我 -
不会加快IO,只是在读完后进行通知 -
使用回调函数,进行业务处理
AIO的相关代码:
AsynchronousServerSocketChannel
server = AsynchronousServerSocketChannel.open().bind( new InetSocketAddress (PORT)); 使用server上的accept方法
server.accept(null,
new CompletionHandler<AsynchronousSocketChannel, Object>() {
final ByteBuffer buffer = ByteBuffer.allocate(1024);
public void completed(AsynchronousSocketChannel result,
Object attachment) {
System.out.println(Thread.currentThread().getName());
Future<Integer> writeResult = null;
try {
buffer.clear();
result.read(buffer).get(100, TimeUnit.SECONDS);
buffer.flip();
writeResult = result.write(buffer);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} finally {
try {
server.accept(null, this);
writeResult.get();
result.close();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
@Override
public void failed(Throwable exc, Object attachment) {
System.out.println("failed: " + exc);
}
});
补充
注:由于LINUX对AIO的支持不好,所以AIO的使用并不多,大多数使用AIO的情况都是被Netty所替代。
|