输入输出流

File

java.io.File类:文件和文件目录路径的抽象表示形式,和平台无关

File可以对文件或者目录实现增删重命名。但是File不可以访问文件或者目录内容,如果要访问内容,则需要使用输入输出流

构造器:

image-20211001212616904

路径编写分隔符的问题:

image-20211001212934696

File常用方法
获取功能:

image-20211001213338588

getPath是获取你在构造器中填写的那个路径,getAbsolutePath是获取绝对路径。

重命名功能:

image-20211001220609288

file1.renameTo(file2)

要想保证成功,就要使file1在硬盘中存在,file2在硬盘中是不存在的。

相当于实现了一个另存为的功能。

判断功能:

image-20211001221213829

创建功能:

image-20211001221328526

删除功能:

image-20211001221413147

当一个File创建的时候,如果这个路径下真的存在文件或者目录,那么这个File对象的属性是被显示赋值的。如果没有就会使用默认值。

IO流(input和output)

用于处理设备之间的数据传输(输入输出是相当于程序,不是文件)

java中对于数据的输入和输出都是使用的”流(stream)“的形式进行

流的分类:

按照操作数据单位的不同:字节流(8bit) 字符流(16bit)

按照数据流的方向不同:输入流 输出流

按照数据流的角色不同分为:节点流 处理流

image-20211001222124138

节点流和处理流:节点流就是说直接进行数据操作的流,他操作的对象是数据,处理流操作的对象是节点流。

IO流体系

image-20211001222707018

节点流为FileInputStream FileOutputStream FileReader FileWriter

其他的为处理流。

字符输入流:

虽然不知道具体的原因,但是字符流,每次都是操作一个字符,无论是中文还是英文。

