Java学习总结(2021版)---IO流

IO流

File的使用

  • File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
  • 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对 象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。

File 类的使用:常用构造器

  • public File(String pathname)
    • 绝对路径/相对路径
  • public File(String parent,String child)
    • 以parent为父路径,child为子路径创建File对象
  • public File(File parent,String child)
    • 根据一个父File对象和子文件路径创建File对象
import java.io.File;

import org.junit.Test;

public class FileTest {
    
    
	@Test
	public void test1() {
    
    
		File file1 = new File("hello.txt");
		File file2 = new File("D:\\workspace_idea1\\JavaSenior\\day08\\he.txt");
		File file3 = new File("D:\\workspace_idea1","JavaSenior");
		File file4 = new File(file3,"hi.txt");
		System.out.println(file4);
	}
}

File 类的使用:路径分隔符

在这里插入图片描述

File 类的使用:常用方法

File类的获取功能
在这里插入图片描述

@Test
    public void test2(){
    
    
        File file1 = new File("hello.txt");
        File file2 = new File("d:\\io\\hi.txt");

        System.out.println(file1.getAbsolutePath());
        System.out.println(file1.getPath());
        System.out.println(file1.getName());
        System.out.println(file1.getParent());
        System.out.println(file1.length());
        System.out.println(new Date(file1.lastModified()));

        System.out.println();

        System.out.println(file2.getAbsolutePath());
        System.out.println(file2.getPath());
        System.out.println(file2.getName());
        System.out.println(file2.getParent());
        System.out.println(file2.length());
        System.out.println(file2.lastModified());
    }
    @Test
    
    public void test3(){
    
    
        File file = new File("D:\\workspace_idea1\\JavaSenior");
        //获取指定目录下的所有文件或者文件目录的名称数组
        String[] list = file.list();
        for(String s : list){
    
    
            System.out.println(s);
        }
        System.out.println();
        //获取指定目录下的所有文件或者文件目录的File数组
        File[] files = file.listFiles();
        for(File f : files){
    
    
            System.out.println(f);
        }

    }

File类的重命名功能

  • public boolean renameTo(File dest):把文件重命名为指定的文件路径
  • 比如:file1.renameTo(file2)为例:要想保证返回true,
  • 需要file1在硬盘中是存在的,且file2不能在硬盘中存在

File类的判断功能
在这里插入图片描述
File类的创建功能
在这里插入图片描述

File类的删除功能
在这里插入图片描述

    @Test
    public void test6() throws IOException {
    
    
        File file1 = new File("hi.txt");
        if(!file1.exists()){
    
    
            //文件的创建
            file1.createNewFile();
            System.out.println("创建成功");
        }else{
    
    //文件存在
            file1.delete();
            System.out.println("删除成功");
        }


    }
    @Test
    public void test7(){
    
    
        //文件目录的创建
        File file1 = new File("d:\\io\\io1\\io3");

        boolean mkdir = file1.mkdir();
        if(mkdir){
    
    
            System.out.println("创建成功1");
        }

        File file2 = new File("d:\\io\\io1\\io4");

        boolean mkdir1 = file2.mkdirs();
        if(mkdir1){
    
    
            System.out.println("创建成功2");
        }
        //要想删除成功,io4文件目录下不能有子目录或文件
        File file3 = new File("D:\\io\\io1\\io4");
        file3 = new File("D:\\io\\io1");
        System.out.println(file3.delete());
    }

创建File对象注意点(是否真实存在)

在这里插入图片描述

举例

1:创建一个与file同目录下的另外一个文件,文件名:haha.txt;

@Test
	public void test7() throws IOException {
    
    
		File file = new File("D:\\IO\\IO1\\hello.txt");
		//创建一个与file同目录下的另外一个文件,文件名:haha.txt;
		File destfileFile = new File(file.getParent(),"haha.txt");//内存层面
		boolean newFile = destfileFile.createNewFile();//硬盘层面
		if(newFile) {
    
    
			System.out.println("创建成功");
		}
	}

2: 判断指定目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称

import org.junit.Test;

import java.io.File;
import java.io.FilenameFilter;
/**
 * 课后练习2:判断指定目录下是否有后缀名为.jpg的文件,如果有,就输出该文件名称
 */
