IO 1.0

I/O流

输入流:磁盘 -----》内存;

输出流:内存 -----》磁盘;

  • 输入流:InputStream、Reader;
  • 输出流:OutputStream、Writer;

一、File

1.1、常见的文件操作

  • 创建文件对象相关构造器和方法;

    • new File(String pathname) //根据路径构建一个File对象
      new File(File parent,String child) //根据父目录文件 + 子路径构建
      new File(String parent,String child) //根据父目录 + 子路径构建
      

案例:

public class FileCreate {
    public static void main(String[] args) {
        FileCreate fileCreate = new FileCreate();
        fileCreate.createFile1();
        fileCreate.createFile2();
        fileCreate.createFile3();
    } 
    
    // 方式一、new File(String pathname)
    public void createFile1() {
        String filePath = "";
        File file = new File(filePath);
        
        // 之后搭配try-catch语句块
        file.createNewFile();
        System.out.println("文件创建成功");
        
    }
    
    // 方式二、new File(File parent,String child) 根据父目录文件 + 子路径构建
    public void createFile2() {
        File parentFile = new File("e:\\"); // 其中\\,头一个是转义字符,否则如果只有一个就不合法,检测不出来
        String fileName = "new2.txt";
        File file = new File(parentFile,fileName); //此处file对象,在java程序中,知识一个对象,尚且存在于内存中
        
        // try-catch语句块
        file.createNewFile(); // 将内存中的file写入到磁盘中
        System.out.println("文件创建成功");
    }
    
    // 方式三、new File(String parent,String child) 根据父目录 + 子目录构建,可以在父目录下创建多个子文件
    public void createFile3() {
        String parentPath = "e:\\";
        String fileName = "new3.txt";
        File file = new File(parentPath,fileName);
        
        // try-catch语句块
        file.createNewFile();
        System.out.println("文件创建成功")
    }
}

1.2、File类的方法

序号方法名描述
1getName()获取文件名
2getAbsolutePath()获取绝对路径
3getParent()获取父级目录
4length()获取文件内字节长度
5exists()判断文件是否存在
6isFile()判断文件是否是文件
7isDirectory()判断文件是否是目录
public class FileInformation{
    public static void main(String[] args) {
        
    }
}

1.3、目录操作以及文件删除

  • mkdir-----创建一级目录;
  • mkdirs—创建多级目录;
  • delete----删除空白目录或文件;

在java中,目录也被当做文件

  • 判断文件“e:\new1.txt”是否存在,如果存在就删除;
  • 判断目录“e:\demo2”是否存在,如果存在就删除;
// 删除文件
public void deleteFile01() {
    String filePath = "e:\\new1.txt";
    File file = new File(filePath);
    if(file.exists){
        if(file.delete()){
            System.out.println("文件已经删除");
        }else{
            System.out.println("文件删除失败");              
        }
    }else{
        System.out.println("文件不存在");
    }
}

//删除目录
public void deleteFile02() {
    String filePath = "e:\\demo";
    File file = new File(filePath);
    if(file.exists){
        if(file.delete()){
            System.out.println("目录已经删除");
        }else{
            System.out.println("目录删除失败");              
        }
    }else{
        System.out.println("目录不存在");
    }
}

// 创建多级目录
public void mkdirsDirectory() {
    String directoryPath = "e:\\demo\\a\\b\\c";
    File file = new File(filePath);
    if(file.exists){
       System.out.println("目录已经存在");
    }else{
		if(file.mkdirs()){ // mkdirs()创建
            System.out.println("目录创建成功");
        }else{
            System.out.println("目录创建失败");
        }
    }
}
/*
疑问:
如果只有demo一级目录,却没有a/b/c这样的子目录,会怎么样呢?
是删除demo之后,从新新建;
还是在demo目录之后,再新建子级目录呢/
*/

二、I/O

  • I/O(Input/Output),I/O技术处理数据传输,如读、写文件,网络通讯等;
  • Java程序中,对于数据的输入、输出操作以 “流(Stream)” 的方式进行
  • Java.io包下,提供各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据。

2.1、I/O原理

  • 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中;
  • 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中;

2.2、流的分类

  • 按操作数据单位不同分为:字节流(8 bit)、字符流(字符)
    • 字节流适用在二进制文件,可以无损;
    • 字符流适用于文本文件;
  • 按流向的不同分为:输入流、输出流
  • 按流的角色不同分为:节点流、处理流、包装流
