Java高级编程十一:IO流(BIO和NIO)

第十一章 IO流

1.File类的使用

  • java.io.File 类:**文件和文件目录路径**的抽象表示形式,和平台无关,声明在java.io下
  • File 能新建、删除、重命名文件和目录,但是 File 不能访问文件内容本身,如需要访问文件内容,需要借助输入/输出流
  • 想要在Java程序中表示一个真实存在的文件或目录,name必须有一个File对象,但是在Java程序中的一个File对象,可能没有一个真实存在的文件或目录
  • File 对象可以作为参数传递给li流的构造器
1.1 File 类的常用方法
  1. 创建 File 类的对象

    • 相对路径 :相较于某个路径下,指明的路径
    • 绝对路径:包含盘符在内的文件或文件目录的路径
    • 在Windows下路径分隔符用 / 在UNIX下用 \
    • 为了避免在不同操作系统出现混淆,java 提供了一个常量,根据操作系统,动态提供分隔符 public static final String separator
    //构造器一 File(String filePath)
    //相对路径
    File file1 = new File("Hello.txt");
    //绝对路径
    File file2 = new File("D:\\Study\\java\\java培训详细版.md");
    //使用常量的方式
    //"D:" + File.separator + "Study" +File.separator + "java" File.separator + "java培训详细版.md"
    
    //构造器二 File(String parentPath,String childPath)
    File file3 = new File("D:\\Study\\java","Test");
    //构造器三 File(File parentFile,String childPath)
    File file4 = new File(file3,"tset.txt");
    
  2. 获取绝对路径 getAbsolutePath()[一等优先级]

    //public String getAbsolutePath()
    System.out.println(file1.getAbsolutePath());
    
  3. 获取相对路径 getPath()[一等优先级]

    //public String getPath()
    System.out.println(file1.getPath());
    
  4. 获取名称 getName()[一等优先级]

    //public String getName()
    System.out.println(file1.getName());
    
  5. 获取上层文件目录路径,没有返回null getParent()[一等优先级]

    //public String getParent()
    System.out.println(file1.getParent());
    
  6. 获取文件字节总数 length()[一等优先级]

    //public long length()
    System.out.println(file1.length());
    
  7. 获取最后一次修改时间 毫秒值 lastModified()[一等优先级]

    //public long lastModified()
    System.out.println(new Date(file1.lastModified());
    

    以下两个方法适用于文件目录

  8. 获取指定目录下所有文件或文件目录的名称数组 list()[特等优先级]

    //public String[] list()
    File file4 = new File("D:\\study");
    String[] list = file.list();
    for(String s : list){
        System.out.println(s);
    }
    
  9. 获取指定目录下的所有文件或目录的File数组listFiles()[特等优先级]

    //public File[] listFiles()
    File[] fs = file4.listFiles();
    for(File f : fs){
        System.out.println(f);
    }
    
  10. 得到当前系统的所有根目录listRoots()[特等优先级]

    //public static listRoots
    File[] fs = File.listRoots();
    
  11. 把文件重命名为指定的文件路径 renameTo()[高危]

    //public boolean renameTo(File dest)
    File f1 = new File("hello.txt");
    File f2 = new File("D:\\Study\\hello.txt");
    boolean re = f1.renameTo(f2);
    System.out.println(re);
    /*
    	要想保证是true,需要 f1 在硬盘中存在的,且 f2 不能再硬盘中存在
    */
    

    2. File类的判断功能

  12. 是否是文件目录 isDirectory()[一等优先级]

    //public boolean isDirectory()
    File f1 = new File("hello.txt");
    System.out.println(f1.isDirectory());//false
    
  13. 是否是文件 isFile()[一等优先级]

    System.out.println(f1.isFile());
    
  14. 是否存在 exists()[一等优先级]

    System.out.println(f1.exists());
    
  15. 是否可读 canRead()

    System.out.println(f1.canRead());
    
  16. 是否可写 canWrite()

    System.out.println(f1.canWrite());
    
  17. 是否隐藏 isHidden()

    System.out.println(f1.isHidden);
    

    3. File类的创建删除功能

    方法作用
    createNewFile()创建文件,如果存在返回false不进行创建
    mkdir()创建文件目录,存在则不创建
    mkdirs()[高危]创建文件目录,如果上一级目录不存在,一并创建
    delete()[高危]删除文件或文件夹,不经过回收站
    File file = new File("hi.txt");
    if(!file.exists()){
        file.createNewFile();
    }else{
        file.delete();
    }
    
    File file1 = new File("D:\\io\\io1 ");
    file1.mkdir();
    file1.mkdirs();
    

    例题

    判断指定目录下是否有.jpg文件,如果有输出文件名

    import java.io.*;
    public class JpgTest{
        public static void main(String[] args){
        	File srcFile = new File("D:\\Study");
            String[] fileNames = srcFile.list();
            for(String name : fileNames){
                if(name.endsWith(".jpg")){
                    System.out.println(name);
                }
            }
        }
    }
    

    遍历指定目录下所有文件名称,包括文件目录中的文件

    import java.io.*;
    public class FileTest{
        public static void main(String[] args){
            File dir = new File("D:\\Study\\Yitu");
            printSubFile(dir);
        }
       	private static void printSubFile(File dir){
            File[] subFiles = dir.listFiles();
            for(File f : subFiles){
                if(f.isDirectory()){
                    printSubFile(f);
                }else{
                    System.out.println(f.getAbsolutePath());
                }
            }
        }
    }
    

2. IO流原理及流的分类

  • 用于**处理设备之间的数据传输**,如读/写文件、网络通讯等
  • java程序中,对于数据的输入/输出操作以**流(Stream)**的方式进行
  • java.io 包下提供了各种 “ 流” 类的接口,用一获取不同种类的数据,并通过**标准的方法**输入或输出数据
  1. 流的分类

    • 按操作数据单位不同:字节流(8 bit)、字符流(16 bit)
    • 按数据流的流向不同:输入流、输出流
    • 按流的角色不同分为:节点流、处理流
    • 字节流读取中文会乱码,因为一个中文占用两个字节,所以需要用字符流读取
    抽象基类字节流字符流
    输入流InputStreamReader
    输出流OutputStreamWriter
    分类字节输入流字节输出流字符输入流字符输出流
    抽象基类InputStreamOutputStreamReaderWriter
    访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
    访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
    访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
    访问字符串StringReaderStringWriter
    缓冲流BufferedInputStreamBufferedOutputStreamBufferrdReaderBufferedWriter
    转换流InputStreamReaderOutputStreamWriter
    对象流ObjectInputStreamObjectOutputStream
    ****FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
    打印流PrintStremPrintWriter
    推回输入流PushbackInputStreamPushbackReader
    特殊流DataInputStreamDataOutputStream
2.1FileInputStream/FileOutputStream
  1. try-catch-finally

    import java.io.*;
    public class TestFileCopy{
        public static void main(String[] args) throws IOException{
    		FileInputStream fis = null;
    		FileOutputStream fos = null;
    		try{
    			fis = new FileInputStream("DNF - 痛苦之村列瑟芬.mp3");
    			fos = new FileOutputStream("DNF - 痛苦之村列瑟芬1.mp3");
    			byte[] data = new byte[3 << 20];
    			int len;
    			while((len = fis.read(data)) != -1){
    				fos.write(data,0,len);
    			}
    			//太慢了
    			/*
    			while((data = fis.read()) != -1){
    				fos.write(data);
    			}
    			*/
    		}catch(IOException e){
    			e.printStackTrace();
    		}finally{
    			try{
    				fis.close();
    			}catch(IOException e){
    				e.printStackTrace();
    			}finally{
    				try{
    					fos.close();
    				}catch(IOException e){
    					e.printStackTrace();
    				}
    			}
        	}
    	}
    }
    
  2. TWR 7.0新特性[超级重要🐴]

    import java.io.*;
    public class TestFileCopyWithTWR{
        public static void main(String[] args){
    		try(FileInputStream fis = new FileInputStream("1.jpg");FileOutputStream fos = new FileOutputStream("2.png")){
    			byte[] data = new byte[1024];
    			int len;
    			while((len = fis.read(data)) != -1){
    				fos.write(data,0,len);
    			}
    		}catch(IOException e){
    			e.printStackTrace();
    		}
        }
    }
    
  3. FileOutputStream的构造方法

    FileOutputStream( File f / String name) 这种模式如果有文件则会把源文件删除,在创建新的文件。想要在源文件的基础上追加文件则需要用 FileOutputStream(File f,true)

3 节点流

3.1 FileReader / FileWriter
  1. FileReader
  1. read() 返回读入的一个字符,如果达到文件末尾,则返回 -1
  2. 为了保证流资源一定会执行关闭操作,并需用try-catch-finally捕获异常
import java.io.*;
public class FileReaderTest{
    @Test
    public void test(){
        File file = null;
        FileReader fr = null;
        try{
            //1.实例化 File 类的对象,指明要操作的文件
            file = new File("hi.txt");
            //2.提供具体的流
            fr = new FileReader(file);
            //3.数据的读入
           int data = fr.read();
           while(data != -1){
               System.out.print((char)data);
               data = fr.read();
           }
            /*
            int data;
            while((data = fr.read()) != -1){
                System.out.println((char)data);
            }
            */
        }catch(IOExecption){
            e.printStackTrace(); 
        }finally{
            try{
                 //4.流的关闭
                 if(fr != null)
           		 	fr.close();
            }catch(IOExecption){
            	e.printStackTrace(); 
       		}
        }
    }
    
    //对 read() 操作升级,使用 read 的重载方法
    @Test
    public void testFileReader1{
        File file = null;
        FileReader fr = null;
        try{
            //1.File 类的实例化
        	file = new File("Hi.txt");
            //2.FileReader流的实例化
            fr = new FileReader(file);
            //3.读入操作
            //read(char[cbuf]):返回每次读入 cbuf数组中的字符串个数,如果达到文件末尾返回-1
            char[] cbuf = new char[5];
            int len;
            while((len = file.read(cbuf)) != -1){
    			//方式一
                for(int i = 0;i < len;i++){
                    System.out.print(cbuf[i]);
                }  
                //方式二
                String str = new String(cbuf,0,len);
                System.out.print(str);
            }
        }catch(IOExecption e){
            e.printStackTrace();
    	}finally{
            //4.资源的关闭
        }
    }
}
  1. FileWriter

说明

  1. 输出操作,对应的 File 可以不存在,并不会报异常

  2. File 对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建这个对象
    如果存在:①如果流使用的构造器是 FileWriter(file ,false) / FileWriter(file) ,对原有文件覆盖②如果使用的是 FileWriter(file,true) 不会对原有文件覆盖,而是在原有文件基础上追加内容
@Test
public void testFileWriter(){
     File file = null;
     FileWriter fw = null;
    try{
        //1. 提供 File 类对象,指明写出到的文件
        file = new File("Hi1.txt");
        //2.提供 FileWriter 的对象,用于数据写出
        fw = new FileWriter(file,false);
        //3.写出的操作
        fw.write("Hello World!");
    }catch(IOExecption e){
        e.printStackTrace();
    }fianlly{
        fw.close();
    }
}

使用 FileWriter 和 FileReader 实现文本文件的复制

import java.io.*;
//不能用字符流处理图片文件
public class TestFileCopy{
    @Test
    public void test(){
        FileReader fr = null;
         FileWriter fw = null;
       try{
            //1.创建 File 类的对象,指明读入和写出的文件
            File srcFile = new File("Hei.txt");
            File destFile = new File("Hi.txt");
            //2.创建输入流和输出流的对象
           	fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);
            //3.数据输入输出操作
            char[] c = new char[5];
            int len;//记录每次读出来的字符个数
            while((len = fr.read(c)) != -1){
                //每次写出 len 个字符
                fw.write(c,0,len);
            }
       }catch(IOExecption e){
           e.printStackTrace();
       }finally{
            //4.资源的关闭
            try{
                if(fw != null)
                    fw.close();
            }catch(IOExecption){
                 e.printStackTrace();
            }finally{
            	try{
                    if(fr != null)
                        fr.close();
                }catch(IOExecption){
                     e.printStackTrace();
                } 
            }
       }
    }
}

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

