10、IO流

11、IO流

File类

  • File类的一个对象,代表一个文件或一个文件目录(文件夹);(用于io流中 内存 <-->目标对象)
  • File类声明在java.io包下;
  • File类中只涉及到文件的创建,删除,修改等方法,并未涉及 写入/读取文件操作 -->IO流
  • File类的对象常会作为参数 传递到流的构造器中,指明 读取/写入 的"终点"

 创建File类实例:

File(String filePath) //完整路径(目录/文件)
File(String parentPaht , String childPath) // 目录 + 子文件夹/文件
File(File parentFile , String childPath) //File目录 + 文件

 路径

相对路径:当前 Project 或 当前 Module (非main())

绝对路径(包含盘符在内的路径)。

路径分隔符:
 windows系统下: \ \ d:\\wang\\info.txt
 UNIX和URL: / d:/wang
 Java通用常量: separator "d:" + File.separator + "wang" + File.separator + "infotxt"

 常用方法:

File类 的获取功能:
​  public String getAbsolutePath():获取绝对路径
​  public String getPath() :获取路径
​  public String getName() :获取名称
​  public String getParent():获取上层文件目录路径。若无,返回null
​  public long length() :获取文件长度(即:字节数)。不能获取目录的长度。
​  public long lastModified() :获取最后一次的修改时间,毫秒值

​ 适用于文件目录:
​  public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组
​  public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组

​ File 类的重命名功能:
​  public boolean renameTo(File dest):把文件重命名为指定的文件路径

file1 = new File("hello.txt"); 
file2 = new File("D//wang//hi.txt"); //把f1移动到f2目录下并改名为hi.txt
finle1.renameTo(file2); //file1必须存在硬盘,file2必须不存在硬盘

File 类的判断功能:
 public boolean isDirectory():判断是否是文件目录
 public boolean isFile() :判断是否是文件
 public boolean exists() :判断是否存在
 public boolean canRead() :判断是否可读
 public boolean canWrite() :判断是否可写
 public boolean isHidden() :判断是否隐藏

创建文件
​  public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
​  public boolean mkdir() :创建文件目录。如果此文件目录的上层目录不存在,也不创建
​  public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建

删除文件
​  public boolean delete():删除文件或者文件夹 (删除目录时必须保证目录为空;不会进入回收站)

IO流

流的分类:

 按操作 数据单位不同分为:字节流(8 bit) ,字符流(16 bit)
 按数据流的 流向不同分为: 输入流,输出流
 按流的 角色的不同分为: 节点流处理流 (套管子,作用在节点流上)

流的体系结构:

抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputSteam Writer

节点流(文件流):

节点流 FileInputStream FileOutputStream FileReader FileWriter

处理流:

​ 缓冲流,转换流,对象流; 其他(打印流, 输入输出流, 特殊流)

image-20220405152658420

节点(文件)流

基本操作步骤:

  1. File类 实例化 【可以省略】
  2. 流的实例化
  3. 读入/写入 操作
  4. 关闭资源

字符流与字节流:

对于文本文件,使用字符流处理 (txt, java, c , cpp)

对于非文本文件 ,使用字节流处理 (jpg, mp3, mp4, avi, doc, ppt )

字符流 :(未进行异常处理)

