java学习——I/O

目录

一、File类

1、File类的作用

2、File类的使用

常用构造方法

获取文件相关信息方法

文件的相关判断方法

文件列表相关方法

递归学习

思考学习——任何删除一个文件夹

二、I/O流学习

1、初步了解

2、字节流

说明

OutputStream常用方法

文件输入流 FileOutputStream 构造方法

InputStream常用方法

文件输入流 FileInputStream构造方法

练习:使用字节流实现磁盘文件拷贝功能

3、字符流

说明

Writer常用方法

FileWriter构造方法

Reader常用方法

FileReader构造方法

练习:使用字符流实现磁盘文件拷贝功能

4、缓冲流

说明

BufferedOutputStream构造方法

BufferedInputStream构造方法

练习:缓冲字节流实现文件拷贝

练习:缓冲字符流实现文件拷贝

补充内容

5、数据流

说明

DataOutput 接口常用方法

DataOutputStream构造方法

DataInput 接口常用方法

DataInputStream构造方法

6、对象流

说明

ObjectOutput 接口常用方法

ObjectOutputSteam构造方法

ObjectInput 接口常用方法

ObjectInputStream构造方法

三、将一个字节流转换成一个字符流


一、File类

1、File类的作用

java.io.File类是对存储在磁盘上的文件信息的一个抽象表示,主要用于文件的创建、查找和删除。

2、File类的使用

常用构造方法

public File(string pathname);//通过将给定的字符串路径名转换为抽象路径名来创建File实例

public File(string parent, string child) ;

//通过给定的字符父级串路径和字符串子级路径来创建File实例

public File(File parent, string child);//通过父级抽象路径名和字符串子路径创建File实例

例子

package IO_files;

import java.io.File;

public class test1 {
    public static void main(String[] args) {
        //以下三种文件生成方法结果都是"F:\\a\\b\\c.txt"
        File file1=new File("F:\\a\\b\\c.txt");

        File file2=new File("F:\\a\\b","c.txt");

        File parent=new File("F:\\a\\b");
        File file3=new File(parent,"c.txt");
    }
}

获取文件相关信息方法

public string getAbsolutepath(); //获取文件的绝对路径


public string getName();//获取文件的名字


public string getpath();//获取文件的路径


public File getParentfile();//获取文件的父文件


public string getParent();//获取文件的父文件路径public long length();//获取文件的大小


public long lastModified();//获取文件最后修改时间

例子

package IO_files;

import java.io.File;

public class test2 {
    public static void main(String[] args) {

        File file1=new File("F:\\a\\b\\c.txt");
        //获取文件的绝对路径
        String absPath=file1.getAbsolutePath();
        System.out.println(absPath);

        //获取文件的路径,可能是相对路径,也可能是绝对路径
        String path=file1.getPath();
        System.out.println(path);

        String name=file1.getName();//获取文件名
        System.out.println(name);

        //获得文件的父级文件夹对象
        File parentFile=file1.getParentFile();
        System.out.println(parentFile);

        //获得文件的父级路径
        String parentPath=file1.getParent();
        System.out.println(parentPath);

        //获取文件的大小,单位是字节
        long length=file1.length();
        System.out.println(length);

        //获取文件的最后修改时间
        long lastUpdateTime=file1.lastModified();
        System.out.println(lastUpdateTime);

        //获取系统当前时间:单位毫秒
        long currentTime=System.currentTimeMillis();
        System.out.println(currentTime);

        File file2=new File("chapter4\\c.txt");
        System.out.println(file2.getAbsolutePath());
        System.out.println(file2.getPath());
    }
}

文件的相关判断方法

public boolean canRead();//是否可读


public boolean canwrite();//是否可写


public boolean exists();//是否存在


public boolean isDirectory()://是否是目录


public boolean isFile();//是否是一个正常的文件


public boolean isHidden();//是否隐藏


public boolean canExecute();//是否可执行


public boolean createNewFile() throws IOException;
//创建新的文件


public boolean delete();//删除文件


public boolean mkdir();//创建目录,一级


public boolean mkdirs();//创建目录,多级


public boolean renameTo(File dest);//文件重命名

例子

package IO_files;

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

