看看Java里面的IO
IO流
intput:输入流,从网络种读取文件到内存,磁盘里面读取文件到内存。
output:输出流,从内存里面读取文件显示在网络上面,内存的数据写到文件上面。
字节流
以byte为最小单位。
intputStream 输入字节流
outputStream 输出字节流
字符流
以char字符的方式去读写
如果文件是以文本的方式存在,用字符流方便
reader 读
writer 写
同步&异步
IO同步
这个CPU在等待现在正在进行的IO,必须等现在进行的IO执行完毕了。在去执行下一个IO。
IO操作的时候,必须等待数据返回!才能执行下面的代码。
IO异步
IO操作的时候,不需要等待数据返回!就可以执行下面的代码
在java.io里面都是同步IO
在java.nio里面都是异步IO
File 文件对象
package com.hu.io_; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; public class FileDome { public static void main(String[] args) throws IOException{ /* * 创建一个file里面可以放入绝对路径和相对路径 * 绝对路径:以根目录为开头的例如:C:\\a\\a.txt * 相对路径:取出掉绝对路径的目录就是相当路径例如:a\\a.txt * * File:有三种表示路径的方式 * file.getPath(): 返回构造器里面的路径 * file.getAbsolutePath(): 返回绝对路径 * file.getCanonicalPath(): 返回规范路径 *规范路径就是:把.和.. 当前级和返回上一级给表现出来。 * * File是一个文件对象,他也可以表示一个目录对象。 * isFile() 判断是否是一个文件 * isDirectory() 判断是否是一个目录 * 用File对象获取到一个文件时,还可以进一步判断文件的权限和大小: boolean canRead():是否可读; boolean canWrite():是否可写; boolean canExecute():是否可执行; long length():文件字节大小。 创建和删除文件: file.createNewFile(); file.delete(); * Java里面提供了一个创建临时文件的 * File.createTempFile("tmp-", ".txt"); // 提供临时文件的前缀和后缀 deleteOnExit(); // JVM退出时自动删除 遍历文件或目录 当File对象表示一个目录时,可以使用list()和listFiles()列出目录下的文件和子目录名 File[] files = file.listFiles(); 返回当前目录下的所有文件 * File[] fs2 = file.listFiles(new FilenameFilter() { // 仅列出.exe文件 public boolean accept(File dir, String name) { return name.endsWith(".txt"); // 返回true表示接受该文件 } });返回当前目录下面的txt后缀名的文件 * 如何创建一个目录 File file = new File("C:\\ABC"); if(file.mkdirs()){ System.out.println("创建成功!"); } * 如何删除这个目录 * * */ File file = new File("C:\\ABC"); if(file.delete()){ System.out.println("cs成功!"); } // File file = new File("D:\\User\\hupenglong.UCO\\Desktop\\demoGit"); // // File[] files = file.listFiles(); // printFiles(files); // File[] fs2 = file.listFiles(new FilenameFilter() { // 仅列出.exe文件 // public boolean accept(File dir, String name) { // return name.endsWith(".txt"); // 返回true表示接受该文件 // } // }); // printFiles(fs2); // File f = File.createTempFile("abc", ".txt"); // // f.deleteOnExit(); // System.out.println(f.getAbsolutePath()); // File file = new File(".."); // System.out.println(file.getPath()); // System.out.println(file.getAbsolutePath()); // System.out.println(file.getCanonicalPath()); // File file = new File("D:\\User\\hupenglong.UCO\\Desktop\\demoGit\\wd.txt"); // System.out.println(file.isFile());//T // System.out.println(file.isDirectory());//F // File file = new File("D:\\User\\hupenglong.UCO\\Desktop\\demoGit\\wd"); // file.createNewFile(); // file.delete(); //System.out.println(File.separator); // 根据当前平台打印"\"或"/" } static void printFiles(File[] files) { System.out.println("=========="); if (files != null) { for (File f : files) { System.out.println(f); } } System.out.println("=========="); } }<di> </di>
遍历一个文件夹下面所有的文件
public void selectFile(File file){ Files[] fs = file.listFiles(); for(int i = 0; i < fs.length;i++){ if(fs[i].isDirectory()){ selectFile(fs[i]); }else{ System.out.println(fs); } } }
InputStream
InputStream是一个抽象类,是输入IO里面的基类。
这一个read方法非常重要
public abstract int read() throws IOException;
去读取数据,读数据的下一行并且返回一个【0~255】的数字,如果读带最后一行返回-1
根据以上案例如何去读一个文件
一直去读嘛,然后返回值是-1停止。记得关闭资源
Java7的引入的语法
//用try ... finally来编写上述代码会感觉比较复杂,更好的写法是利用Java 7引入的新的try(resource)的语法,只需要编写try语句,让编译器自动为我们关闭资源。推荐的写法如下: public void readFile() throws IOException { try (InputStream input = new FileInputStream("src/readme.txt")) { int n; while ((n = input.read()) != -1) { System.out.println(n); } } // 编译器在此自动为我们写入finally并调用close() } //实际上,编译器并不会特别地为InputStream加上自动关闭。编译器只看try(resource = ...)中的对象是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally语句并调用close()方法。InputStream和OutputStream都实现了这个接口,因此,都可以用在try(resource)中。
缓冲
一个一个读取太慢了。我们可以先读取一部分放在一个容器里面
就是一次性读取多个字节,InputStream里面提供两个重载的方法
- int read(byte[] b):读取若干字节并填充到byte[]数组,返回读取的字节数
- int read(byte[] b, int off, int len):指定byte[]数组的偏移量和最大填充数
阻塞
我们的是同步IO的,所以在读的时候不知道要等多久
OutputStream
是基本输出IO,他的输出差不多
public abstract void write(int b) throws IOException;
虽然是int类型的参数,不过他只写入一个字节的。
这里面有一个fluch(),和缓存差不多就是写的时候一个一个写太慢了。先写在一个容器里面在一次性写出去。
我们来实现一下文件的复制
基本原理就是读一个文件,同时去写一个文件。
package com.hu.io_; import java.io.*; public class Text3 { public static void main(String[] args) { InputStream input = null; OutputStream output = null; try{ input = new FileInputStream("D:\\User\\hupenglong.UCO\\Desktop\\t\\a.txt"); output = new FileOutputStream("D:\\User\\hupenglong.UCO\\Desktop\\t\\b.txt"); while(true){ int n = input.read(); output.write(n); if(n == -1){ break; } System.out.println(n); } }catch(IOException e){ System.out.println(e); } finally{ try { input.close(); output.close(); } catch (IOException e) { e.printStackTrace(); } } } }
Filter 模式 这就是装饰器模式
FileinputStream 如果给他添加一个缓存
FileinputStream 如果给他添加一个加密
FileinputStream 如果给他添加一个签名
我们都需要添加一个类去继承FileinputStream,这种子类太多了非常麻烦!
但是我们可以子类引用指向父类。
InputStream in = new FileInputStream("test.gz");
InputStream in = new 其他的子类,
通过少量的类,来实现工作功能组合
我们编写一个自己这对于IO流的功能的
public class Main { public static void main(String[] args) throws IOException { byte[] data = "hello, world!".getBytes("UTF-8"); try (CountInputStream input = new CountInputStream(new ByteArrayInputStream(data))) { int n; while ((n = input.read()) != -1) { System.out.println((char)n); } System.out.println("Total read " + input.getBytesRead() + " bytes"); } } } //CountInputStream,它的作用是对输入的字节进行计数: class CountInputStream extends FilterInputStream { private int count = 0; CountInputStream(InputStream in) { super(in); } public int getBytesRead() { return this.count; } public int read() throws IOException { int n = in.read(); if (n != -1) { this.count ++; } return n; } public int read(byte[] b, int off, int len) throws IOException { int n = in.read(b, off, len); if (n != -1) { this.count += n; } return n; } }
序列化
序列化,就是把Java对象变成为一个byte[] 二进制数据,然后这样就方便在网络上传输了
一个类要实现这种操作,必须实现Serializable 接口
ClassPath路径
我们在读取一个文件的时候要根据文件的路径去读,但是操作系统不同读取的文件路径就是不同的这样就很麻烦