程序员程序员首页投稿首页投稿(暂停使用,暂停投稿)

Java复习之IO流(上)

2017-10-26  本文已影响229人  maoqitian

IO流(Input Output ),即输入输出。

IO流:IO流用于处理设备间的数据传输(内存和硬盘之间)。IO流读取硬盘上的文件,对文件的操作,文件有可能不存在,操作不存在的文件,就会出现错误,Java程序在运行过程中出现的错误,而这个错误就叫做异常(Exception)。

下一篇文章传送门:
Java复习之IO流(下)

什么叫异常:

异常的概述

异常继承体系.png

JVM(Java Virtual Machine)默认是如何处理异常的

函数自己处理异常

/**
 * 
 * @author 毛麒添
 * throw 抛出异常
 * 运行时异常抛出和编译时异常抛出
 */
public class Demo_throws {
   
    public static void main(String[] args) throws Exception {
        Person p=new Person();
        p.setAge(-17);
    }
}

class Person{
     private int age;
     private String name;
     
    public int getAge() {
        return age;
    }
    public void setAge(int age) throws Exception {
        if(age>0&&age<=100){
            this.age = age;
        }else{
            throw new Exception("年龄不合法");
        }
    }
       /**
         * RuntimeException 不需要throws声明
    
    public void setAge(int age)  {
        if(age>0&&age<=100){
            this.age = age;
        }else{
            throw new RuntimeException("年龄不合法");
        }
        
    }
     */
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
     
}
运行截图.png
try {
            FileInputStream fis=new FileInputStream("aaa.txt");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
class AgeOutoflegalException extends Exception{

    public AgeOutoflegalException() {
        super();
        // TODO Auto-generated constructor stub
    }

    public AgeOutoflegalException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }
    
}
自定义异常运行结果.png
/**
 * @author 毛麒添
 *  键盘录入一个int类型的整数,对其求二进制表现形式
 *  如果录入的整数过大,给予提示,录入的整数过大请重新录入一个整数BigInteger
 *  如果录入的是小数,给予提示,录入的是小数,请重新录入一个整数
 *  如果录入的是其他字符,给予提示,录入的是非法字符,请重新录入一个整数
 */
public class Demo_Test {

    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        
        System.out.println("请输入一个整数:");
        
            while(true){
                String string = sc.nextLine();
            
                try {
                    //将字符串转换成整数
                    int num=Integer.parseInt(string);
                    System.out.println(string+"的二进制表达形式为:"+Integer.toBinaryString(num));
                    break;
                } catch (Exception e) {
                    try {
                        new BigInteger(string);//到这步说明这是一个很大的整数
                        System.out.println("录入错误,输入的是一个很大的整数,请重新输入");
                    } catch (Exception e2) {
                        try {
                            new BigDecimal(string);//到这步说明这是一个小数
                            System.out.println("录入错误,输入的是一个小数,请重新输入");
                        } catch (Exception e3) {
                            //到这一步说明输入的是非法字符
                            System.out.println("录入错误,输入的是非法字符,请重新输入");
                        }
                    }
                }
            }
    }
}

运行截图:

异常小结例子截图.png

前面提到,IO流操作文件,我们首先要知道文件在哪,没有这个文件则需要创建,修改文件名等操作,则我们需要用到File类。

/**
 * 
 * @author 毛麒添
 * 需求:判断D盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称 //递归
 * 需求:判断D盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称//文件过滤器
 */
public class Test {

    public static void main(String[] args) {
        
        demo1(new File("D:\\图片"));
         //需求:判断D盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称//文件过滤器
        File file=new File("D:\\图片");
        String[] list = file.list(new FilenameFilter() {
            
            @Override
            public boolean accept(File dir, String name) {
                // 将遍历的文件封装成对象
                File file2=new File(dir, name);
                return file2.isFile()&&file2.getName().endsWith(".jpg");
            }
        });
        
        for (String string : list) {
            System.out.println(string);
        }
    }

    private static void demo1(File dir) {
        //需求:判断D盘目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称 //递归 
         File[] files = dir.listFiles();
         for (File file2 : files) {
            if(file2.isFile()&& file2.getName().endsWith(".jpg")){
                System.out.println(file2);
            }else if(file2.isDirectory()){//如果是文件夹,则递归继续寻找
                demo1(file2);
            }
        }
    }

}