3.2BufferedInputStream/BufferedOutputStream
  • 提高流的读取,写入速度
  1. 实现非文本文件的复制

    import java.io.*;
    public class BufferedTest{
        @Test
        public void BUfferedTest(){
             FileInuputStream fis = null;
             FileInuputStream fis = null;
             BufferedInputStream bis = null;
             BufferedOutputStream bos = null;
            
            try{
                //1.造 File 对象
                File file1 = new File("hi.jpg");
                File file2 = new File("hei.jpg");
                //2.造流
                //2.1 造节点流
                fis = new FileInputStream(file1);
                fis = new FileOutputStream(file2);
                //2.2造缓冲流
                bis = new BufferedInputStream(fis);
                bos = new BufferedOutputStream(fos);
                //3.读取写入
                byte[] b = new byte[10];
                int len;
                while((len = bis.read(b)) != -1){
                    bos.writer(b,o,len);
                }
            }finally{
                //4.资源关闭
                //先关闭外层,再关内层
                bos.close();
                bis.close();
                //关闭外层流的同时,内层流会自动关闭
             fw.close();
                fr.close();
            }
        }
    }
    
3.3 DataInputStream/DataOutputStream
  • 都属于**字节流、过滤流**
  • 作为过滤流,是为了给原本的节点流添加读写基本数据类型的功能的
  • 过滤流不能直接连接文件,只能连接其他的流
  • **DataInputStream **不再以-1作为读取结束的标志。如果到了文件结果还尝试进行读取会导致EOFException -> EndOfFileException