public class FindJPGFileTest {
    
    

	@Test//方法一
	public void test1(){
    
    
		File srcFile = new File("d:\\code");
		
		String[] fileNames = srcFile.list();
		for(String fileName : fileNames){
    
    
			if(fileName.endsWith(".jpg")){
    
    
				System.out.println(fileName);
			}
		}
	}
	@Test//方法二
	public void test2(){
    
    
		File srcFile = new File("d:\\code");
		
		File[] listFiles = srcFile.listFiles();
		for(File file : listFiles){
    
    
			if(file.getName().endsWith(".jpg")){
    
    
				System.out.println(file.getAbsolutePath());
			}
		}
	}
	/*
	 * File类提供了两个文件过滤器方法
	 * public String[] list(FilenameFilter filter)
	 * public File[] listFiles(FileFilter filter)

	 */
	@Test//方法三
	public void test3(){
    
    
		File srcFile = new File("d:\\code");
		
		File[] subFiles = srcFile.listFiles(new FilenameFilter() {
    
    
			
			@Override
			public boolean accept(File dir, String name) {
    
    
				return name.endsWith(".jpg");
			}
		});
		
		for(File file : subFiles){
    
    
			System.out.println(file.getAbsolutePath());
		}
	}
	
}

3: 遍历指定目录所有文件名称,包括子文件目录中的文件。

  • 拓展1:并计算指定目录占用空间的大小
  • 拓展2:删除指定文件目录及其下的所有文件
import java.io.File;
/**
 * 3. 遍历指定目录所有文件名称,包括子文件目录中的文件。
	拓展1:并计算指定目录占用空间的大小
	拓展2:删除指定文件目录及其下的所有文件

 */
public class ListFilesTest {
    
    

	public static void main(String[] args) {
    
    
		// 递归:文件目录
		/** 打印出指定目录所有文件名称,包括子文件目录中的文件 */

		// 1.创建目录对象
		File dir = new File("E:\\teach\\01_javaSE\\_尚硅谷Java编程语言\\3_软件");

		// 2.打印目录的子文件
		printSubFile(dir);
	}

	public static void printSubFile(File dir) {
    
    
		// 打印目录的子文件
		File[] subfiles = dir.listFiles();

		for (File f : subfiles) {
    
    
			if (f.isDirectory()) {
    
    // 文件目录
				printSubFile(f);
			} else {
    
    // 文件
				System.out.println(f.getAbsolutePath());
			}

		}
	}

	// 方式二:循环实现
	// 列出file目录的下级内容,仅列出一级的话
	// 使用File类的String[] list()比较简单
	public void listSubFiles(File file) {
    
    
		if (file.isDirectory()) {
    
    
			String[] all = file.list();
			for (String s : all) {
    
    
				System.out.println(s);
			}
		} else {
    
    
			System.out.println(file + "是文件!");
		}
	}

	// 列出file目录的下级,如果它的下级还是目录,接着列出下级的下级,依次类推
	// 建议使用File类的File[] listFiles()
	public void listAllSubFiles(File file) {
    
    
		if (file.isFile()) {
    
    
			System.out.println(file);
		} else {
    
    
			File[] all = file.listFiles();
			// 如果all[i]是文件,直接打印
			// 如果all[i]是目录,接着再获取它的下一级
			for (File f : all) {
    
    
				listAllSubFiles(f);// 递归调用:自己调用自己就叫递归
			}
		}
	}

	// 拓展1:求指定目录所在空间的大小
	// 求任意一个目录的总大小
	public long getDirectorySize(File file) {
    
    
		// file是文件,那么直接返回file.length()
		// file是目录,把它的下一级的所有大小加起来就是它的总大小
		long size = 0;
		if (file.isFile()) {
    
    
			size += file.length();
		} else {
    
    
			File[] all = file.listFiles();// 获取file的下一级
			// 累加all[i]的大小
			for (File f : all) {
    
    
				size += getDirectorySize(f);// f的大小;
			}
		}
		return size;
	}

