java代码实现复制一个文件夹&独特流中的内存流、打印流、对象流(序列化和反序列化)

本文深入讲解Java中的IO流概念,包括内存流、打印流、对象流等,详细介绍了各种流的使用方法,如ByteArrayOutputStream、PrintStream、ObjectOutputStream等,并探讨了序列化、反序列化及对象持久化的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.内存流:ByteArrayOutputStream,内存流效率高.内存流关闭无效.

eg:public static void main(String[] args) throws IOException {
		//1.创建流对象
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		//2.用流对象向内存中写入内容
		baos.write("abdefefefeefefefeffef我是中国人,我爱中国.写个50个字符试试,试试就试试.我爱学习,学习爱我.我想静静,静静是谁".getBytes());
		System.out.println("内容写入成功");
		//3.关流
		baos.close();
		
		//第一种:获得内存输出流中数据toByteArray()
		byte[] content=baos.toByteArray();	
		String s1=new String(content);
		System.out.println("第一种:"+s1);
		
		//第二种:获得内存输出流中数据toString()
		String s2=baos.toString();
		System.out.println("第二种:"+s2);
		
		//第三种:获得内存输出流中数据,将数据写入到文件中writeTo()
		baos.writeTo(new FileOutputStream("aa"+File.separator+"a1.txt"));
		System.out.println("第三种获得数据写入文件成功");
		
		/*第四种:用内存读取流来读取内存中数据*/
		//创建流对象
        ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
		//准备一个数组
		byte[] b=new byte[1024];
		//用流对象调用方法读取数据,返回读取的长度,读取的内容存在数组中
		int len;
		while ((len=bais.read(b))!=-1) {
			//将读取的内容转换字符串输出
			String s4=new String(b, 0, len);
			System.out.println(s4);
		}
		System.out.println("第四种读取完毕");
		//关流
		bais.close();
	}

2.打印流:

2.1:字节打印流:PrintStream

eg:public static void main(String[] args) {
		//声明流对象
		PrintStream ps1=null;
		try {
			//1.创建流对象
			ps1=new PrintStream("aa"+File.separator+"a2.txt");
			//2.用流对象向文件中写入内容
			ps1.append("第一阶段Java注重规范和语法");
			ps1.print("第二阶段Java注重项目综合能力及调试bug能力");
			ps1.println("第三阶段Java注重企业级开发,框架使用及团队开发");
			ps1.write("第四阶段Java注重分布式和微服务开发,注重项目性能".getBytes());
			ps1.printf("%.2f", 3.1415926);
			System.out.println("写入成功!");
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//3.关流
			if (ps1!=null) {
				ps1.close();
			}
		}
		}

2.2:字符打印流:PrintWriter

eg:public static void main(String[] args) {
	//声明流对象
	PrintWriter pw=null;
	try {
		//1.创建流对象
		pw=new PrintWriter("aa"+File.separator+"a3.txt");
		//2.用流对象向文件中写入内容
		pw.append("第一阶段Java注重规范和语法");
		pw.print("第二阶段Java注重项目综合能力及调试bug能力");
		pw.println("第三阶段Java注重企业级开发,框架使用及团队开发");
		pw.write("第四阶段Java注重分布式和微服务开发,注重项目性能");
		pw.printf("%.2f", 3.1415926);
		pw.printf("%d%%", 50);
		System.out.println("写入成功!");
	} catch (Exception e) {
		e.printStackTrace();
	}finally {
		//3.关流
		if (pw!=null) {
			pw.close();
		}
	}
}

2.3:输出重定向(重新定义一个方向输出):将原来在控制台输出的内容,改变方向,写入到文件中.

eg:public static void main(String[] args) throws IOException {
		//声明一个存原来打印输出流对象
		PrintStream p1=System.out;
		//输出重定向,输出到文件中
		System.setOut(new PrintStream("aa"+File.separator+"a4.txt"));
		//输出内容
		System.out.append("别无我有");
		System.out.print("别有我优");
		System.out.println("无所畏惧");
		System.out.write("别优我精".getBytes());
		System.out.printf("%.3f", 3.141592631415927);
		
		//输出重定向,重新输出到控制台
		System.setOut(p1);
		System.out.println("今天中午乌云散去了");
		System.out.println("控制台,我又回来了");
	}

2.4:输入重定向(重新定义一个方向来接收数据):将原来从控制台接收的数据,改变方向,从文件中接收数据.

  eg:public static void main(String[] args) throws FileNotFoundException {
		//声明一个变量存标准输入流
		InputStream is=System.in;
		//输入重定向,在文件中接收数据
		System.setIn(new FileInputStream("aa"+File.separator+"a5.txt"));
		
		//创建Scanner类的对象,输入一个输入流作为参数,调用方法从键盘上接收数据
		Scanner input=new Scanner(System.in);
		System.out.println("请输入姓名:");
		String sname=input.next();
		System.out.println("请输入爱好:");
		String shobby=input.next();
		System.out.println("接收姓名为:"+sname+",爱好为:"+shobby);
		
		//输入重定向,重新在控制台接收数据
		Scanner input2=new Scanner(is);
		System.out.println("请输入一句话:");
		String word=input2.next();
		System.out.println("接收话为:"+word);
	}

3.对象流:用来程序间交换数据.

3.1:序列化:将程序(内存)中对象存到磁盘的文件中,叫序列化.

持久化:将内存中短暂存储的数据存长久存储的磁盘上叫持久化.

反序列化:将磁盘上文件中对象读取到程序(内存)中,叫反序列化.

3.2:对象输出流:ObjectOutputStream

注意:对象输出流向文件中写入对象的过程,其实就是序列化.

