【Java基础21】文件与I/O,装饰者模式

本文详细介绍了Java中File类的基本方法,如创建、删除、重命名文件,以及列举文件等。接着,深入讲解了I/O流的概念,包括字节流和字符流的使用,如FileInputStream、FileOutputStream、FileReader、FileWriter等,并展示了文件复制的实例。此外,还提到了缓冲流、打印流、对象流和数据流的使用,以及File工具类和装饰者模式的应用。

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

一、File类

1、基本方法

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class Test01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file=new File("E:\\JavaProject\\Test01");
		if(!file.exists()){
			try{
				file.createNewFile();
				System.out.println("文件创建成功");
			}catch(IOException e){
				e.printStackTrace();
			}
		}
		System.out.println(file.isFile());//判断是否为文件
		System.out.println(file.isDirectory());//判断是否为文件夹
		
//		file.delete();
		if(!file.exists()){
			System.out.println("文件删除成功!");
		}
		
		//列出当前文件夹所有文件的文件名
		boolean flag=file.isDirectory();
		if(flag==true){
			String[] str=file.list();
			System.out.println(Arrays.toString(str));
		}
		
		//列出当前文件夹所有文件,以对象返回
		File[] f1=file.listFiles();
		for(File f:f1){
			System.out.println(f.getName()+f.getAbsolutePath()+f.toString());
			Date date=new Date(f.lastModified());
			DateFormat df=new SimpleDateFormat("HH:mm:ss");
			System.out.println("文件最后修改时间="+df.format(date));
			
		}
		
		
		
		//创建文件夹
		File f2=new File("E:\\JavaProject\\Test11");
		f2.mkdir();
		if(f2.isDirectory()){
			System.out.println("创建文件夹成功!");
		}
		
		//重命名
		f2.renameTo(new File("E:\\JavaProject\\Test10"));
		
		//过滤器,只输出TXT文件
		File f3=new File("E:\\JavaProject\\Test01");
	/*	File[] files=f3.listFiles(new FileFilter(){
			public boolean accept(File pathname){
				return pathname.getName().endsWith(".txt");
			}
		});*/
		File[] files=f3.listFiles((pathname)->pathname.getName().endsWith(".txt"));//lambda表达式
		for(File f:files){
			System.out.println(f.getName());
		}
}

}

2、实例

//在指定的目录中查找文件
import java.io.File;

public class Test02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FindFile(new File("C:\\Users\\Administrator\\Desktop\\Desktop"),".jpg");
	}
	
	public static void FindFile(File target,String ext){
		if(target==null) return;
		if(target.isDirectory()){
			File[] f=target.listFiles();
			if(f!=null){
				for(File f1:f){
					FindFile(f1,ext);
				}
			}
		}else{
			String name=target.getName().toLowerCase();
//			System.out.println(name);
			if(name.endsWith(ext)){
				System.out.println(target.getAbsolutePath());
			}
		}
	}
}

二、I/O流

(1)流的定义:流是一组有顺序的,有起点和终点的字节的集合,是对数据传输的总称或抽象。即数据在两设备见的传输称为流。流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

(2)IO流的分类:

根据处理数据类型的不同分为:字符流和字节流

根据数据流向不同分为:输入流和输出流(相对程序而言)

(3)一般操作非文本文件时,使用字节流,操作文本文件时,使用字符流。

(4)字符流的内部实现还是字节流。

1、字节流

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.print.attribute.standard.OutputDeviceAssigned;

import org.xml.sax.InputSource;

public class Test03 {
//I/O流
   public static void main(String[] args) throws FileNotFoundException {
   	// TODO Auto-generated method stub
   	output();
   	input();
   }
   
   public static void output(){
   	//1、确定进行操作的文件
   	File file=new File("E:\\JavaProject\\Test01.txt");
   	//2、构建输出的对象
   	try{
   		OutputStream os=new FileOutputStream(file);
   		String str="把键盘敲烂!!!!";
   		os.write(str.getBytes());
   		os.close();//关闭流
   		System.out.println("写入成功!");
   	}catch(IOException e){
   		e.printStackTrace();
   	}
   }
   