抽象类字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

注意:

  • InputStream、OutputStream、Reader、Writer都是抽象类,是所有流的超类(父类);
  • 使用的都是他们的子类

2.3、流和文件的关系

三、字节流

InputStream:字节输入流常用子类:

  • FileInputStream:文件输入流;
  • BufferedInputStream:缓冲字节输入流;
  • ObjectInputStrean:对象字节输入流;

此处需要各个流之间的关系图

3.1、FileInputStream

此处应该有FileInputStream的方法表

  • read()方法,如果到达文件的末尾,则返回-1
  • 单个 字节的读取,效果较低;

实例:读取源文件,并将文件呈现出来;

public class FileInputStreamDemo {
    public static void main(String[] args){
        
    }
    
    public void readFile1() {
        String filePath = "e:\\demo.txt";
        int readDate = 0;
        
        // 创建FileInputStream 对象,用于读取文件
        // 此处应该使用try-catch语句块
        FileInputStream fileInputStream 
            = new FileInputStream(filePath);
        
        while((readDate = fileInputStream.read()) != -1) {
            System.out.println((char)readDate); //转换成char显示
        }
    }
}

使用read(byte[] b)来提高读取速度

public class FileInputStreamDemo {
    public static void main(String[] args){
        
    }
    
    public void readFile1() {
        String filePath = "e:\\demo.txt";
        int readDate = 0;
        // 字节数组
        byte[] buf = new byte[8]; //一次性读取8个字节
        FileInputStream fileInputStream = null;
        
        // 创建FileInputStream 对象,用于读取文件
        // 此处应该使用try-catch语句块
		 fileInputStream 
            = new FileInputStream(filePath);
        
        while(fileInputStream.read(buf))!= -1) {
            System.out.println((char)readDate); //转换成char显示
        }
    }
}

3.4、FileReader

此处应该有FileReader的关系流程图,继承了谁

  • FileReader和FileWriter是字符流,即按照字符来操作IO;
  • FileReader相关方法:
    • new FileReader(File/String)
    • read每次读取单个字符,返回该字符,如果到文件末尾则返回-1
    • read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾,则返回-1(数组就相当于是缓冲区);
  • 相关API:
    • new String(char[]):将char[]转换成String;
    • new String(char[],off,len):将char[]的指定部分转换成String;

实例:从读取“e:\story.txt”

public class FileReaderDemo {
    public static void main(String[] args){
        String filePath = "e:\\story.txt";
        FileReader fileReader = null;
        int data = 0;
        
        try{
            // 新建FileReader对象
            fileReader = new FileReader(filePath);
            // 读取文件
            // 使用 read()读取
			while((data = fileReader.read()) != -1){
                System.out.println((char) data);
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                if(fileReader != null){
                    fileReader.close();
                }
            }catch(){
                
            }
        }
        
    }
}

public void readFile2(){
    String filePath = "e:\\story.txt";
        FileReader fileReader = null;
        int readLen = 0;
    	char[] buf = new char[8];
        
        try{
            // 新建FileReader对象
            fileReader = new FileReader(filePath);
            // 读取文件
            // 使用 read(char[])读取,返回的是实际读取数
			while((readLen = fileReader.read(buf)) != -1){
                System.out.println(new String(buf,0,readLen));
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                if(fileReader != null){
                    fileReader.close();
                }
            }catch(){
                
            }
        }
}

3.5、FileWriter

此处应该有关系图;

  • FileWriter常用方法
    • new FileWriter(File/String):覆盖模式,相当于流的指针在首端
    • new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
    • write(int):写入单个字符;
    • write(char[]):写入指定数组;
    • write(char[],off,len):写入指定数组的指定部分;
    • write(String):写入整个字符串;
    • write(String,off,len):写入字符串的指定部分;
  • 相关API:String类:toCharArray:将String转换成char[]

注意:FileWriter使用后,必须要关闭流,close()或者刷新–flush(),否则写入不到指定的文件;

因为还在内存中,所以刷新之后,就可以将内存中数据刷新到指定文件。