	// 拓展2:删除指定的目录
	public void deleteDirectory(File file) {
    
    
		// 如果file是文件,直接delete
		// 如果file是目录,先把它的下一级干掉,然后删除自己
		if (file.isDirectory()) {
    
    
			File[] all = file.listFiles();
			// 循环删除的是file的下一级
			for (File f : all) {
    
    // f代表file的每一个下级
				deleteDirectory(f);
			}
		}
		// 删除自己
		file.delete();
	}

}

IO流原理及流的分类

Java IO原理

在这里插入图片描述

流的分类

在这里插入图片描述

  • 节点流:流直接作用在文件上
  • 处理流:流作用在已有的流基础上
    在这里插入图片描述

IO 流体系

在这里插入图片描述

抽象基类:InputStream(字节) & Reader(字符)(是所有输入流的基类)

  • InputStream(典型实现:FileInputStream
    在这里插入图片描述

  • Reader(典型实现:FileReader
    在这里插入图片描述

抽象基类:OutputStream(字节) & Writer(字符)(是所有输出流的基类)

  • OutputStream(典型实现:FileOutStream
    在这里插入图片描述
  • Writer(典型实现:FileWriter
    在这里插入图片描述

节点流(或文件流)

读取文件:FileReader(字符流)

步骤:

1.建立一个流对象,将已存在的一个文件加载进流

FileReader fr = new FileReader(new File(“Test.txt”));
  • 注意一:可分为两步
//1:实例化File类的对象,需要指明要操作的文件
File file = new File("C:\\Users\\Administrator\\Desktop\\hello.txt");
//2.提供具体的流
FileReader fr = new FileReader(file);

  • 注意2:可直接写成这样
FileReader fr = new FileReader(“Test.txt”);
  • 注意3:指定操作的文件必须存在,否则报错

2.创建一个临时存放数据的数组。

 char[] ch = new char[1024];

3.调用流对象的读取方法将流中的数据读入到数组中。

fr.read(ch);

4. 关闭资源。

fr.close();

举例:将本项目下的hello.txt文件内容读入到程序中并输出到控制台

@Test
    public void testFileReader1()  {
    
    
        FileReader fr = null;
        try {
    
    
            //1.File类的实例化
            File file = new File("hello.txt");

            //2.FileReader流的实例化
            fr = new FileReader(file);

            //3.读入的操作
            //read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1
            char[] cbuf = new char[5];
            int len;
            while((len = fr.read(cbuf)) != -1){
    
    
                //方式一:
                //错误的写法
//                for(int i = 0;i < cbuf.length;i++){
    
    
//                    System.out.print(cbuf[i]);
//                }
                //正确的写法
//                for(int i = 0;i < len;i++){
    
    
//                    System.out.print(cbuf[i]);
//                }
                //方式二:
                //错误的写法,对应着方式一的错误的写法
//                String str = new String(cbuf);
//                System.out.print(str);
                //正确的写法
                String str = new String(cbuf,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if(fr != null){
    
    
                //4.资源的关闭
                try {
    
    
                    fr.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }

    }

注意:正确与错误的写法对比

写入文件:FileWriter(字符流)

步骤:

1.创建流对象,建立数据存放文件

 FileWriter fw = new FileWriter(new File(“Test.txt”));
  • 注意1:文件可以不存在,不会报异常,会自动创建
  • 注意2:FileWrite(file) = FileWrite(file ,false)对原有文件进行完全覆盖
  • 注意3:FileWrite(file ,true)对原有文件进行追加

2.调用流对象的写入方法,将数据写入流

fw.write(“atguigu-songhongkang”);
  • 注意1:可以多次调用

3.关闭流资源,并将流中的数据清空到文件中。

fw.close();

举例:从内存中写出数据到硬盘的文件里。

@Test
    public void testFileWriter() {
    
    
        FileWriter fw = null;
        try {
    
    
            //1.提供File类的对象,指明写出到的文件
            File file = new File("hello1.txt");

            //2.提供FileWriter的对象,用于数据的写出
            fw = new FileWriter(file,false);

            //3.写出的操作
            fw.write("I have a dream!\n");
            fw.write("you need to have a dream!");
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //4.流资源的关闭
            if(fw != null){
    
    

                try {
    
    
                    fw.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
        }


    }

举例:使用FileReader和FileWriter实现文本复制。

@Test
    public void testFileReaderFileWriter() {
    
    
        FileReader fr = null;
        FileWriter fw = null;
        try {
    
    
            //1.创建File类的对象,指明读入和写出的文件
            File srcFile = new File("C:\\Users\\Administrator\\Desktop\\hello.txt");
            File destFile = new File("C:\\Users\\Administrator\\Desktop\\hellocopy.txt");

            //不能使用字符流来处理图片等字节数据
//            File srcFile = new File("爱情与友情.jpg");
//            File destFile = new File("爱情与友情1.jpg");


            //2.创建输入流和输出流的对象
            fr = new FileReader(srcFile);
            fw = new FileWriter(destFile);


            //3.数据的读入和写出操作
            char[] cbuf = new char[5];
            int len;//记录每次读入到cbuf数组中的字符的个数
            while((len = fr.read(cbuf)) != -1){
    
    
                //每次写出len个字符
                fw.write(cbuf,0,len);

            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //4.关闭流资源
            //方式一:
//            try {
    
    
//                if(fw != null)
//                    fw.close();
//            } catch (IOException e) {
    
    
//                e.printStackTrace();
//            }finally{
    
    
//                try {
    
    
//                    if(fr != null)
//                        fr.close();
//                } catch (IOException e) {
    
    
//                    e.printStackTrace();
//                }
//            }
            //方式二:
            try {
    
    
                if(fw != null)
                    fw.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }

            try {
    
    
                if(fr != null)
                    fr.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }

        }

    }

读取/写入文件文件:FileInputStream/FileOutputStream(字节流)

举例:使用字节流FileInputStream处理文本文件,可能出现乱码。

举例:实现对图片的复制操作

/*
    实现对图片的复制操作
     */
    @Test
    public void testFileInputOutputStream()  {
    
    
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
    
    
            //
            File srcFile = new File("C:\\Users\\Administrator\\Desktop\\test.png");
            File destFile = new File("C:\\Users\\Administrator\\Desktop\\爱情与友情2.png");

            //
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);

            //复制的过程
            byte[] buffer = new byte[5];
            int len;
            while((len = fis.read(buffer)) != -1){
    
    
                fos.write(buffer,0,len);
            }

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if(fos != null){
    
    
                //
                try {
    
    
                    fos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(fis != null){
    
    
                try {
    
    
                    fis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }

    }

举例:指定路径下文件的复制(传参)

//指定路径下文件的复制
    public void copyFile(String srcPath,String destPath){
    
    
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
    
    
            //
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);

            //
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(destFile);

            //复制的过程
            byte[] buffer = new byte[1024];
            int len;
            while((len = fis.read(buffer)) != -1){
    
    
                fos.write(buffer,0,len);
            }

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if(fos != null){
    
    
                //
                try {
    
    
                    fos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(fis != null){
    
    
                try {
    
    
                    fis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }


    }

    @Test
    public void testCopyFile(){
    
    

        long start = System.currentTimeMillis();

        String srcPath = "C:\\Users\\Administrator\\Desktop\\01-视频.avi";
        String destPath = "C:\\Users\\Administrator\\Desktop\\02-视频.avi";


//        String srcPath = "hello.txt";
//        String destPath = "hello3.txt";

        copyFile(srcPath,destPath);


        long end = System.currentTimeMillis();

        System.out.println("复制操作花费的时间为:" + (end - start));//618

    }

注意:System.currentTimeMillis();计算复制操作花费时间

缓冲流

缓冲流理解

在这里插入图片描述
在这里插入图片描述

  • 注意1:向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,
    BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流
  • 注意3:关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也
    会相应关闭内层节点流

举例:实现非文本文件的复制

/*
    实现非文本文件的复制
     */
    @Test
    public void BufferedStreamTest() throws FileNotFoundException {
    
    
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
    
    
            //1.造文件
            File srcFile = new File("爱情与友情.jpg");
            File destFile = new File("爱情与友情3.jpg");
            //2.造流
            //2.1 造节点流
            FileInputStream fis = new FileInputStream((srcFile));
            FileOutputStream fos = new FileOutputStream(destFile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节:读取、写入
            byte[] buffer = new byte[10];
            int len;
            while((len = bis.read(buffer)) != -1){
    
    
                bos.write(buffer,0,len);

//                bos.flush();//刷新缓冲区

            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //4.资源关闭
            //要求:先关闭外层的流,再关闭内层的流
            if(bos != null){
    
    
                try {
    
    
                    bos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            if(bis != null){
    
    
                try {
    
    
                    bis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
//        fos.close();
//        fis.close();
        }


举例:实现文件复制的方法

//实现文件复制的方法
    public void copyFileWithBuffered(String srcPath,String destPath){
    
    
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
    
    
            //1.造文件
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);
            //2.造流
            //2.1 造节点流
            FileInputStream fis = new FileInputStream((srcFile));
            FileOutputStream fos = new FileOutputStream(destFile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节:读取、写入
            byte[] buffer = new byte[1024];
            int len;
            while((len = bis.read(buffer)) != -1){
    
    
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //4.资源关闭
            //要求:先关闭外层的流,再关闭内层的流
            if(bos != null){
    
    
                try {
    
    
                    bos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            if(bis != null){
    
    
                try {
    
    
                    bis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
//        fos.close();
//        fis.close();
        }
    }

    @Test
    public void testCopyFileWithBuffered(){
    
    
        long start = System.currentTimeMillis();

        String srcPath = "C:\\Users\\Administrator\\Desktop\\01-视频.avi";
        String destPath = "C:\\Users\\Administrator\\Desktop\\03-视频.avi";


        copyFileWithBuffered(srcPath,destPath);


        long end = System.currentTimeMillis();

        System.out.println("复制操作花费的时间为:" + (end - start));//618 - 176
    }

举例:使用BufferedReader和BufferedWriter实现文本文件的复制

/*
    使用BufferedReader和BufferedWriter实现文本文件的复制

     */
    @Test
    public void testBufferedReaderBufferedWriter(){
    
    
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
    
    
            //创建文件和相应的流
            br = new BufferedReader(new FileReader(new File("dbcp.txt")));
            bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));

            //读写操作
            //方式一:使用char[]数组
//            char[] cbuf = new char[1024];
//            int len;
//            while((len = br.read(cbuf)) != -1){
    
    
//                bw.write(cbuf,0,len);
//    //            bw.flush();
//            }

            //方式二:使用String
            String data;
            while((data = br.readLine()) != null){
    
    
                //方法一:
//                bw.write(data + "\n");//data中不包含换行符
                //方法二:
                bw.write(data);//data中不包含换行符
                bw.newLine();//提供换行的操作

            }


        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            //关闭资源
            if(bw != null){
    
    

                try {
    
    
                    bw.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }
            }
            if(br != null){
    
    
                try {
    
    
                    br.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }

    }

举例:图片的加密与解密(互为逆过程)

加密操作

import org.junit.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * @author shkstart
 * @create 2019 下午 4:08
 */
public class PicTest {
    
    

    //图片的加密
    @Test
    public void test1() {
    
    

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
    
    
            fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\test11xing.png");
            fos = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test22.png");

            byte[] buffer = new byte[20];
            int len;
            while ((len = fis.read(buffer)) != -1) {
    
    
                //字节数组进行修改
                //错误的
                //            for(byte b : buffer){
    
    
                //                b = (byte) (b ^ 5);
                //            }
                //正确的
                for (int i = 0; i < len; i++) {
    
    
                    buffer[i] = (byte) (buffer[i] ^ 5);
                }


                fos.write(buffer, 0, len);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (fos != null) {
    
    
                try {
    
    
                    fos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            if (fis != null) {
    
    
                try {
    
    
                    fis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }
    } 

解密操作

 //图片的解密
    @Test
    public void test2() {
    
    

        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
    
    
            fis = new FileInputStream("C:\\Users\\Administrator\\Desktop\\test22.png");
            fos = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test11xing.png");

            byte[] buffer = new byte[20];
            int len;
            while ((len = fis.read(buffer)) != -1) {
    
    
                //字节数组进行修改
                //错误的
                //            for(byte b : buffer){
    
    
                //                b = (byte) (b ^ 5);
                //            }
                //正确的
                for (int i = 0; i < len; i++) {
    
    
                    buffer[i] = (byte) (buffer[i] ^ 5);
                }

                fos.write(buffer, 0, len);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if (fos != null) {
    
    
                try {
    
    
                    fos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
            if (fis != null) {
    
    
                try {
    
    
                    fis.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }


    }
}

转换流

  • 字节流和字符流之间的转换

InputStreamReader:将InputStream转换为Reader

  • 字节流中的数据都是字符时,转成字符流操作更高效。
  • 实现将字节的输入流按指定字符集转换为字符的输入流
  • 需要和InputStream“套接”。

OutputStreamWriter:将Writer转换为OutputStream

  • 实现将字符的输出流按指定字符集转换为字节的输出流。
  • 需要和OutputStream“套接”。

举例:综合使用InputStreamReader和OutputStreamWriter

@Test
    public void test2()  {
    
    
        //1.造文件、造流
        InputStreamReader isr = null;
		OutputStreamWriter osw = null;
		try {
    
    
			File file1 = new File("C:\\Users\\Administrator\\Desktop\\hellocopy.txt");
			File file2 = new File("C:\\Users\\Administrator\\Desktop\\hellocopy222.txt");

			FileInputStream fis = new FileInputStream(file1);
			FileOutputStream fos = new FileOutputStream(file2);

			isr = new InputStreamReader(fis,"utf-8");
			osw = new OutputStreamWriter(fos,"gbk");

			//2.读写过程
			char[] cbuf = new char[20];
			int len;
			while((len = isr.read(cbuf)) != -1){
    
    
			    osw.write(cbuf,0,len);
			}
		
		} catch (IOException e) {
    
    
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
    
    
			if(isr != null) {
    
    
				try {
    
    
					isr.close();
					
				}catch (IOException e) {
    
    
					e.printStackTrace();
				}
			}
		}
			if(osw != null) {
    
    
			try {
    
    
				osw.close();
				
			}catch (IOException e) {
    
    
				e.printStackTrace();
			}
		}
    }
}

补充:字符编码

标准输入、输出流------了解

对象流

强大之处:把内存中的对象存到硬盘中

序列化:用ObjectOutputStream类从内存写入硬盘

序列化机制:

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。

  • 注意序列化后,并不能查看,是乱码。如需查看需要用反序列化机制
/*
    序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
    使用ObjectOutputStream实现
     */
    @Test
    public void testObjectOutputStream(){
    
    
        ObjectOutputStream oos = null;

        try {
    
    
            //1.造流造对象
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            //2.写到硬盘
            oos.writeObject(new String("我爱北京天安门"));
            oos.flush();//刷新操作

            oos.writeObject(new Person("王铭",23));
            oos.flush();

            oos.writeObject(new Person("张学良",23,1001,new Account(5000)));
            oos.flush();

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if(oos != null){
    
    
                //3.
                try {
    
    
                    oos.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }

    }

自定义类实现序列化需要满足的条件

  • 需要实现接口:Serializable
  • 2.当前类提供一个全局常量:serialVersionUID
  • 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。(默认情况下,基本数据类型可序列化)
  • ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
    在这里插入图片描述

反序列化:用ObjectInputStream类从硬盘读取到内存

/*
    反序列化:将磁盘文件中的对象还原为内存中的一个java对象
    使用ObjectInputStream来实现
     */
    @Test
    public void testObjectInputStream(){
    
    
        ObjectInputStream ois = null;
        try {
    
    
            ois = new ObjectInputStream(new FileInputStream("object.dat"));

            Object obj = ois.readObject();
            String str = (String) obj;

            Person p = (Person) ois.readObject();
            Person p1 = (Person) ois.readObject();

            System.out.println(str);
            System.out.println(p);
            System.out.println(p1);

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            if(ois != null){
    
    
                try {
    
    
                    ois.close();
                } catch (IOException e) {
    
    
                    e.printStackTrace();
                }

            }
        }



    }

随机存取文件流

  • RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并
    且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也
    可以写
  • RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意
    地方来读、写文件
    • 支持只访问文件的部分内容
    • 可以向已存在的文件后追加内容

在这里插入图片描述

既可以读也可以写

在这里插入图片描述

使用RandomAccessFile实现数据的插入效果

在这里插入图片描述
未插入前:
在这里插入图片描述

插入后:
在这里插入图片描述

问题:只能实现对原文件的覆盖,不想覆盖,想实现插入

完善:真正实现插入
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_51755061/article/details/114227108