public void reader(){
    //1.创建File对象,指明要读入的文件(不能为空)
    File f1 = new File("D:\\w.txt");
    //2.创建 流对象
    FileReader fr = new FileReader(f1);
    //3.读入操作
    int len; //fr.read() 默认读取方式,每次读取一个字符(int形式),若读取为空返回-1
    char[] arr = new char[5]; //读取多个字符
    while( (len=fr.read(arr)!=-1 ) {
        //注意遍历arr时以len为基准-->实际读取到的是前len个数据
        for (int i = 0; i < len; i++) {     
            System.out.print(arr[i]);
        }
        //方式二:
        String str = new String(arr,0,len);
        sout(srt);
    }
    //4.关闭流
    fr.close(); 
}
public void writer(){
    //1.创建File对象,指明要写出的文件(若不存在,会自动创建)
    File f2 = new File("D:\\w.txt"); 
    //2.创建 流对象
    FileWriter fw = new FileWriter(f2,true); //默认fales 覆盖写入
    //3.写出操作
    fw.write("啦啦啦啦啦");
    //4.关闭流
    fw.close();
}        

字节流:(在写出时可以通过 异或运算进行加密解密操作

//实现文件赋值
public void copyFile(String srcPath,String destPath){
    FileInputStream fis = null;
    FileOutputStream fos = null;
    try{
        //1.创建File对象
        File srcFile = new File(srcPath);
        File destFile = new File(destPath);
        //2.创建流对象
        fis = new FileInputStream(srcFile);
        fos = new FileOutputStream(destPath,true);
        //3.读取,写出操作
        byte[] buffer = new byte[1024]; //字节数组容器读取字节流
        int len;
        while ( (len=fis.read(buffer))!=-1 ){  //读入字节流
            fos.write(buffer,0,len);       //字节流写出
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        //4.关闭流
        try {
            if (fos!=null)
                fos.close();
            if (fis!=null)
                fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

处理流

作用与节点流之上的流

缓冲流:Buffered

  • 提高 流的读取,写入速度

    (内部提供了一个缓冲区,先读取到缓冲区,再把缓冲区数据全部写出)

  • .fulsh() 刷新缓冲区 提前将缓冲区的内容全部写入输出流

  • BuffereReader类新增 .readLine(), .newLine()方法,可以一次读取一行(不自动换行)

    //文件流
    FileInputStream fis = null;
    FileOutputStream fos = null;
    //处理流
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    //1.创建File对象,创建流对象
    fis = new FileInputStream(new File(srcPath));
    fos = new FileOutputStream(new File(destPath));
    bis = new BufferedInputStream(fis); //套管子--缓冲流
    bos = new BufferedOutputStream(fos);
    //2.读入,写出操作
    byte[] buffer = new byte[1024];
    int len;
    while ( (len=bis.read(buffer))!=-1){  //读入byte数组
        bos.write(buffer,0,len);      //从byte数组中写出
    }
    //4.关闭资源
    if (bis!=null)  //在关(外层)处理流时,底层的文件流会自动关闭
        bis.close();
    if (bos!=null)
        bos.close();
    

转换流:

  • 作用:提供 字节流与字符流之间的转换

  • 属于字符流对象:

    • InputStreamReader:将 字节输入流 转化为 字符输入流 --- 解码
    • OutputSreamWriter:将 字符输出流 转化为 字节输出流 --- 编码
    //1.造文件,造流
    File f1 = new File("utf8.txt");
    File f2 = new File("gbk.txt");
    FileInputStream fis = new FileInputStream(f1);
    FileOutputStream fos = new FileOutputStream(f2);
    InputStreamReader isr = new InputStreamReader(fis,"utf-8");//转换流--编码
    OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");//转换流---解码
    //2.读入,写出操作
    char[] cbuffer = new char[20];
    int len;
    while ( (len=isr.read(cbuffer))!=-1 ){ //读
        osw.write(cbuffer,0,len); 		   //写
    }
    //3.关闭资源
    osw.close();
    isr.close();
    

字符编码

计算机识别的二进制字节 与 文字数字 一一对应 ---》 编码表

 常见的编码表
ASCII:美国标准信息交换码。 用一个字节的7位可以表示。
 ISO8859-1:拉丁码表。欧洲码表。用一个字节的8位表示。
 GB2312:中国的中文编码表。最多两个字节编码所有字符
GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。(Unicode并不能用来实现编码,无法让计算机识别是 1个字节还是2个字节)
UTF-8变长编码方式,可用1-4个字节来表示一个字符

image-20220405204144107

对象流

  • 用于存储和读取 基本数据类型数据 或 对象 的处理流。可以将Java中的对象写入,读出数据源

  • 属于 字节流对象:

    • 序列化:ObjectOutputSream类 writeObject 对象/基本类型数据---> 二进制(字节)流

    • 反序列化:ObjectInputSream类 readObject 二进制流--->对象/基本类型数据;

  • ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

 序列化对象的要求

1.实现Serializable接口 --(标识接口)

2.提供一个全局常量 serialVersionUID -- (序列化版本号, 唯一标识序列化对象)
 若未显示定义此UID,Java在序列化时会根据类自动生成一个UID;
 但如果之后类发生修改,自动生成的UID也会变化,使得反序列化时,找不到该序列化对象

3.序列化对象类内部中的所有属性也必须是可序列化的 (即也实现了Serializeble接口)

class Person implements Serializable{
    //提供全局常量
    public static final long serialVersionUID = 5615656L;
    //类中的所有属性也必须可序列化
    int age; 		//基本数据类型 默认可序列化
    Dog gog; 		//自定义类,也需要实现序列化接口+serialVersionUID
}

对象序列化机制

允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。

代码操作:

//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“data.txt"));
Person p = new Person("韩梅梅", 18, "中华大街", new Pet());
oos.writeObject(p);
oos.flush();
oos.close()
//反序列化                                                                     
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“data.txt"));
Person p1 = (Person)ois.readObject();
System.out.println(p1.toString());
ois.close();

其他流(了解):

标准输入、输出流

 System.in:标准输入流,默认从键盘输入
 System.out:标准输出流,默认从控制台输出

System类的 setIn(InputStream is) / setOut(PrintStream ps) 方式重新指定输入和输出的流

System.out.println("请输入信息(退出输入e或exit):");
// 把"标准"输入流(键盘输入)这个字节流包装成字符流,再包装成缓冲流
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s = null;
while ((s = br.readLine()) != null) { // 读取用户输入的一行数据 --> 阻塞程序
    if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)) {
        System.out.println("安全退出!!");
        break;
    }
    // 将读取到的整行字符串转成大写输出
    System.out.println("-->:" + s.toUpperCase());
    System.out.println("继续输入信息");
}
br.close(); // 关闭过滤流时,会自动关闭它包装的底层节点流

打印流

PrintStream 和 PrintWriter

 提供了一系列重载的print()和println()方法,用于多种数据类型的输出

 实现将 基本数据类型的数据格式转化为 字符串输出

数据流

DataInputStream 和 DataOutputStream

 用于 读取,写入 基本数据类型的变量或字符串

//写入
DataOutputSream dos = new DataOutputStream(new FileOutputSream("date.dat"));
dos.writeUTF("我爱北京天安门");	// 写UTF字符串
dis.flush(); //刷新操作,将内存中的数据写入文件
dos.writeBoolean(false); 		 // 写入布尔值
dis.flush(); 
dos.writeLong(1234567890L); 	 // 写入长整数
dis.flush(); 
dos.close();

//读取(读取不同类型的数据时, 顺序必须与 写入时一致)
DataInputSream dis = new DataInputStream(new FileInputStream("data.dat"));
String info = dis.readUTF();
boolean flag = dis.readBoolean();
long time = dis.readLong();
dis.close();

随机存取文件流

  • RandomAccessFile 类 直接继承于java.lang.Object类。实现了DataInput、DataOutput接口,也就意味着这个类 既可以读(输入流)也可以写(输出流)
  • RandomAccessFile作为输出流时,若写出的文件不存在 则 自动创建;若存在 则对原有文件内容(默认从头开始)进行覆盖
  • RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置。且可以自由移动记录指针:
     long getFilePointer():获取文件记录指针的当前位置
     void seek(long pos):将文件记录指针定位到 pos 位置
  • 实例化:new RandomAccessFile(File file, String mode),mode参数指定访问模式:
    r: 以只读方式打开
    rw :打开以便读取和写入
     rwd: 打开以便读取和 写入;同步文件内容的更新
     rws: 打开以便读取和 写入;
//实现文件的文本插入功能
public void t6() throws Exception { 
    //1.创建流对象
    RandomAccessFile raf = new RandomAccessFile("utf8.txt","rw");
    //2.读写操作
    raf.seek(3); //移动文件指针,从第4个位置开始覆盖写入
    	//a.将指针3后面的数据保存到 bao中
    ByteArrayOutputStream bao = new ByteArrayOutputStream();
    byte[] buffer = new byte[20];
    int len;
    while ( (len=raf.read(buffer))!=-1){
        bao.write(buffer,0,len);
    }//此时指针已经指向末尾了
    	//b.指针重新指向 指针3位置
    raf.seek(3);
    raf.write("呜呜".getBytes()); //插入数据
    	//c.写回后面保存的数据
    raf.write(bao.toByteArray());
    //3.关闭资源
    raf.close();
    bao.close();
}

文件多线程断点下载功能:

我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立 两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。

Java NIO

Java NIO 概述

 Java NIO (New IO,Non-Blocking IO)是从Java 1.4版本开始引入的一套新的IO API,可以替代标准的Java IO API。NIO与原来的IO有同样的作用和目的,但是使用的方式完全不同,NIO支持面向缓冲区的(IO是面向流的)、基于通道的IO操作。NIO将以更加高效的方式进行文件的读写操作

 Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO。
|-----java.nio.channels.Channel
|-----FileChannel:处理本地文件
|-----SocketChannel:TCP网络编程的客户端的Channel
|-----ServerSocketChannel:TCP网络编程的服务器端的Channel
|-----DatagramChannel:UDP网络编程中发送端和接收端的Channel

JDK1.7发布 NIO.2

原本的 java.io.File 升级未 java.nio.file包 :Path,Files,Paths核心API

Path可以看成是File类的升级版本,实际引用的资源也可以不存在。还提供了Files、Paths工具类

Path接口

Path 常用方法:
 String toString() : 返回调用 Path 对象的字符串表示形式
 boolean startsWith(String path) : 判断是否以 path 路径开始
 boolean endsWith(String path) : 判断是否以 path 路径结束
 boolean isAbsolute() : 判断是否是绝对路径
 Path getParent() :返回Path对象包含整个路径,不包含 Path 对象指定的文件路径
 Path getRoot() :返回调用 Path 对象的根路径
 Path getFileName() : 返回与调用 Path 对象关联的文件名
 int getNameCount() : 返回Path 根目录后面元素的数量
 Path getName(int idx) : 返回指定索引位置 idx 的路径名称
 Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
 Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象
 File toFile(): 将Path转化为File类的对象

Files类

java.nio.file.Files 用于操作文件或目录的工具类。
Files 常用方法:
 Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
 Path createDirectory(Path path, FileAttribute … attr) : 创建一个目录  Path createFile(Path path, FileAttribute … arr) : 创建一个文件
 void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错
 void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除
 Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置
 long size(Path path) : 返回 path 指定文件的大小

Files 常用方法:用于判断
 boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
 boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
 boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件
 boolean isHidden(Path path) : 判断是否是隐藏文件
 boolean isReadable(Path path) : 判断文件是否可读
 boolean isWritable(Path path) : 判断文件是否可写
 boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
Files 常用方法:用于操作内容
 SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接, how 指定打开方式。
 DirectoryStream newDirectoryStream(Path path) : 打开 path 指定的目录
 InputStream newInputStream(Path path, OpenOption…how):获取 InputStream 对象
 OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象

posted @ 2022-04-11 21:18  simp1e1  阅读(50)  评论(0)    收藏  举报