@Test
public void test03()  {
    File file=new File("C:\\Users\\26779\\Desktop\\temp.txt");
    FileReader fileReader=null;
    try{
        fileReader=new FileReader(file);
        int data=-1;
        while((data=fileReader.read())!=-1){
            if(data=='\r'||data=='\n')
                continue;
            System.out.print((char)data);
        }
    }
    catch (Exception e){
        e.printStackTrace();
    }
    finally {
        try {
            if(fileReader!=null){
                fileReader.close();
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }

    }
}
换行是'\r''\n'或者只是一个'\n'
public void test04(){
    File file=new File("C:\\Users\\26779\\Desktop\\temp.txt");
    FileReader fileReader=null;
    int len=-1;
    try {
        fileReader=new FileReader(file);
        char[] buf=new char[5];
        while((len=fileReader.read(buf))!=-1){
          /*  for(int i=0;i<len;i++){
                System.out.print(buf[i]);
            }*/
            String str=new String(buf,0,len);
            System.out.print(str);
        }
    }
    catch (Exception e){
        e.printStackTrace();
    }
    finally {
        try {
            if(fileReader!=null){
                fileReader.close();
            }
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}
字符输出流
@Test
public void test05(){
    File file=new File("C:\\Users\\26779\\Desktop\\temp.txt");
    FileWriter fileWriter=null;
    try {
        fileWriter=new FileWriter(file,true);
        fileWriter.write("我是一个人",0,2);
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try{
            if(fileWriter!=null){
                fileWriter.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
我们是不可以通过字符流实现图片等字节文件的处理。
字节输入流:
字节输出流:
public void test06(){
    File file1=new File("C:\\Users\\26779\\Desktop\\1111.png");
    File file2=new File("C:\\Users\\26779\\Desktop\\2222.png");
    FileInputStream fileInputStream=null;
    FileOutputStream fileOutputStream=null;
    try{
        fileInputStream=new FileInputStream(file1);
        fileOutputStream=new FileOutputStream(file2,false);
        byte[] bytes=new byte[10];
        int len=-1;
        while((len=fileInputStream.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,len);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try{
            if(fileInputStream!=null){
                fileInputStream.close();
            }
            if(fileOutputStream!=null){
                fileOutputStream.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
缓冲流(提高文件的读写效率)

先关闭外层流再关闭内层流。(其实关闭外层流的时候内层流也会关闭)

缓冲流有一个readline()函数,每次读取一行

package com.geng;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileTest {
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("C:\\Users\\26779\\Desktop\\autoQQ.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str = null;
while((str = bufferedReader.readLine()) != null) {
if(str.equals("")){
continue;
}
System.out.println(str);
}
inputStream.close();
bufferedReader.close();
}
}

public void test07(){
    File file1=new File("C:\\Users\\26779\\Desktop\\1111.png");
    File file2=new File("C:\\Users\\26779\\Desktop\\2222.png");
    FileInputStream fileInputStream=null;
    FileOutputStream fileOutputStream=null;
    BufferedInputStream bufferedInputStream=null;
    BufferedOutputStream bufferedOutputStream=null;
    try{
        fileInputStream=new FileInputStream(file1);
        fileOutputStream=new FileOutputStream(file2,false);
        bufferedInputStream=new BufferedInputStream(fileInputStream);
        bufferedOutputStream=new BufferedOutputStream(fileOutputStream);
        byte[] bytes=new byte[10];
        int len=-1;
        while((len=bufferedInputStream.read(bytes))!=-1){
            bufferedOutputStream.write(bytes,0,len);
            //bufferedOutputStream.flush();
            //刷新缓冲区
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try{
            if(bufferedInputStream!=null){
                bufferedInputStream.close();
            }
            if(bufferedOutputStream!=null){
                bufferedOutputStream.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

传统的io操作是存在堵塞的,当你进行读的时候,你的写是停止的,缓冲流是在内存中开辟一个空间,存放读写的数据,这样减少了堵塞的时间,所以看起来更加高效(是一种空间换时间的操作)

转换流(实现字符流和字节流之间的转换)

image-20211002165145717

public void test09(){
    File file1=new File("C:\\Users\\26779\\Desktop\\autoQQ.txt");
    File file2=new File("C:\\Users\\26779\\Desktop\\temp.txt");
    FileInputStream fileInputStream=null;
    FileOutputStream fileOutputStream=null;
    InputStreamReader inputStreamReader=null;
    OutputStreamWriter outputStreamWriter=null;
    try{
        fileInputStream=new FileInputStream(file1);
        fileOutputStream=new FileOutputStream(file2,false);
        inputStreamReader=new InputStreamReader(fileInputStream,"utf-8");
        outputStreamWriter=new OutputStreamWriter(fileOutputStream,"gbk");
        char[] buff=new char[5];
        int len=-1;
        while((len=inputStreamReader.read(buff))!=-1){
            outputStreamWriter.write(buff,0,len);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try{
            if(outputStreamWriter!=null){
                outputStreamWriter.close();
            }
            if(inputStreamReader!=null){
                inputStreamReader.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

编码字符集:

在Java(其中主要包括在JVM中、内存中、在代码里声明的每一个char、String类型的变量中。)中字符只以一种形式存在,那就是Unicode,不选择任何特定的编码,直接使用它们在字符集中的编号,这是统一的唯一的方法。
在JVM内部,统一使用Unicode表示,当着字符从JVM内部移动到外部时(即保存为文件系统中的一个文件内容时),就进行了编码转换,使用了具体的编码方案。因此也可以说,所有的编码转换只发生在边界的地方,也就是各种输入/输出流的起作用的地方。

(6条消息) Java中弄懂Unicode和UTF-8编码方式_诚-CSDN博客_java unicode

标准输入输出流

System.in:标准的输入流,默认从键盘输入

System.out:标准的输出流,默认从控制台输出

image-20211002172332628

public static void main(String[] args){
    InputStreamReader inputStreamReader=null;
    BufferedReader bufferedReader=null;
    try {
        inputStreamReader=new InputStreamReader(System.in);
        bufferedReader=new BufferedReader(inputStreamReader);
        while(true){
            System.out.println("请输入:");
            String str=bufferedReader.readLine();
            if("exit".equalsIgnoreCase(str)){
                break;
            }
            System.out.println(str);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try {
            if(bufferedReader!=null){
                bufferedReader.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
打印流

image-20211002174538079

public static void main(String[] args){
    InputStreamReader inputStreamReader=null;
    BufferedReader bufferedReader=null;
    FileOutputStream fileOutputStream=null;
    PrintStream printStream=null;
    try {
        inputStreamReader=new InputStreamReader(System.in);
        bufferedReader=new BufferedReader(inputStreamReader);
        fileOutputStream=new FileOutputStream("C:\\Users\\26779\\Desktop\\temp.txt",false);
        printStream=new PrintStream(fileOutputStream,true);//开启自动刷新
        System.setOut(printStream);
        while(true){
            String str=bufferedReader.readLine();
            if("exit".equalsIgnoreCase(str)){
                break;
            }
            System.out.println(str);
        }
    }catch (Exception e){
        e.printStackTrace();
    }finally {
        try {
            if(bufferedReader!=null){
                bufferedReader.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
数据流

image-20211002180213584

对象流

用于存储和读取java的基本数据类型数据和对象的处理流

序列化:ObjectOutputStream类保存基本数据类型或者对象的机制

反序列化:ObjectInputStream类读取基本数据类型或者对象的机制

注意对象流是不可以序列化static和transient修饰的成员变量的。

对象的序列化机制:

允许把内存中的java对象转换成平台无关的二进制流,从而允许这种二进制流持久的存储在磁盘上,或通过网络将这种二进制传输到另一个网络节点。

序列化时RMI(远程方法调用)过程的参数和返回值都必须实现的机制

如果需要将某个对象支持序列化机制,我们让对象所属的类是可以被序列化的,就必须实现两个接口之一,否则会抛出NotSerializableException异常

Serializable

Externalizable

凡是实现了Serializable接口的类都有一个表示序列化版本标识符的静态常量
private static final long serialVersionUID;

这个常量会实现类的版本控制(确定是否兼容)

如果类没有显示定义这个静态常量,他的值就是java运行时根据类的内部细节生成的,也就是说如果你修改了类,可能会导致这个常量发生变化,此时如果你进行反序列化,就会报错InvalidCastException

(简单来说java的序列化机制时通过在运行时判断类的serialVersionUID来验证版本是否一致,在进行反序列化的时候,jvm会将传来的字节流的serialVersionUID和本地实体类的进行比较,如果一致才可以进行反序列化)

import org.junit.Test;
import org.junit.experimental.theories.suppliers.TestedOn;

import java.io.*;
import java.util.Scanner;

public class FileTest {
    @Test
    public void test1(){
        Store store=new Store(12,"lala","0100101");
        ObjectOutputStream objectOutputStream=null;
        try {
            objectOutputStream=new ObjectOutputStream
                    (new FileOutputStream
                            ("C:\\Users\\26779\\Desktop\\temp.txt",false)
                    );
            objectOutputStream.writeObject(store);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(objectOutputStream!=null){
                    objectOutputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }
    @Test
    public void test2(){
        ObjectInputStream objectInputStream=null;
        try {
            objectInputStream=new ObjectInputStream
                    (new FileInputStream
                            ("C:\\Users\\26779\\Desktop\\temp.txt")
                    );
            Object store=objectInputStream.readObject();
            if(store instanceof Store)
                store=(Store)store;
            System.out.println(store.toString());

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                if(objectInputStream!=null){
                    objectInputStream.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}
class Store implements Serializable{
    private int count;
    private String name;
    private String id;

    public Store(int count, String name, String id) {
        this.count = count;
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString() {
        return "Store{" +
                "count=" + count +
                ", name='" + name + '\'' +
                ", id='" + id + '\'' +
                '}';
    }
}
其实我们除了保证类是可以进行序列化的,我们也要保证类中的所有属性都是可以进行序列化的
任意存取文件流RandomAccessFile(不是继承于四个基本抽象类而是直接继承自Object)

image-20211002193925534

image-20211002194154533

rw模式下数据不会立即写入到磁盘中,而rwd数据会立即写入到磁盘中。也就是说如果写的过程中,如果出现异常,rwd会保存当前进度,rw会丢失。

任意存取文件流在写入的时候,如果不指定指针位置,是在开始位置,然后进行覆盖(这个覆盖其实是一个个字符进行覆盖)

这个类是可以实现一个多线程断点下载的功能,其实我们在下载文件的时候,都会建立两个临时文件,一个是和被下载文件大小相同的空文件,另一个是记录指针的位置文件,每次下载暂停的时候我们都会从上一次的地方接着下载。

Java NIO

从jdk1.4版本开始引入的一套新的IO API,NIO是支持面向缓冲区的(IO是面向流的)基于通道的IO操作。NIO将以更加高效的方式进行文件读写操作

JAVA API提供了两套NIO,一套是针对标准的输入出输出NIO,一套是网络编程NIO

NIO2

image-20211002230659670

Path 、Paths和Files

image-20211002230822716

image-20211002231037774

image-20211002230956724

image-20211002231058645

关于IO apache提供了很多官方api,在org.apache.commons.io这个包内

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;

public class FileUtilsTest {
    public static void main(String[] args) throws IOException {
        File file1=new File("C:\\Users\\26779\\Desktop\\老婆.jpg");
        File file2=new File("C:\\Users\\26779\\Desktop\\2121.jpg");
        FileUtils.copyFile(file1,file2);
    }

}

posted on 2021-10-08 19:18  gyp666  阅读(77)  评论(0)    收藏  举报