import java.io.*;
public class TestDataStream{
	public static void main(String[] args)throws Exception{

		//我们想要把人物等级保存下来~等到明年春暖花开日 再继续游戏~
		/*
		int level = 7365;
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.data"));
		dos.writeInt(level);
		dos.close();
		*/

		DataInputStream dis = new DataInputStream(new FileInputStream("data.data"));
		int x = dis.readInt();
		dis.close();
		System.out.println(x);
	}
}
3.4 ObjectInputStream/ObjectOutputStream
  • 同样是**字节流、过滤流**
  • 为了给原本的节点流添加读取对象的功能的
  • 如果到达文件结尾会触发EOFException

注意点

想要持久化一个对象 必须先要序列化这个类型
如果想要将A类的对象写出到磁盘当中 则A类必须实现序列化接口
implements Serializable
而如果A类当中还有其它引用类型的属性 则这些属性的类型
也要实现序列化接口 否则A对象持久化会出现异常
如果某些属性 无关紧要 不需要保存到文件当中
可以使用transient修饰
transient = 短暂的 转瞬即逝的 = 不参与持久化的
在写出一个对象的时候 transient的属性 将直接写出null
所以这个属性的类型 也就不需要序列化了~

import java.io.*;
import java.text.*;
public class TestObjectStream2{
	public static void main(String[] args){
		Wish myWish = new Wish("能早点在一起上课~网络教学就是坑!有个屁用!","5v");
		System.out.println(myWish);

		//请许下自己的愿望 并且将愿望保存在磁盘文件当中
		try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("月光宝盒.data"))){
			oos.writeObject(myWish);
		}catch(Exception e){
			e.printStackTrace();
		}

	}
}
class Wish implements Serializable{//愿望
	String content;//愿望的内容
	String name;//许愿人姓名
	long time;//许下愿望的时间
	public Wish(String content,String name){
		this.content = content;
		this.name = name;
		time = System.currentTimeMillis();
	}
	@Override
	public String toString(){
		SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
		return content + "\n\t\t\t" + name +"\n\t\t\t" + f.format(time);
	}

}