一不小心,扯了这么多,好吧,下面进入到本文主题 IO流

 * 
 * @author 毛麒添
 * 读取项目中 a.txt文件中的内容,一次读取一个字节
 */

public class Demo_FileInputStream {

    public static void main(String[] args) throws IOException {
        FileInputStream fis=new FileInputStream("a.txt");//确保项目中有该文件
        int a;
        while((a=fis.read())!= -1){
            System.out.println(a);
        }
        System.out.println(a);
        fis.close();

    }

a.txt中的内容.png

运行结果:

FileInputStream例子运行截图.png
/**
 * 
 * @author 毛麒添
 * 写入内容,一个一个字节写
 */

public class Demo_FileOutputStream {

    public static void main(String[] args) throws IOException {
        /* 如果没有改文件,则会自动创建,构造方法中,写入文件如果不加入boolean类型判断,则写入会
         * 清空之前的内容再写入,如果想继续在前面写入的基础追加,则需要boolean类型参数,true表示继续追加
         */
        FileOutputStream fos=new FileOutputStream("b.txt",true);
        //前面我们读取到123,现在则写入 机器码分别为 49 50 51
        fos.write(49); //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个字节
        fos.write(50);
        fos.write(51);
        fos.close();
    }
}

程序每运行一次都会添加一次123

b.txt文件内容.png
/**
 * 
 * @author 毛麒添
 * 文件拷贝三种方式
 * 方式一 :一个字节一个字节读取拷贝
 * 方式二:整个文件一起读取在拷贝
 * 方式三:定义小数组读取文件,在将小数组中的数据写入文件
 */

public class FileCopy {

    public static void main(String[] args) throws IOException {
        //demo1();
        //demo2();
        
        //方式三:定义小数组读取文件,在将小数组中的数据写入文件(开发中标准的文件拷贝写法)
        FileInputStream fis=new FileInputStream("a.txt");
        FileOutputStream fos=new FileOutputStream("c.txt");
        
        byte[] bytes=new byte[1024*2];
        int len;
        //这里如果不读取字节数组,则len每一次得到的是对应数据的机器码,则拷贝写入的文件大小则为机器码的字节数总和
        while((len=fis.read(bytes))!=-1){
            fos.write(bytes, 0, len);
        }
        
        fis.close();
        fos.close();
        
    }

    private static void demo2() throws FileNotFoundException, IOException {
        //方式二:整个文件一起读取在拷贝(available())
        //该方式如果读取的是大文件,当将整个大文件读取,则会导致内存溢出
                FileInputStream fis=new FileInputStream("a.txt");
                FileOutputStream fos=new FileOutputStream("c.txt");
                
                int available = fis.available();//获取文件大小
                //创建一个与该文件一样大小的字节数组
                byte[] b= new byte[available];
                //将字节数组读取到内存中
                fis.read(b);
                //将字节数组的数组写到需要拷贝到的文件中
                fos.write(b);
                
                fis.close();
                fos.close();
    }

    private static void demo1() throws FileNotFoundException, IOException {
        //方式一 :一个字节一个字节读取拷贝(该方法也是IO流的拷贝核心代码)
        FileInputStream fis=new FileInputStream("a.txt");
        FileOutputStream fos=new FileOutputStream("c.txt");
        
        int a;
        while((a=fis.read())!=-1){
            fos.write(a);
        }
        
        fis.close();
        fos.close();
    }

}

/**
 * 
 * @author 毛麒添
 * JDK 1.6 1.7 版本IO流标准异常处理写法
 *
 */
public class Demo_CopyFile {

    public static void main(String[] args) throws IOException {
        demo1();
        //jdk 1.7 版本
        // FileInputStream和FileOutputStream 最上层都继承了 AutoCloseable接口,自动调用close方法,所以该写法不用手动关流
        try(
                FileInputStream fis=new FileInputStream("a.txt");
                FileOutputStream fos=new FileOutputStream("b.txt");
                ){
             int a;
            
             while((a=fis.read())!=-1){
                fos.write(a);
        }
        }
    }