public class test3 {
    public static void main(String[] args) {
        File file1=new File("D:\\:record\\stu.txt");

        //判断文件是否可读
        boolean readable=file1.canRead();
        System.out.println("文件是否可读:"+readable);

        //判断文件是否可写
        boolean writeable=file1.canWrite();
        System.out.println("文件是否可写:"+writeable);

        //判断文件是否存在
        boolean exists=file1.exists();
        System.out.println("文件是否存在:"+exists);

        //判断文件是否是目录
        boolean isDirectory=file1.isDirectory();
        System.out.println("文件是否是目录:"+isDirectory);
        File parent=file1.getParentFile();
        System.out.println("父级文件是否是目录:"+parent.isDirectory());

        //判断文件是否是隐藏文件
        boolean hidden=file1.isHidden();
        System.out.println("文件是否是隐藏文件:"+hidden);

        //判断文件是否可执行
        boolean executable=file1.canExecute();
        //可执行文件定义:是指双击后有反应的文件
        System.out.println("文件是否可执行:"+executable);

        //创建新的文件
        File newFile=new File("D:\\test\\new.txt");
        File parentFile=newFile.getParentFile();
        if(!parentFile.exists()){ //exists 通常会与创建目录的方法配合使用
            //创建父级目录,但只能创建一级
     //       parentFile.mkdir();
            //创建多级父级目录
            parentFile.mkdirs();
        }

        if(!newFile.exists()){
            try {
                //创建文件时,必须保证该文件的父级目录存在,否则,创建将报IO异常
                boolean success=newFile.createNewFile();
                System.out.println("文件创建是否成功:"+success);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        boolean deleteSuccess=file1.delete();
        System.out.println("文件是否被删除:"+deleteSuccess);
        //删除文件夹时,必须保证文件夹中没有任何文件,也就是保证文件夹是空的
        boolean deleteFolderSuccess=parentFile.delete();
        System.out.println("文件夹删除是否成功:"+deleteFolderSuccess);

        File renameFiles=new File("F:\\test\\stu_new\\new.txt");
        //文件重命名至目标文件夹时,必须保证目标文件夹存在。重命名操作成功后,
        //原来的文件就移动过去了。
        boolean renameSuccess=newFile.renameTo(renameFiles);
        System.out.println("文件重命名是否成功:"+renameSuccess);
    }
}

注:删除文件夹时,必须保证文件夹为空,否则将删除失败。

文件列表相关方法

public File[ ] listFiles(); //列出文件夹下所有文件

public File[ ] listFiles(FileFilter filter); //列出文件夹下所有满足条件的文件

例子

package IO_files;

import java.io.File;
import java.io.FileFilter;

public class test4 {
    public static void main(String[] args) {
        File directory=new File("D:\\java study\\IDEA_list");
        //列出文件夹中所有的文件
        File[] files=directory.listFiles();

        //需要做非空判断,因为目录可能是非法的,也可能是不存在的
//        if(files!=null){
            for (int i=0;i<files.length;i++){
                File file=files[i];
            }
            for (File file:files){//增强for循环,效果与上面注释代码相同
                System.out.println(file.getPath());
            }

        File folder=new File("D:\\idea\\IntelliJ IDEA 2020.1\\bin");
        //FileFilter是一个匿名内部类,相当于将类的名字隐藏起来
        FileFilter filter=new FileFilter() {
            //accept表示接受文件的条件
            @Override
            public boolean accept(File file) {
                String name=file.getName();//获取文件名,也包含后缀在内
                return name.endsWith(".exe");//表示将后缀为".exe"的文件返回
                //startsWith("") 表示检测到以""内的内容为开头的字符串
            }
        };
        
        File[] childFiles=folder.listFiles(filter);
        if(childFiles!=null){
            for (File file:childFiles){
                System.out.println(file);
            }
        }
    }
}

递归学习

认知概念:

在方法内部再调用自身就是递归。递归分为直接递归和间接递归。
直接递归就是方法自己调用自己。
间接递归就是多个方法之间相互调用,形成一个闭环,从而构成递归。
使用递归时必须要有出口,也就是使递归停下来。否则,将导致栈内存溢出。

例子

package IO_files;

public class test5 {
    public static void main(String[] args) {
        int result=sum(5);
        System.out.println(result);
        int result1=multiply(5);
        System.out.println(result1);
    }

    public static int sum(int number){//递归实现累加求和
        if(number==1)
            return 1;
        return number+sum(number-1);
    }

    public static int multiply(int number){//递归实现阶乘
        if(number==0||number==1)
            return 1;
        return number*multiply(number-1);
    }
}

思考学习——任何删除一个文件夹

代码如下:

package IO_files;

import java.io.File;
import java.io.FileFilter;

public class test6 {
    public static void main(String[] args) {
        File folder = new File("D:\\java study");
        recursiveFolder(folder);
    }

    public static void recursiveFolder(File folder) {
        if (folder.isDirectory()) {//检查是否是文件夹
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {//如果是文件夹,就再调用方法看看
                        recursiveFolder(file);
                    } else {
                        System.out.println(folder.getPath());
                    }
                }
            } else { //不是文件夹就直接打印文件的路径
                System.out.println(folder.getPath());
            }
        }
    }