   //输入
public static void input() throws FileNotFoundException{
   	File file1=newFile("E:\\JavaProject\\Test01.txt");
   	try{
   		//输入数据,一个字节一个字节读
   		InputStream is=new FileInputStream(file1);	
   		
   		byte[] bytes=new byte[1024];//每次读1024个字节
   		StringBuilder sb=new StringBuilder();
   		int len=-1;
   		while((len=is.read(bytes))!=-1){//返回读入的字节数并与-1比较,等于-1说明读入数据
   			sb.append(new String(bytes));//输出
   		}
   		System.out.println(sb);
   		
   	}catch(FileNotFoundException e){
   		e.printStackTrace();
   	} catch (IOException e) {
   		// TODO Auto-generated catch block
   		e.printStackTrace();
   	}
   }

}

字节操作流,默认每次执行写入操作会直接把数据写入文件。

2、字符流

Writer流和Reader流,使用FileWriter和FileReader进行实例化。

public static void writer(){
		File f1=newFile("E:\\JavaProject\\Test02.txt");
		try {
			Writer w=new FileWriter(f1);
			w.write("把键盘敲烂!!!");
			w.close();
			System.out.println("写入成功!");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
public static void reader(){
		File f2=newFile("E:\\JavaProject\\Test02.txt");
		try{
			Reader r=new FileReader(f2);
			char[] c=new char[1];
			StringBuilder sb=new StringBuilder();
			int len=-1;
			while((len=r.read(c))!=-1){
				sb.append(new String(c,0,len));
			}
			r.close();
			System.out.println(sb);
		}catch(FileNotFoundException e){
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

文件字符操作流自带一个缓存,默认大小1024字节,在缓存满后,或手动刷新,或关闭流时会把数据写入文件。

3、文件复制实例

//文件复制
import java.io.*;
public class Test01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		copy("E:\\JavaProject\\Test01.txt","E:\\JavaProject\\Test02.txt");
		System.out.println("复制成功!");
	}
	
	public static void copy(String src,String target){
		File f1=new File(src);
		File f2=new File(target);
		InputStream is=null;
		OutputStream os=null;
		try {
			is=new FileInputStream(f1);
			os=new FileOutputStream(f2);
			byte[] b=new byte[1024];
			int len=-1;
			while((len=is.read(b))!=-1){
				os.write(b,0,len);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try {
				if(is!=null) is.close();
				if(os!=null) os.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}

4、字节字符转换流

import java.io.*;

//字节流转换为字符流
public class Test02 {

	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		InputStream is=new FileInputStream("E:\\JavaProject\\Test01.txt");
		InputReader(is);
		OutputStream os=new FileOutputStream("E:\\JavaProject\\Test03.txt");
		OutputWriter(os);
	}
	
	public static void InputReader(InputStream is) throws IOException{
		Reader reader=new InputStreamReader(is);
		char[] c=new char[1024];
		reader.read(c);
		System.out.println(c);
	}
	
	public static void OutputWriter(OutputStream os) throws IOException{
		Writer writer=new OutputStreamWriter(os);
		writer.write("1234567");
		writer.close();
	}

}

5、缓冲流

(1)缓冲的目的是解决在写入文件时频繁地操作文件所带来的的性能降低的问题。

(2)BufferedOutputStream内部默认缓存大小是8KB,但可以手动指定缓存大小,每次写入存储到缓存中的byte数组中,当数组存满后,会把数据写入文件,并且缓存下标归零。

(3)JDK1.7新语法:try(),try方法会自动关闭()内的文件。

(4)格式:字符流和字节流同理

File file=new File(“绝对路径”);

OutputStrram os=new FileOutputStream(“file”);

BufferedOutputStream b=new BufferedOutputStream(os);

6、打印流

格式:字符流和字节流同理(只有输出没有输入)

File file=new File(“绝对路径”);

OutputStrram os=new FileOutputStream(“file”);

BufferedOutputStream b=new BufferedOutputStream(os);

PrintStream ps=new PrintStream(b);

ps.println(" ");

7、对象流

(1)对象流的两个类:ObjectInputStream、ObjectOutputStream

(2)序列化一组对象可采用对象数组的形式,因为对象数组可以向Object进行转型操作。同时序列化多个对象时,反序列化也必须按顺序操作。

(3)对象序列化保存的是对象的状态,即对象序列化不会关注类中的静态变量。

(4)写:序列化 读:反序列化

(5)什么时候对象需要序列化:1、把对象保存在文件中 2、文件需要在网络上传输

//对象流
import java.io.*;
public class Test03 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Serializable();
		DeSerializable();
	}
	public static void DeSerializable(){
		Pet pet=new Pet("小小",3);
		File f1=new File("E:\\JavaProject\\pet.txt");
		try {
			InputStream is=new FileInputStream(f1);
			ObjectInputStream ois=new ObjectInputStream(is);
			Pet pet1=(Pet)ois.readObject();
			System.out.println(pet);
			ois.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public static void Serializable(){
		Pet pet=new Pet("小小",3);
		Pet pet2=new Pet("大大",3);
		Pet[] pets={pet,pet2};
		File f1=new File("E:\\JavaProject\\pet.txt");
		try {
			OutputStream os=new FileOutputStream(f1);
			ObjectOutputStream oos=new ObjectOutputStream(os);
			oos.writeObject(pets);
			oos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

}

class Pet implements Serializable{
	private String name;
	private int age;
	private transient int id;//在序列化中被忽略
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Pet(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Pet [name=" + name + ", age=" + age + "]";
	}
	public Pet() {
	}
	
}

8、字节数组流

**ByteArrayInputStream:**包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read方法要提供的下一个字节。关闭ByteArrayInputStream无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何的IOException。

**ByteArrayOutputStream:**此类实现了一个输出流,其中的数据被写入一个byte数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()和toString()获取数据。关闭ByteArrayOutputStream无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException。

9、数据流

**DataInputStream:**数据输入流允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。DataInputStream对于多线程访问不一定是安全的。线程安全是可选的,它由此类方法的使用者负责。

**DataOutputStream:**数据输出流运行应用程序以适当方式将基本Java数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

10、其他流

(1)字符串流:StringReader/StringWriter
流标记器:StreamTokenizer
(2)管道流:数据由某个线程从PipedInputStream对象读取,并由其他线程写入相应的输出流。

11、文件压缩和解压

ZipOutputStream (压缩)、ZipInputStream(解压缩)

三、File工具类

使用File工具类可代理I/O流的操作,具体参考jdk API文档。

四、装饰者模式

1、概念

意图: 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。该模式以 对和客户端透明的方式扩展对象的功能。

适用环境: 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。处理那些可以撤销的职责。当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类使得子类数目呈爆炸式增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

2、实例

在这里插入图片描述

3、要点

OO原则:动态地将责任附加到对象身上。想要扩展功能,装饰者提供有别于继承的另一种选择。

(1)继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案。

(2)在我们的设计中,应该允许行为可以被扩展,而不须修改现有的代码。

(3)组合和委托可用于在运行时动态地加上新的行为。

(4)除了继承,装饰者模式也可以让我们扩展行为。

(5)装饰者模式意味着一群装饰者类,这些类用来包装具体组件。

(6)装饰者类反映出被装饰的组件类型(实际上,他们具有相同的类型,都经过接口或继承实现)

(7)装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。

(8)你可以有无数个装饰者包装一个组件。
(9)装饰者一般对组建的客户是透明的,除非客户程序依赖于组件的具体类型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值