4 字符流

Reader / Writer 是字符流的抽象基类

4.1FileReader/FileWriter

这两个类只能用来读取文本文件,但是字节流通用语所有文件

.txt .java .html .js .css .jsp .asp .php等

用法用FileInputStream / FileOutputStream类似

4.2 BufferedReader/BufferedWriter
  1. BufferedReader / BufferedWriter

    • 给原本的流添加一个变长的缓冲空间,从而实现以行为单位的读取
    • 文件结束返回null
    import java.io.*;
    public class TestBufferedWriter{
    	public static void main(String[] args)throws Exception{
    		//春眠不觉晓 处处闻啼鸟 夜来风雨声 花落知多少
    		BufferedWriter bw = new BufferedWriter(new FileWriter("鹅鹅鹅.txt"));
    		bw.write("鹅鹅鹅");
    		bw.newLine();//能够写出当前操作系统所匹配的换行标识
    		bw.write("鹅项向天歌");
    		bw.newLine();
    		bw.write("鹅毛浮绿水");
    		bw.newLine();
    		bw.write("鹅可能死了");
    		bw.close();
    	}
    }
    
  2. PrintWiter

    PrintWriter 和BufferedWriter 相比的优势

    1. PrintWriter既可以当做节点流 也可以当做过滤流,构造方法允许传入 File对象 / String路径 / 流!
    2. PrintWriter既可以连接字节流 又可以连接字符流,构造方法既可以传入 FileWriter 也可以传入 FileOutputStream
    3. 当做节点流使用的时候 构造方法第二个参数可以指定字符编码
      new PrintWriter(“鹅鹅鹅.txt”,“utf-8”);
    4. 当做过滤流使用的时候 构造方法第二个参数可以指定自动清空缓冲
      new PrintWriter(new FileWriter(“abc.txt”),true);//autoFlush
    5. 它的println() = write() + newLine()
    import java.io.*;
    public class TestPrintWriter{
    	public static void main(String[] args)throws Exception{
    		PrintWriter pw = new PrintWriter("春晓.txt");
    		pw.println("春眠不觉晓");//write()+newLine();
    		pw.println("处处闻啼鸟");
    		pw.println("夜来风雨声");
    		pw.print("花落知多少");
    		pw.close();
    
    	}
    }
    

5. 转换流

  • 转换流提供了在字节流和字符流之间的转换
  • 通常使用转换流来处理文件乱码问题,
  • 字节大输入流转换成字符输入流**InputStreamReader、字符输出流转换成字节输出流OutputStreamWriter**
public class InputStreamReaderTest{
    public static void main(String[] args) throws IOExecption{
    	FileInputStream fis = new FileInputStream("Test.txt");
        InputStreamReader isr = new InputStreamReader(fis);
        char[] c = new char[10];
        int len;
        while((len = isr.read(c)) != -1){
            String str = new String(c,0,len);
            System.out.println(str);
        }
        isr.close()
    }
}

6. NIO2

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值