    //实现文件夹删除
    public static void deleteFolder(File folder){
        if(folder.isDirectory()) {//是文件夹就需要再进去看
            File[] files = folder.listFiles();
            if(files!=null){
                for(File file:files){
                    if(file.isDirectory()){
                        deleteFolder(file);
                    } else {
                        file.delete();
                    }
                }
                folder.delete();//文件夹中文件删除完毕后,文件夹也要删除
            }
        } else {//不是文件夹,直接删除
            folder.delete();
        }
    }
}

二、I/O流学习

1、初步了解

I/O的来源

I/O是Input和Ouput两个单词的首字母,表示输入输出。其参照物就是内存,写入内存,就是输入,从内存读取数据出来,就是输出。

Java中的I/O流


磁盘和内存是两个不同的设备,它们之间要实现数据的交互,就必须要建立一条通道, 在Java中实现建立这样的通道的是I/0流。Java中的I/0流是按照数据类型来划分的。分别是字节流(缓冲I、二进制数据流和对象流)、字符流。

2、字节流

说明

程序使用字节流执行8位字节的输入和输出,所有字节流类均来自InputStream和OutputStream。

字节流仅仅适用于读取原始数据(基本数据类型)。

OutputStream常用方法

public abstract void write(int b); //写一个字节

public void write(byte b[ ]) throws IOException;
 //将给定的字节数组内容全部写入文件中

//将给定的字节数组中指定的偏移量和长度之间的内容写入文件中

public void write(byte b[ ], int off, int len) throws IOExCeption;

public void flush() throws IOException;
//强制将通道中数据全部写出

public void close() throws IOException;//关闭通道

文件输入流 FileOutputStream 构造方法

public Fileoutputstrean(string name) throws FileNotFoundException; 
//根据提供的文件路径构建条一条文件输出通道

//根据提供的文件路径构建一条文件输出通道,并根据append的值决定是将内容追加到末尾还是直接覆盖public Fileoutputstrean(string name, boolean append) throws Fi leNotFoundException;

public Fileoutputstream(File file) throws FileNotFoundException;
//根据提供的文件信息构建一条文件输出通道

//根据提供的文件信息构建一条文件输出通道,并根据append的值决定是将内容追加到末尾还是直接覆盖public Fileoutputstream(File file, boolean append) throws FileNotFoundException;

示例:将"IO流学习"写入磁盘中

代码如下:

package ByteStreams;

import java.io.*;