    private static void demo1() throws FileNotFoundException, IOException {
        // JDK1.6版本
        FileInputStream fis=null;//局部变量使用前需要赋值
        FileOutputStream fos=null;
        try {
            fis=new FileInputStream("a.txt");
            fos=new FileOutputStream("b.txt");
            
            int a;
            
            while((a=fis.read())!=-1){
                fos.write(a);
            }
        } finally{
            try{                    //try finally 嵌套保证能关一个流就尽量关闭一个
                if(fis!=null)
                    fis.close();
            }finally{

                if(fos!=null)
                fos.close();
            }
            
        }
    }

}

BufferedInputStream 和 BufferedOuputStream操作示意图.png

下面给出BufferedInputStream 和 BufferedOuputStream拷贝问价的例子

/**
 * 
 * @author 毛麒添
 * BufferedInputStream和BufferOutputStream拷贝
 */

public class Demo_BufferCopy {

    public static void main(String[] args) throws IOException {
        
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream("a.txt"));
        
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("c.txt"));
        
        int a;
        
        while((a=bis.read())!=-1){
            bos.write(a);
        }

        
        bis.close();
        bos.close();

    }

}
/**
 * 
 * @author 毛麒添
 * 文件加密
 * 将写出的字节异或上一个数,这个数也就是我们的秘钥,这时候文件已经加密
 * 如果需要将文件解密,则读取加密文件再次异或我们的秘钥变可以解密
 */


public class FileEncrypt {

    public static void main(String[] args) throws IOException {
        
        String file1="a.jpg";
        
        String file2="c.jpg";
        int key=456;
        //加密
        fileEncrypt(file1, file2, key);
        
        String file3="d.jpg";
        //解密
        fileEncrypt(file2, file3, key);
    }

    public static void fileEncrypt(String file1, String file2, int key) throws FileNotFoundException, IOException {
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file1));
        
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file2));
        
        int b;
        while((b= bis.read())!=-1){
            bos.write(b^key);//456就是我们加密的秘钥
        }
    }
}

运行结果:

图片a.png 图片C.png 图片d.png
/**
 * 
 * @author 毛麒添
 * 将键盘输入的字符串写入到文件当中
 */
public class WriteToFile {

    public static void main(String[] args) throws IOException {
        Scanner sc=new Scanner(System.in);

        FileOutputStream fos=new FileOutputStream("write.txt");
        
        System.out.println("请在键盘中输入数据:");
        while(true){
            String nextLine = sc.nextLine();
            if("quit".equals(nextLine)){
                System.out.println("写入完成!!");
                break;
            }
            fos.write(nextLine.getBytes());//字符串写入文件必须为字符数组
            fos.write("\r\n".getBytes());//换行
        }
        
        fos.close();
    }

}

运行结果:

文件写入运行结果1.png 文件写入运行结果2.png
/**
 * 
 * @author 毛麒添
 * 键盘输入文件路径,将该文件拷贝到当前项目下
 * 
 */
public class CopyFileProgress {

    public static void main(String[] args) throws IOException {
        //键盘录入文件路径,获取该文件对象
        File file=getFile();

        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
        //拷贝的文件名称一样
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file.getName()));
        
        int a;
        
        while((a=bis.read())!= -1){
            bos.write(a);
        }
        System.out.println("拷贝完成");
        bis.close();
        bos.close();
        
    }

    private static File getFile() {
        Scanner sc=new Scanner(System.in);
    
        System.out.println("请输入文件的路径:");
        
        while(true){
            String nextLine = sc.nextLine();
            File file=new File(nextLine);
            if(!file.exists()){
                System.out.println("该文件不存在,请重新输入!");
            }else if(file.isDirectory()){//如果是一个路径
                System.out.println("输入的是文件路径,请重新输入!");
            }else{
                return file;
            }
        }
        
    }

}

键盘输入路径拷贝文件截图.png

本文对异常处理,File类和字节流做了复习,在下一篇文章则继续对IO流中的字符流等知识进行复习。如果大家有发现不对的地方,欢迎给我指出,大家一起学习进步。如果觉得文章对你有帮助,也请给我一个喜欢。

本系列文章:
Java复习之集合框架
Java复习之IO流(上)
Java复习之IO流(下)
Java 复习之多线程

上一篇下一篇

猜你喜欢

热点阅读