public class FileWriter{
    public static void main(String[] args){
        String filePath = "e:\\note.txt";
        // 创建FileWriter对象
        FileWriter fileWriter = null;
        char[] chars = {'a','b','c'};
        
        
        try{
            fileWriter = new FileWriter(filePath); // 目前默认是覆盖模式写入
            // 写入单个字符
            fileWriter.write('H');
            // 写入字符数组
            fileWriter.write(chars);
            // 写入指定数组的指定部分
            fileWriter.write("张韬".toCharArray(),0,3);
            // 写入字符串
            fileWriter.write("你好");
            // 写入字符串的指定部分
            fileWriter.write("上海北京"0,2)// 如果数据量大,则循环写入
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            // 对于fileWriter,一定要关闭流,或者flush
            try{
                fileWriter.close()
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

疑问点:为什么这个没有覆盖,而是追加?

解释:因为都是一个对象

//close()源码

关闭文件流:等价与flush() + 关闭

四、节点流和处理流

  • 节点流可以从一个特定的数据源读写数据,如:FileReader、FileWriter;
    • 针对特定数据源:比如说针对文件;
    • 针对字符文件:FileReader、FileWriter;
    • 针对二进制文件:FileInputStream、FileOutputStream;
  • 处理流(也称为包装流),是连接在已经存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter;

节点流

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问管道PipedInputStreamPipledOutputStreamPipledReaderPipledWriter
访问字符串StringReaderStringWriter

处理流

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
转换流InputStreamReaderOutputWriter
对象流ObjectInputStreamObjectOutputStream
打印流PrintStreamPrintWriter
特殊流DataInputStreamDataOutputStream

注意:BufferedReader类中,有属性Reader,即可以封装一个节点流,而节点流可以是任意的,只要Reader子类

public class BufferedReader extends Reader {
    private Reader in;
}

4.1、节点流以及处理流区别

  • 节点流是底层流/低级流,直接和数据源相接
  • 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
  • 处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连;

处理流的功能主要体现在以下方面:

  • 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
  • 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量数据,使用更加灵活方便。

此处需要重新观看 -----节点流以及处理流的设计模式

五、处理流

  • 最常见的处理流:BufferedReader、BufferedWriter;

  • BufferedReader以及BufferedWriter属于字符流,是按照字符来读取数据的;

  • 关闭时,只需要关闭外层流即可

    • BufferedReader bufferedReader = new BufferedReader(FileReader);
      
    • 关闭外层流的时候,外层的流(包装流)会自动地将内部流(节点流)也关掉;

实例:演示BufferedReader

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String filePath = "e:\\note.txt";
        //创建BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        //读取
        String line;//按行读取,效率高
        // 当返回null,表示文件读取完毕
        while((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        
        // 关闭流
        bufferedReader.close();
        // 底层源码中,包装流会自动关掉节点流 
    }
}
  • 注意:此处应该看源码;
  • 了解Thinking in java

实例:演示BufferedWriter

public class BufferedWriterDemo {
    public static void main(String[] args) {
        String filePath = "e:\\note.txt";
        //创建BufferedWriter
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
        //写入
        bufferedWriter.write("hello,开始");
        bufferedWriter.newLine();
        bufferedWriter.write("hello2,开始");
        bufferedWriter.write("hello3,开始");
        bufferedWriter.close();
        //
    }
}
// new FileWriter(filePath,true); 表示以追加的方式写入
// new FileWriter(filePath) 表示以覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));

注意:覆盖与追加需要深究

5.2、Buffered拷贝

public class BufferedCopyDemo {
    public static void main(String[] args) {
        String srcFilePath = "e:\\note.txt";
        String destFilePath = "e:\\note2.txt";
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        String line;
        
        try{
            bufferedReader = new BufferedReader(new FileReader(srcFilePath));
            bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
            // readLine(),读取一行数据,但是没有换行
            while((line = bufferedReader.readLine()) != null) {
                bufferedWriter.write(line);
				//换行
                bufferedWriter.newLine();
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            // 关闭流
            // 加上一个try-catch语句块
			if(bufferedReader != null) {
                bufferedReader.close();
            }
            if(bufferedWriter != null) {
                bufferedWriter.close();
            }
        }
    } 
}

注意:

  • BufferedReader以及BufferedWriter 是字符操作;
  • 不要去操作 二进制文件,可能造成文件损坏;
    • 二进制文件:声音、视频、doc、pdf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值