public class test1 {
    public static void main(String[] args) {

        //将内容写入文件时,需要保证这个文件的父级目录一定存在,否则将报文件未找到异常
        try {
            File dir=new File("D:\\as");
            if(!dir.exists()){
                dir.mkdirs();
            }
            File file=new File(dir,"io.txt");
            //OutputStream os=new FileOutputStream("D:\\as\\io.txt"); 与上面功能相同
            //实现内容再写入一次
            OutputStream os=new FileOutputStream(file,true);

            String text="IO流学习";
            byte[] bytes=text.getBytes();
//            for(byte b:bytes){
//                os.write(b);//一次写一个字节至文件中
//            }
            //向通道中一次将所有字节数组中的内容发送过去
            //os.write(bytes);

            //使用偏移量和长度的时候要考虑数组下标越界
            os.write(bytes,1,bytes.length);//偏移一个字节
            //在通道关闭之前使用,强制将通道中的数据写入文件中
            os.flush();

            os.close();//关闭通道

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

InputStream常用方法

public abstract int read() throws IOException; //读取一个字节

public int read(byte b[ ]) throws IOException; //读取多个字节存储至给定的字节数组中

//读取多个字节按照给定的偏移量及长度存储在给定的字节数组中
public int read(byte b[ ],int off, int len) throws IOException;

public void close() throws IOException;//关闭流, 也就是关闭磁盘和内存之间的通道


public int available() throws IOException;// 获取通道中数据的长度

文件输入流 FileInputStream构造方法

public abstract int read() throws IOException; //读取一个字节

public int read(byte b[ ]) throws IOException; //读取多个字节存储至给定的字节数组中
 

示例:使用文件输入流将文件信息从磁盘中读取到内存中来,并在控制台输出

代码如下:

package ByteStreams;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/*
使用文件输入流将文件信息从磁盘中读取到内存中来,并在控制台输出
 */
public class test2 {
    public static void main(String[] args) {
        try {
            InputStream is=new FileInputStream("D:\\as\\io.txt");
            int length=is.available();//获取通道中的长度
            //根据通道中数据长度构建字节数组,但需要考虑到一点,
            //如果通道中数据长度过长,那么字节数组构建太大,则
            //可能导致内存不够,比如使用流读取一个大小为10G的文
            //件,这种方式存在弊端
            byte[] buffer=new byte[length];
            int index=0;

//            while(true){
//                //读取通道中的数据,一次读取一个字节,如果读到末尾,则返回-1
//                byte b=(byte) is.read();
//                if(b==-1)
//                    break;
//                buffer[index++]=b;
//            }
            //read() 有返回值,返回值是输入总字节数
            is.read(buffer);//上面代码与此代码效果相同

            System.out.println(new String(buffer));
            is.close();//关闭通道
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

补充学习代码

package ByteStreams;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class test3 {
    public static void main(String[] args) {
        try {
            InputStream is=new FileInputStream("D:\\as\\io.txt");

            //实际开发过程中字节数组的长度一般定义为1024的整数倍
            byte[] buffer=new byte[30];//构建了一个长度为30的字节数组
            while(true){
                //从通道中读取数据存入字节数组buffer中,返回值就是读取的字节长度
                //如果读取到数据末尾,则返回-1
                int len=is.read(buffer);
                if(len==-1) break;
                System.out.println(len);
            }
//            int count1=is.read(buffer);//输出30
//            int count2=is.read(buffer);//输出30
//            int count3=is.read(buffer);//输出1
//            int count4=is.read(buffer);//输出-1
//            System.out.println(count1);
//            System.out.println(count2);
//            System.out.println(count3);
//            System.out.println(count4);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注:如果通道中数据长度过长,那么根据通道中数据的长度来构建字节数组,则可能导致内存不够,比如使用流读取一个大小10G的文件那么通道中就应该存在10G长的数据。

思考代码:

package ByteStreams;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class test4 {
    public static void main(String[] args) {
        try {
            InputStream is=new FileInputStream("D:\\as\\io.txt");
            byte[] buffer=new byte[1024];
            int offset=0;
            while ((true)){
                int len=is.read(buffer,offset,40);

                if(len==-1) break;
                System.out.println(len);
                offset+=len;
            }
            //System.out.println(new String(buffer));//输出文本内容
            System.out.println(new String(buffer,0,offset));//效果与上面代码一样
            is.close();
//            int pos1=is.read(buffer,0,40);
//            int pos2=is.read(buffer,40,40);
//            int pos3=is.read(buffer,80,40);
//            System.out.println(pos1);
//            System.out.println(pos2);
//            System.out.println(pos3);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

练习:使用字节流实现磁盘文件拷贝功能

代码如下:

package ByteStreams;

import java.io.*;

/**
 * 使用字节流实现磁盘文件拷贝功能
 */
public class test5 {
    public static void main(String[] args) {
        String soureFile = "D:\\as\\io.txt";//目标文件
        String destFile = "D:\\at\\iu.txt";//新的文件
        copyFile(soureFile,destFile);
    }

    public static void copyFile(String soureFile,String destFile){
        File file=new File(destFile);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();//检测父级目录是否存在,不存在就创建一个
        try {
            InputStream is=new FileInputStream(soureFile);
            OutputStream os=new FileOutputStream(destFile);
            byte[] buffer=new byte[4096];//1024*4
            while(true){
                int len=is.read(buffer);
                if(len==-1) break;
                os.write(buffer,0,len);
            }
            os.flush();
            is.close();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

进阶版:

package ByteStreams;

import java.io.*;

/**
 * 使用字节流实现磁盘文件拷贝功能(改进版)
 */
public class test6 {
    public static void main(String[] args) {
        String soureFile = "D:\\as\\io.txt";//目标文件
        String destFile = "D:\\at\\iu.txt";//新的文件
        copyFile1(soureFile, destFile);
    }

    public static void copyFile1(String soureFile, String destFile) {
        File file = new File(destFile);
        File parent = file.getParentFile();
        if (!parent.exists()) parent.mkdirs();//检测父级目录是否存在,不存在就创建一个
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream(soureFile);
            os = new FileOutputStream(destFile);
            byte[] buffer = new byte[4096];//1024*4
            while (true) {
                int len = is.read(buffer);
                if (len == -1) break;
                os.write(buffer, 0, len);
            }
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {//清除缓存
//            if (is != null){
//                try {
//                    is.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//        }
//            if (os != null) {
//                try {
//                    os.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
            close(is, os);//效果与上述注释代码相同
        }
    }

    //Cloneable...c 是不定长自变量,它本质是一个数组,在使用不定长自变量
    //作为方法的参数时,必须为该方法参数列表的最后一个参数
    public static void close(Closeable... closeables) {
        for (Closeable c : closeables) {
            if (c != null) {
                try {
                    c.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void copyFile2(String soureFile, String destFile) {
        File file = new File(destFile);
        File parent = file.getParentFile();
        if (!parent.exists()) parent.mkdirs();//检测父级目录是否存在,不存在就创建一个
        //try(){}catch(){}  JDK 1.7及其后续版本才能使用
        //写在括号中的代码只能够实现AutoClosable接口的类
        //不需要考虑关闭操作
        try(InputStream is = new FileInputStream(soureFile);
            OutputStream os = new FileOutputStream(destFile);) {
            byte[] buffer = new byte[4096];//1024*4
            while (true) {
                int len = is.read(buffer);
                if (len == -1) break;
                os.write(buffer, 0, len);
            }
            os.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3、字符流

说明

a、Java平台使用unicode约定存储字符值。字符流I/O会自动将此内部格式与本地字符集转换。在西方语言环境中, 本地字符集通常是ASCII的8位超集。
b、所有字符流类均来自Reader和Writer。与字节流一样, 也有专门用于文件I/O的字符流类: FileReader和Filewriter。

Writer常用方法

public void write(int c) throws IOException; //写一个字符

public void write(char cbuf[ ]) throws IOException;//将给定的字符数组内容写入到文件中

//将给定的字符数组中给定偏移量和长度的内容写入到文件中
abstract public void write(char cbuf[ ], int off, int len) throws IOException;

public void write(string str) throws IoException;//将字符写入到文件中

abstract public void flush() throws IOException;//强制将通道中的数据全部写出

abstract public void close() throws IOException;//关闭通道

FileWriter构造方法

public Filewriter(string fileName) throws IOException;//根据提供的文件路径构建一条文件输出通道

//根据提供的文件路径构建一条文件输出通道,并根据append的值决定是将内容追加到末尾还是直接覆盖

public Filewriter(string fileName, boolean append) throws IOException;

public Filewriter(File file) throws IOException:;//根据提供的文件信息构建一 条文件输出通道

//根据提供的文件信息构建一条文件输出通道,并根据append的值决定是将内容追加到末尼还是直接覆盖

public Filewriter(File file, boolean append) throws IOExCeption;

示例:使用字符流将"IO流学习"写入磁盘文件中

代码如下:

package IO_char;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class test1 {
    public static void main(String[] args) {
        File file=new File("D:\\as\\io.txt");
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        //Writer类实现了AutoCloseable接口,因此可以将Writer类对象的构建方法
        //写在try后面的()中
        try(Writer writer=new FileWriter("D:\\as\\io.txt",true);) {
            String text="IO流学习";
//            char[] values=text.toCharArray();
//            for(char c:values){
//                writer.write(c);
//            }
//            writer.write(values);//重写一遍内容到文件中
//            writer.write(values,0,values.length);//进行偏移,重写一遍内容到文件中
            writer.write(text);//重写一遍内容到文件中
            writer.flush();//强制将通道中的数据写入文件
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Reader常用方法

public int read() throws IOException; //读取一个字符

public int read(char cbuf[ ]) throws IOException; //读取字符到给定的字符数组中I

//将读取的字符按照给定的偏移量和长度存储在字符数组中
abstract public int read(char cbuf[ ], int off,int len) throws IOExCeption;

abstract public void close() throws IOException;//关闭通道

FileReader构造方法

public FileReader(string filename) throws FilenotFoundException;//根据提供的文件路径构建一 条文件输入通道

public FileReader(File file) throws FilenotFoundException://根据提供的文件信息构建一条文件输入通道

示例:使用字符流将文件信息从磁盘中读取到内存中,并在控制台输出

代码如下:

package IO_char;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class test2 {
    public static void main(String[] args) {
        try(Reader reader=new FileReader("D:\\as\\io.txt");) {

//            StringBuilder builder=new StringBuilder();
//            while(true){
//                int c=reader.read();
//                if(c==-1) break;
//                builder.append((char)c);
//            }
//            System.out.println(builder);

            char[] buffer=new char[4096];
            int offset=0;
            while(true){
//                int len=reader.read(buffer);
                int len=reader.read(buffer,offset,30);
                if(len==-1) break;
                offset+=len;
            }
            System.out.println(new String(buffer,0,offset));

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

练习:使用字符流实现磁盘文件拷贝功能

代码如下:

package IO_char;

import java.io.*;

/**
 * 使用字符流实现磁盘文件拷贝功能
 */
public class test3 {
    public static void main(String[] args) {
        String soureFile = "D:\\as\\io.txt";
        String destFile = "D:\\at\\ix.txt";
        copyFile(soureFile,destFile);
    }

    public static void copyFile(String sourceFile,String destFile){
        File file=new File(destFile);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(Reader reader=new FileReader(sourceFile);
            Writer writer=new FileWriter(destFile)) {
            char[] buffer=new char[4096];
            while (true){
                int len=reader.read(buffer);
                if(len==-1) break;
                writer.write(buffer,0,len);
            }
            writer.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4、缓冲流

说明

到目前为止,我们看到的大多数示例都使用无缓冲的I/O。这意味着每个读取或写入请求均由基础操作系统直接处理。由于每个这样的请求通常会触发磁盘访问,网络活动或某些其他相对昂贵的操作,因此这可能会使程序的效率大大降低。

为了减少这种开销,Java平台实现了缓冲的I/O流。缓冲的输入流从称为缓冲区的存储区中读取数据;仅当缓冲区为空时才调用本机输入API。同样, 缓冲的输出流将数据写入缓冲区,并且仅在缓冲区己满时才调用本机输出API。

有四种用于包装非缓冲流的缓冲流类:BufferedInputstream 和Bufferedoutputstream创建缓冲的字节流,而BufferedReader和Bufferedwriter创建缓冲的字符流。

BufferedOutputStream构造方法

public Bufferedoutputstream(outputstream out);//根据给定的字节输出流创建一个缓冲输出流,缓冲区大小使用默认大小

public Bufferedoutputstream(outputstream out, int size) ;//根据给定的字节输出流创建一个缓冲输出流, 并指定缓冲区大小

BufferedInputStream构造方法

public BufferedInputstream(Inputstream in); //根据给定的字节输入流创建一个缓冲输入流,缓冲区大小使用默认大小

public BufferedInputstream(Inputstream in, int size);//根据给定的字节输入流创建一个缓冲输入流,并指定缓冲区大小

练习:缓冲字节流实现文件拷贝

代码如下:

package IO_char;

import java.io.*;

/**
 * 缓冲字节流实现文件拷贝
 */
public class test4 {
    public static void main(String[] args) {
        String soureFile = "D:\\as\\io.txt";
        String destFile = "D:\\at\\ix.txt";
        copyFile(soureFile,destFile);
    }

    public static void copyFile(String soureFile,String destFile){
        File file=new File(destFile);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(InputStream is=new FileInputStream("");
            BufferedInputStream bis=new BufferedInputStream(is);
            OutputStream os=new FileOutputStream("");
            BufferedOutputStream bos=new BufferedOutputStream(os)){
            byte[] buffer=new byte[4096];
            while (true){
                int len=bis.read(buffer);
                if(len==-1) break;
                bos.write(buffer,0,len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

练习:缓冲字符流实现文件拷贝

代码如下:

package IO_char;

import java.io.*;

/**
 * 缓冲字符流实现文件拷贝
 */
public class test5 {
    public static void main(String[] args) {
        String soureFile = "D:\\as\\io.txt";
        String destFile = "D:\\at\\ix.txt";
        copyFile(soureFile,destFile);
    }

    public static void copyFile(String soureFile,String destFile){
        File file=new File(destFile);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(Reader reader=new FileReader("");
            BufferedReader br=new BufferedReader(reader);
            Writer writer=new FileWriter("");
            BufferedWriter bw=new BufferedWriter(writer)) {
            char[] buffer=new char[4096];
            while (true){
                int len=br.read(buffer);
                if(len==-1) break;
                bw.write(buffer,0,len);
            }
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

补充内容

package IO_char;

import java.io.*;

public class test6 {
    public static void main(String[] args) {
        String sourceFile = "D:\\buffer\\io.txt";
        String destFile = "D:\\copy\\copy.txt";
    }

    public static void copyFile(String sourceFile,String destFile){
        File file=new File(destFile);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(Reader reader=new FileReader(sourceFile);
            BufferedReader br=new BufferedReader(reader);
            Writer writer=new FileWriter(file);
            BufferedWriter bw=new BufferedWriter(writer)) {
            while (true){
                String line=br.readLine();//读行
                if(line==null) break;
                bw.write(line);//写行
                bw.newLine();//换行 => 相当于写入了一个 \r\n
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void readLine(){
        String path="D:\\buffer\\io.txt";
        try(Reader reader=new FileReader(path);
            BufferedReader br=new BufferedReader(reader)) {
            while (true){
                String line=br.readLine();
                if(line==null) break;
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void writeLine(){//写行
        String path="D:\\buffer\\io.txt";
        File file=new File(path);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(Writer writer=new FileWriter(file);
        BufferedWriter bw=new BufferedWriter(writer)) {
            bw.write("这是第一行");
            bw.newLine();
            bw.write("这是第二行");
            bw.newLine();
            bw.write("这是第三行");
            bw.newLine();
            /*
            文件内容如下:
            这是第一行
            这是第二行
            这是第三行

             */
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5、数据流

说明

数据流支持原始数据类型值(布尔值,char,字节,short, int, long. float 和double)以及String值的二进制I/O。所有数据流都实现DataInput接口或Dataoutput接口。本 节重点介绍这些接口的最广泛使用的实现,即DataInputStream和DataOutputStream。

DataOutput 接口常用方法

void writeBoolean(boolean v) throws IOException;

//将布尔值作为1个字节写入底层输出通道

void writeByte(int v) throws IOException;

//将字节写入底层输出通道

void writeShort(int v) throws IOException;

//将短整数作为2个字节(高位在前)写入底层输出通道

void writeChar(int v) throws IOException;

//将字符作为2个字节写(高位在前)入底层输出通道

void writeInt(int v) throws IOException;

//将整数作为4个字节写(高位在前)入底层输出通道

void writeLong(long v) throws IOException;

//将长整数作为8个字节写(高位在前)入底层输出通道

void writeFloat(float v) throws IOException;

//将单精度浮点数作为4个字节写(高位在前)入底层输出通道

void writeDouble(double v) throws IOException;

//将双精度浮点数作为8个字节写(高位在前)入底层输出通道

void writeUTF(string s) throws IoException;

//将UTF-8编码格式的字符串以与机器无关的方式写入底层输出通道
 

DataOutputStream构造方法

public DataOutputStream(OutputStream out); 根据给定的字节输出流创建一个二进制输出流

使用示例

private static void writeData(){
        String path="D:\\data\\io.txt";
        File file=new File(path);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(OutputStream os=new FileOutputStream(file);
            DataOutputStream dos=new DataOutputStream(os)) {
            dos.writeByte(-1);
            dos.writeShort(-2);
            dos.writeInt(1);
            dos.writeLong(100);
            dos.writeFloat(1.0f);
            dos.writeDouble(100.0);
            dos.writeChar('a');
            dos.writeBoolean(true);
            dos.writeUTF("这是UTF-8编码格式的字符串");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

DataInput 接口常用方法

boolean readBoolean() throws IOException;

//读取一 个字节,如果为0,则返回false: 否则返回true

byte readByte() throws IOException;

//读取一个字节

int readunsignedByte() throws IOException;

//读取一个字节,返回0-255之间的整数

short readShort() throws IOException;

//读取2个字节,然后返一个短整数

int readunsignedshort() throws IOException;

//读取2个字节, 返回一个0-65535之间的整数

char readChar() throws IOException;

//读取2个字节, 然后返回一个字符

int readInt() throws IOException;

//读取4个字节,然后返回一个整数

long readLong() throws IOException;

//读取8个字节, 然后返一个长整数

float readFloat() throws IOException;

//读取4个字节, 然后返一个单精度浮点数

double readDouble() throws IOException;

//读取8个字节, 然后返回一个双精度浮点数

string readUTF() throws IOException;

//读取一个使用UTF-8编码格式的字符串

DataInputStream构造方法

public DataInputstream(InputStream in) ;//根据给定的字节输入流创建个二进制输入流

使用示例

public static void main(String[] args) {
        String path = "D:\\data\\io.txt";
        try(InputStream is=new FileInputStream(path);
            DataInputStream dis=new DataInputStream(is)) {
            byte b=dis.readByte();
            System.out.println("读取字节"+b);
            short s=dis.readShort();
            System.out.println("读取短整数"+s);
            int i=dis.readInt();
            System.out.println("读取整数"+i);
            long l=dis.readLong();
            System.out.println("读取长整数"+l);
            float f=dis.readFloat();
            System.out.println("读取单精度浮点数"+f);
            double d=dis.readDouble();
            System.out.println("读取双精度浮点数"+d);
            char c=dis.readChar();
            System.out.println("读取字符"+c);
            boolean bool=dis.readBoolean();
            System.out.println("读取布尔值"+bool);
            String str=dis.readUTF();
            System.out.println("读取字符串"+str);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (EOFException e){//EndofFile
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

注意:Datastreams通过捕获EOFException来检测文件结束条件,而不是测试无效的返回值。DataInput方法的所有实现都使用EOFException而不是返回值。

6、对象流

说明

正如二进制数据流支持原始数据类型的I/O一样,对象流也支持对象的I/O。大多数(但不是全部)标准类支持其对象的序列化。那些类实现了序列化标记接口Serializable才能够序列化。

ObjectOutput 接口常用方法

public void writeobject(object obj) throws IOException;//将对象写入底层输出通道

ObjectOutputSteam构造方法

public objectoutputstrean(outputstream out) throws IOException;

//根据给定的字节输出流创建一个对象输出流

使用示例

package ObjectStreams;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

private static void writeObject(){
        String path="D:\\Object\\obj.txt";
        File file=new File(path);
        File parent=file.getParentFile();
        if(!parent.exists()) parent.mkdirs();
        try(OutputStream os=new FileOutputStream(file);
            ObjectOutputStream oos=new ObjectOutputStream(os)) {
            oos.writeObject(new Student("ash",20));
            oos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

注:将一个对象从内存中写入磁盘文件中的过程称之为序列化。序列化必须要求该对象所有类型实现序列化的接口。

ObjectInput 接口常用方法

public object readobject() throws ClassnotFoundException, IOExCeption;//读取一个对象

ObjectInputStream构造方法

public objectInputstrean(Inputstream in) throws IOException;

//根据给定的字节输入流创建一个对象输入流

使用示例

package ObjectStreams;

import java.io.Serializable;

public class Student implements Serializable {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

private static void readObject(){
        String path="D:\\Object\\obj.txt";
        try(InputStream is=new FileInputStream(path);
            ObjectInputStream ois=new ObjectInputStream(is)) {
            Student s= (Student) ois.readObject();
            System.out.println(s);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

注:将磁盘中存储的对象信息读入内存中的过程称之为反序列化,需要注意的是,反序列化必须保证与序列化时使用的JDK版本一致。

三、将一个字节流转换成一个字符流

代码如下:

import java.io.*;

public class IOConverter {
    public static void main(String[] args) {
        write();
        read();
    }

    private static void write(){
        try(OutputStream os=new FileOutputStream("D:\\as\\line.txt");
            OutputStreamWriter osw=new OutputStreamWriter(os);
            BufferedWriter bw=new BufferedWriter(osw)) {
            String[] lines={
                        "这是写入的第一行",
                        "这是写入的第一行,",
                        "这是写入的第一行,",
                        "这是写入的第一行,"
            };
            for (String line:lines){
                bw.write(line);
                bw.newLine();//实现换行
            }
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void read(){
        try(InputStream is=new FileInputStream("D:\\as\\line.txt");
            InputStreamReader isr=new InputStreamReader(is);
            BufferedReader reader=new BufferedReader(isr);) {
            while (true){
                String line=reader.readLine();
                if(line==null) break;
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值