eg:public static void main(String[] args) throws IOException {
		//声明流对象
		ObjectOutputStream oos=null;
		
		try {
			//1.创建流对象
			oos=new ObjectOutputStream(new FileOutputStream("aa"+File.separator+"a6"+File.separator+"a11.txt"));
			/*2.用流向文件中写入对象*/
			
			//第一种:写入字符串对象
			String word1="先死后活,死去活来";	
			//将字符串对象写入文件中
			oos.writeObject(word1);
			
			//第二种:写入自定义的对象
			Student stu1=new Student("赵天", 18,"girl");
			//将自定义对象写入文件中
			oos.writeObject(stu1);
			
			//第三种:写入多个对象存到集合中,再将集合写入到文件中
			//创建一个集合
			List<Student> stuList=new ArrayList();
			stuList.add(new Student("张三", 11, "man"));
			stuList.add(new Student("李四", 21, "man"));
			stuList.add(new Student("王五", 31, "man"));
			//将对象集合写入文件中
			oos.writeObject(stuList);
			
			System.out.println("写入成功");
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//3.关流
			if (oos!=null) {
				oos.close();
			}
		}
	}

3.3:对象输入流:ObjectInputStream

注意:对象输入流将文件中数据读取到程序中过程,其实就反序列化.

eg:public static void main(String[] args) throws IOException {
		//声明流对象
		ObjectInputStream ois=null;
		
		try {
			//1.创建流对象
			ois=new ObjectInputStream(new FileInputStream("aa"+File.separator+"a6"+File.separator+"a11.txt"));
			/*2.用流来读取文件中对象*/
			
			//第一种:读取一个字符串对象
			Object word2=ois.readObject();
			//System.out.println("读取的内容为:"+word2);
			
			//第二种:读取写入的自定义的对象
			Student stu2=(Student) ois.readObject();
			System.out.println(stu2);
			
			//第三种:读取,写入多个对象存到集合中,再将集合写入到文件中
			List<Student> stulist2=(List<Student>) ois.readObject();
			for (Student stu : stulist2) {
				System.out.println(stu);
			}
			
			System.out.println("读取完毕");
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//3.关流
			if (ois!=null) {
				ois.close();
			}
		}
	}

3.4:对象输入流读取的方法与对象输出流写入的方法类型要一致,否则会报错EOFException.(write数据类型()和read数据类型()这两个方法的数据类型要一致)

3.5:只有实现序列化接口java.io.Serializable接口的类的对象,才能(序列化)用对象输出流写入到文件中.

3.6:版本号错误:local class incompatible: stream classdesc serialVersionUID = -1243946572963888417, local class serialVersionUID = 3821573340049539149

操作:先将学生类的一个对象进行序列化(用对象输出流存到文件中),再修改学生类,再将现在的学生类反序列化取数据,就报版本号错误.

原因:学生类只实现序列化接口,但是没有因定化序列化版本号,这样学生类每修改一次就会重新产生一个新的序列化版本号,如果你用原来序列化版本号对应类的对象存的数据,用新的序列化版本号就取不出数据.

解决:给每个序列化类固定版本号.

eg:	private static final long serialVersionUID = -1243946572963888417L;

3.7:如果序列化类中属性不想实现序列化,就用static或transient来修饰就可以

eg:
private static String sex;
private transient String sex;

3.8:如果想用对象流存多个对象到文件中,可以先将多个对象存在集合中,再把集合存到文件中.

java代码实现复制一个文件夹(文件夹可以有子子孙孙文件或目录)

package com.qf.day28.zy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * 2.复制一个文件夹(文件夹可以有子子孙孙文件或目录)
 * 分析:文件夹只能创建不能复制,想复制,用代码构造文件夹来创建
 * 		文件夹中文件的复制,用IO流复制
 */
public class Zy2 {

	public static void main(String[] args) {
		//原文件夹
		File sourceFile=new File("aa");
		//目录文件夹
		File destFile=new File("bb");
		//调用文件夹复制方法
		if (sourceFile.isDirectory()&&destFile.isDirectory()) {
			copyFold(sourceFile,destFile);
			System.out.println("文件夹拷贝成功");
		}else {
			System.out.println("原文件夹或目标文件夹不是文件夹");
		}
	}

	/**
	 * 复制文件夹
	 * @param sourceFile
	 * @param destFile
	 */
	public static void copyFold(File sourceFile, File destFile) {//sourceFile=aa,destFile=bb
		//构造文件夹对象
		File f1=new File(destFile, sourceFile.getName());//bb\\aa
		if (!f1.exists()) {//如果文件夹不存在就创建
			f1.mkdirs();
		}
		
		//获得原文件夹下面所子元素
		File[] fileList=sourceFile.listFiles();
		//遍历子元素
		for (File f2 : fileList) {
			if (f2.isDirectory()) {//文件夹,复制
				copyFold(f2,f1); 
			} else {//文件复制
				copyFile(f2,f1);
			}
		}
		
	}

	/**
	 * 复制文件
	 * @param f2 要复制文件
	 * @param f1 目录文件夹
	 */
	private static void copyFile(File f2, File f1) {
		//声明流对象
		FileInputStream fis=null;
		FileOutputStream fos=null;
		
		try {
			//1.创建输入流和输出流对象
			fis=new FileInputStream(f2);
			fos=new FileOutputStream(new File(f1, f2.getName()));
			/*用流边读取边写入*/
			//准备一个数组
			byte[] b=new byte[1024];
			//先读取一次,返回读取的长度,读取的内容存到数组中
			int len=fis.read(b);
			//判断,接着读
			while (len!=-1) {
				//将读取的内容写入到文件中
				fos.write(b, 0, len);
				//接着读
				len=fis.read(b);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//3.关流
			try {
				if (fis!=null) {
					fis.close();
				}
				if (fos!=null) {
					fos.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值