IO 框架

IO框架

File类

  • 表示文件和目录路径名的抽象表示形式
  • 可以实现文件的创建、删除、重命名、得到路径、创建时间等,是唯一与文件本身有关的操作类
public static final String separator   //表示路径分隔符“\”
public File(String pathname)    //构造File类实例,要传入路径
public boolean createNewFile()   //创建新文件
public boolean delete()    //删除文件
public boolean isDirectory()  //判断给定的路径是否是文件夹
    
public boolean isFile()  //判断给定的路径是否是文件
public String[] list()   //列出文件夹中的文件
public File[] listFiles()  //列出文件夹中的所有文件
public boolean mkdir()  //创建新的文件夹
public boolean renameTo(File dest)  //为文件重命名
public long length()   //返回文件大小
String getPath()  //路径名字符串
//方法代码示例
public class FileDemo {

	public static void main(String[] args) {
		//"E:/test/test.txt"
		//"E:\\test\\test.txt"
		File f1 = new File("E:" + File.separator + "test" + File.separator + "test.txt");
		//判断文件是否存在
		if(!f1.exists()) {
			try {
				//创建文件
				f1.createNewFile();
				System.out.println("文件创建成功!");
			} catch (IOException e) {
				e.printStackTrace();
			} 
		}
		
		System.out.println("该路径是否是文件夹:"+f1.isDirectory());
		
		File f2 = new File("E:" + File.separator + "test");
		String[] names = f2.list();
		System.out.println(Arrays.toString(names));
		
		File[] fs = f2.listFiles();
		for(File f : fs) {
			System.out.println("文件长度:"+f.length());
			System.out.println("name="+f.getName());
			System.out.println("相对路径="+f.getPath());
			System.out.println("绝对路径="+f.getAbsolutePath());
			System.out.println("是否是隐藏文件="+f.isHidden());
			System.out.println("是否是可读文件="+f.canRead());
			Date date = new Date(f.lastModified());  //毫秒值
			DateFormat df = new SimpleDateFormat("HH:mm:ss");
			System.out.println("文件最后修改的时间="+df.format(date));  
			System.out.println("-----------------------------");
		}
		
		//文件重命名与移动
		File f3 = new File("E:\\test\\test3");
		f3.mkdirs();
		f3.renameTo(new File("E:\\test3"));
		
		//删除
		File f4 = new File("E:\\test3");
		f4.delete();
		
		//过滤
		File f5 = new File("E:\\test");
		File[] files = f5.listFiles((pathname) -> pathname.getName().endsWith(".txt"));
		for(File f:files) {
			System.out.println(f.getName());
		}
		
	}

}
import java.io.File;
//查找文件
public class FileDemo2 {

	public static void main(String[] args) {
		findFile(new File("E:\\作业图片"),".png");
	}
	private static void findFile(File target, String ext) {
		if(target == null) return;
		if(target.isDirectory()) {
			//目录
			File[] files = target.listFiles();
			if(files != null) {
				for(File f:files) {
					findFile(f,ext);
				}
			}
		}else {
			//文件
			String name = target.getName().toLowerCase();   //文件名字小写
			if(name.endsWith(ext)) {
				System.out.println(target.getAbsolutePath());
			}
		}
	}

}

字节流

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

  • IO流: 输入输出流(流向不同)、字符流字节流(处理数据类型的不同)

  • 输入输出流操作原理:每次只会操作一个字节(从文件中读取或写入)

  • 字节输出流

public abstract class OutputStream extends Object implements Closeable,Flushable
// 表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到InputStream类某个接收器。
//要向文件中输出,使用FileOutputStream类
//输出流
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class ByteStreamDemo {

	public static void main(String[] args) {
		out();
	}
	
	private static void out() {
		
		File file = new File("E:\\test\\test.txt");
		
		try {
			//构建一个文件输出流对象
			OutputStream out = new FileOutputStream(file);  //覆盖
            //OutputStream out = new FileOutputStream(file,true);  //追加
			//输出的内容
			String info = "啦啦啦啦啦啦\r\n";  //\r\n换行
			//把内容写入到文件
			out.write(info.getBytes());
			//关闭流
			out.close();
			System.out.println("写入成功");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
  • 字节输入流
public abstract class InputStream extends Object implements Closeable
//表示字节输入流的所有类的超类
//FileInputStream从文件系统中的某个文件中获得输入字节
//输入流
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class ByteStreamDemo {

	public static void main(String[] args) {
		in();
	}
	
	
	private static void in() {
		File file = new File("E:\\test\\test.txt");
		try {
			InputStream in = new FileInputStream(file);
			byte[] bytes = new byte[1024];
			StringBuilder buf = new StringBuilder();
			int len = -1;      //表示每次读取的字节长度
			//把数据读入到数组中,并返回读取的字节数,当不等于-1时,表示读取到数据,等于-1表示文件已经读完
			while((len = in.read(bytes)) != -1) {
				//根据读取到的字节数组,再转换为字符串内容,添加到StringBuilder中
				buf.append(new String(bytes,0,len));  //加0 len参数避免多读
			}
			//打印内容
			System.out.println(buf);
			//关闭输入流
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

字符流

  • 每次操作的单位是字符。文件字符操作会自带缓存,默认大小为1024字节,在缓存满后,或手动刷新缓存,或关闭流时会把数据写入文件

  • Writer 写入字符流的抽象类,子类必须实现的方法仅有write(char[], int , int)、flush()和close() 。多数子类将重写此处定义的一些方法,以提供更高的效率或实现其他功能。对文件的操作使用FileWriter类完成

  • Reader 用于读取字符流的抽象类,子类必须实现的方法只有read(char[], int, int)和close()。 多数子类将重写此处定义的一些方法,以提供更高的效率或实现其他功能。使用FileReader类进行实例化操作

//写入
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class CharStreamDemo {

	public static void main(String[] args) {
		out();
	}
	
	private static void out() {
		File file = new File("E:\\test\\test.txt");
		try {
			Writer out = new FileWriter(file,true);  //true表示追加
			out.write("哈哈哈哈哈哈");
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

}
//读取
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class CharStreamDemo {

	public static void main(String[] args) {
		in();
	}
	
	private static void in() {
		File file = new File("E:\\test\\test.txt");
		try {
			Reader in = new FileReader(file);
			char[] cs = new char[1];
			int len = -1;
			StringBuilder buf = new StringBuilder();
			while((len=in.read(cs))!=-1) {
				buf.append(new String(cs,0,len));
			}
			in.close();
			System.out.println(buf);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

  • 操作非文本文件时,使用字节流;操作文本文件时,使用字符流
  • 文件复制
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;

public class CopyFileDemo {

	public static void main(String[] args) {
		copy("E:\\作业图片\\1_1.png","E:\\test\\1_1.png");
		System.out.println("成功");
	}

	private static void copy(String src,String target) {
		File srcFile = new File(src);
		File targetFile = new File(target);
		InputStream in = null;
		OutputStream out = null;
		try {
			in = new FileInputStream(srcFile);
			out = new FileOutputStream(targetFile);
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len = in.read(bytes))!= -1) {
				out.write(bytes,0,len);
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(in != null) in.close();
				if(out!=null) out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

字节字符转换流

OutputStreamWriter  //可以将输出的字符流转换为字节流的输出形式
InputStreamReader  //可以将输入的字节流转换为字符流输入形式
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset; 

public class ChangeStreamDemo {

	public static void main(String[] args) throws FileNotFoundException {
		InputStream in = new FileInputStream("E:\\test\\test.txt");
		read(in);
		
	}
	
	private static void read(InputStream in) {
		Reader reader = new InputStreamReader(in,Charset.defaultCharset());
		char[] cs = new char[1024];
		int len = -1;
		try {
			while((len = reader.read(cs)) != -1) {
				System.out.println(new String(cs,0,len));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset; 

public class ChangeStreamDemo {

	public static void main(String[] args) throws FileNotFoundException {
		OutputStream out = new FileOutputStream("E:\\test\\test.txt");
		write(out);
		
	}
	
	
	private static void write(OutputStream out) {
		Writer writer = new OutputStreamWriter(out,Charset.defaultCharset());
		
		try {
			writer.write("嘿嘿嘿嘿嘿嘿");
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

缓冲流

  • 能够更高效的读写信息,原理是将数据先缓冲起来,然后一起写入或者读取出来; 减少对文件的频繁操作
BufferedInputStream: 为另一个输入流添加一些功能,在创建BufferedInputStream时,会创建一个内部缓冲区数组,用于缓冲数据
BufferedOutputStream: 通过设置这种输出流,应用程序就可以将各个字节写入底层输出流,而不必针对每次字节写入调用底层系统
BufferedReader:  从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
BufferedWriter:  将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入
  • BufferedOutputStream 内部默认的缓存大小是8KB,每次写入时存储到缓存中的byte数组中,当数组存满时,会把数组中的数据写入文件,并且缓存下标归零
  • FileReader: 内部使用InputStreamReader( sun.nio.cs.StreamDecoder ),解码过程,byte->char,默认缓存大小是8K
  • BufferedReader: 默认缓存大小是8K,但可以手动指定缓存大小,把数据间接读取到缓存中,减少每次转换过程,效率高
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class BufferStreamDemo {

	public static void main(String[] args) {
		byteWriter();
	}

	private static void byteWriter() {
		File file = new File("E:\\test\\new.txt");
		
		try {
			OutputStream out = new FileOutputStream(file);
			//构造一个字节缓冲流
			BufferedOutputStream bos = new BufferedOutputStream(out);
			
			String info = "红红火火恍恍惚惚";
			bos.write(info.getBytes());
			bos.close();
			//out.close(); 会自动关闭
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}
public class BufferStreamDemo {

	public static void main(String[] args) {
		byteReader();
	}

	private static void byteReader() {
		File file = new File("E:\\test\\new.txt");
		try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len = bis.read(bytes)) != -1) {
				System.out.println(new String(bytes,0,len));
			}
			//bis.close(); 在try里会自动关闭
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}
}
	private static void charReader() {
		File file = new File("E:\\test\\new.txt");
		try {
			Reader reader = new FileReader(file);
			BufferedReader br = new BufferedReader(reader);
			char[] cs = new char[1024];
			int len = -1;
			while((len=br.read(cs))!=-1) {
				System.out.println(new String(cs,0,len));
			}
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
private static void charWriter() {
		File file = new File("E:\\test\\new.txt");
		try {
			Writer writer = new FileWriter(file);
			BufferedWriter bw = new BufferedWriter(writer);
			bw.write("哈哈哈哈哈哈");
			bw.flush();
			bw.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

打印流

private static void bytePrint() {
	File file = new File("E:\\test\\test.txt");
	try {
		OutputStream out = new FileOutputStream(file);
		//加缓存
		BufferedOutputStream bos = new BufferedOutputStream(out);
		//增强打印功能
		PrintStream ps = new PrintStream(bos);
		ps.println("哈哈哈哈哈哈");
		ps.close();
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
}
	private static void charPrint() {
		File file = new File("E:\\test\\test.txt");
		try {
			Writer out = new FileWriter(file);
			//加缓存
			BufferedWriter bos = new BufferedWriter(out);
			//增强打印功能
			PrintWriter pw = new PrintWriter(bos);
			pw.println("哈哈哈哈");
			pw.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

对象流

  • ObjectOutputStream 将java对象的基本数据类型和图形写入OutputStream
  • ObjectInputStream 对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化
import java.io.Serializable;

//如果一个类创建对象需要被序列化,那么该类必须实现Serializable接口
//Serializable是一个标记接口,没有任何定义,为了告诉JVM该类对象可以被序列化

//对象需要被序列化: ①把对象保存到文件中(存储到物理介质) ②对象需要在网络上传输
public class Dog implements Serializable{
    private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private String sex;
	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 String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Dog(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
	}
	public Dog() {
		super();
	}
	@Override
	public String toString() {
		return "Dog [name=" + name + ", age=" + age + ", sex=" + sex + "]";
	}	
}





public class ObjectStreamDemo {

	public static void main(String[] args) {
		writeObject();
	}
	/**
	 * 对象反序列化
	 * 从文件中把对象的内容读取出来,还原成对象
	 */
	private static void readObject() {
		File file = new File("E:\\test\\test.txt");
		try {
			InputStream in = new FileInputStream(file);
			ObjectInputStream ois = new ObjectInputStream(in);
			Dog dog = (Dog)ois.readObject();
			ois.close();
			System.out.println(dog);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 对象序列化
	 * 把对象写入文件:实际写入的是类名、属性名、属性类型、属性的值
	 */
	private static void writeObject() {
		try {
			Dog dog = new Dog("wangwang",2,"母");
			File file = new File("E:\\test\\test.txt");
			OutputStream out = new FileOutputStream(file);
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(dog);
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
  • transient关键字: 如果transient声明一个实例变量,当对象存储时,它的值不需要维持
private transient int id;  //在序列化中被忽略,不会写入到文件中,还原时为默认值0

字节数组流

  • ByteArrayInputStream : 包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read方法要提供的下一个字节。关闭ByteArrayInputStream无效。此类中的方法在关闭此流后仍可被调用,而不产生任何IOException
  • ByteArrayOutputStream: 实现了一个输出流,其中的数据被写入一个byte数组。缓冲区会随着数据的不断写入而自动增长。可使用toByteArray()和toString()获得数据。关闭ByteArrayOutputStream无效。此类中的方法在关闭此流后仍可被调用,而不产生任何IOException
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

public class ByteArrayStreamDemo {
	public static void main(String[] args) {
		byteArray();
	}
	
	private static void byteArray() {
		String s = "1234567gxhjahjk(*%$%^&&*HGDHSNFJ";
		ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int curr = -1;  //每次读取的字节
		while((curr=bais.read()) != -1) {
			if((curr>=65 && curr<=90) || (curr>=97 && curr<=122)) {
				baos.write(curr);
			}
		}
		//此时无需关闭,因为字节数组流是基于内存的操作流
		System.out.println(baos.toString());
	}
}

数据流

  • DataInputStream 数据输入流允许应用程序以与机器无关方式,从底层输入流中读取基本java数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。DataInputStream对于多线程访问不一定是安全的。线程安全是可选的,它由此类方法的使用者负责
  • DataOutputStream 数据输入流允许应用程序以适当方式将基本java数据类型写入输出流中。然后应用程序可以使用数据输入流将数据读入
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
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;

public class DataStreamDemo {

	public static void main(String[] args) {
		write();
		read();
	}
	
	private static void write() {
		File file = new File("E:\\test\\test.bat");
		
		try {
			OutputStream out = new FileOutputStream(file);
			BufferedOutputStream bos = new BufferedOutputStream(out);
			DataOutputStream dos = new DataOutputStream(bos);
			dos.writeInt(10);
			dos.writeByte(1);
			dos.writeUTF("中");
			
			dos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void read() {
		File file = new File("E:\\test\\test.bat");
		
		try {
			InputStream out = new FileInputStream(file);
			BufferedInputStream bis = new BufferedInputStream(out);
			DataInputStream dis = new DataInputStream(bis);
			int num = dis.readInt();
			byte b = dis.readByte();
			String s = dis.readUTF();
			System.out.println(num+","+b+","+s);
			
			dis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

合并流

  • SequenceInputStream: 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,以此类推,直到到达包含的最后一个输入流的文件末尾为止

字符串流

  • StringReader 字符串的字符流
  • StringWriter 字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。关闭StringWriter无效。此类中的方法在关闭该流后仍可被调用,而不会产生任何IOException
//字符串流: 以一个字符串为数据源,来构造一个字符流
//在WEB开发中,我们经常要从服务器上获取数据,数据返回格式通过一个字符串(XML、JSON),我们需要把这个字符串
//构造成一个字符流, 然后再用第三方的数据解析器来解析数据
	private static void stringReader() {
		String info = "good good study day day up";
		StringReader sr = new StringReader(info);
		//流标记器
		StreamTokenizer st = new StreamTokenizer(sr);
		
		int count = 0;
		while(st.ttype != StreamTokenizer.TT_EOF) {
			try {
				if(st.nextToken() == StreamTokenizer.TT_WORD) {
					count++;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		sr.close();
		System.out.println("count="+count);
	}

管道流

  • 管道输入流应该连接到管道输出流,管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从PipedInputStream对象读取,并由其他线程将其写入到相应的PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能会死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏
/**
 * 管道流:一个线程写入,一个线程读取
 * 作用: 用于线程之间的数据通信
 * 
 */
public class PipedStreamDemo {

	public static void main(String[] args) {
		PipedInputStream pin = new PipedInputStream();
		PipedOutputStream pout = new PipedOutputStream();
		
		try {
			pin.connect(pout);  //输入流与输出流连接
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		ReadThread readTh = new ReadThread(pin);
		WriteThread writeTh = new WriteThread(pout);
		new Thread(readTh).start();
		new Thread(writeTh).start();
	}

	
	
}

//读取数据的线程
class ReadThread implements Runnable {
	private PipedInputStream pin;  //输入管道
	
	ReadThread(PipedInputStream pin){
		this.pin = pin;
	}
	
	public void run() {
		
		try {
			byte[] buf = new byte[1024];
			int len = pin.read(buf); //read阻塞
			String s = new String(buf, 0 ,len);
			System.out.println("读到:" + s);
			pin.close();
		} catch (IOException e) {
			e.printStackTrace();
		}  
		
	}
	
}

//写入数据的线程
class WriteThread implements Runnable{
	private PipedOutputStream pout;  //输出管道
	
	WriteThread(PipedOutputStream pout){
		this.pout = pout;
	}
	 public void run() {
		 try {
			pout.write("一个美女...".getBytes());  //管道输出流
			pout.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}  
	 }
}

RandomAccessFile类

  • 从Object直接继承而来,可以对文件进行读取和写入。当模式为r,文件不存在时会报异常;当模式为rw,文件不存在会自己创建文件,当文件存在时不会对原有文件进行覆盖。
  • 内部是大型byte[],可以通过seek(),getFilePointer() 等方法操作的指针,方便对数据进行写入和读取,还可以对基本数据类型进行直接的读和写操作
  • 绝大多数功能已经被nio的 内存映射文件【memory-mapped files】取代了
public class RandomAccessFileDemo {

	public static void main(String[] args) {
		
		try {
			//读取文件
			RandomAccessFile r = new RandomAccessFile("E://test//test.txt","r");
			//写入文件
			RandomAccessFile w = new RandomAccessFile("E://test//new_test.txt","rw");
			
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len = r.read(bytes)) != -1) {
				w.write(bytes,0,len);
			}
			w.close();
			r.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("成功");
	}
}

Properties文件操作

  • ResourceBundle只读 Properties可读可写

  • 在项目新建配置文件config.properties

app.version=1
db.username=admin
db.password=123
  • 读取
public class PropertiesDemo {

	public static void main(String[] args) {
		
		System.out.println(PropertiesDemo.version);
		System.out.println(PropertiesDemo.username);
		System.out.println(PropertiesDemo.password);
	}
	
	public static String version = "";
	public static String username = "";
	public static String password = "";
	
	static {
		readConfig();
	}
	
	/**
	 * 读取properties配置文件
	 */
	private static void readConfig() {
		Properties p = new Properties();
		
		try {
            
			/**
			 * 配置文件放在包里时,通过当前线程的类加载器对象,加载指定包下的配置文件
InputStream inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("com/res/config.properties")
			 */
			InputStream inStream = new FileInputStream("config.properties");
			p.load(inStream);  //加载文件
			
			//从properties中获取数据
			version = p.getProperty("app.version");
			username = p.getProperty("db.username");
			password = p.getProperty("db.password");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
	/**
	 * 对属性文件的写入操作
	 * @param version
	 * @param username
	 * @param password
	 */
	private static void writeConfig(String version,String username,String password) {
		Properties p = new Properties();
		p.put("app.version", version);
		p.put("db.username", username);
		p.put("db.password", password);
		
		try {
			OutputStream out = new FileOutputStream("config.properties");
			//写文件
			p.store(out, "update config");
			out.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		writeConfig("2","vince","2343");
		readConfig();
		System.out.println(PropertiesDemo.version);
		System.out.println(PropertiesDemo.username);
		System.out.println(PropertiesDemo.password);
	}                                                                                                                                                         
  • 方法
getProperty(String key)  //通过key得到value
load(InputStream inStream)  //从输入流中读取属性列表
setProperty(String key, String value)  //调用Hashtable的方法put
store(OutputStream out, String comments)  //与load方法相反,写入到指定的文件
clear()  //清除所有键值对

文件压缩与解压(zip)

ZipOutputStream
  • 实现文件的压缩
  • 方法
ZipOutputStream(OutputStream out)  //创建新的ZIP输出流
void putNextEntry(ZipEntry e)   //开始写入新的ZIP文件条目并将流定位到条目数据的开始处
ZipEntry(String name)  //使用指定名称创建新的ZIP条目
ZipInputStream
  • 实现文件的解压
  • 方法
ZipInputStream(InputStream in)  //创建新的ZIP输入流
ZipEntry getNextEntry()   //读取下一个ZIP文件条目并将流定位到该条目数据的开始处
  • 代码
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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 java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class CompressionAndDecompressionDemo {

	public static void main(String[] args) {
		//compression("E:\\test.zip",new File("E:\\test"));
		decompression("E:\\test.zip","E:\\test\\");
	}
	
	/**
	 * 压缩
	 */
	private static void compression(String zipFileName, File targetFile) {
		System.out.println("正在压缩...");
		
		try {
			//要生成的压缩文件
			ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
			BufferedOutputStream bos = new BufferedOutputStream(out);
			zip(out,targetFile,targetFile.getName(),bos);
			
			bos.close();
			out.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("压缩完成");
	}
	private static void zip(ZipOutputStream zOut,File targetFile,String name,BufferedOutputStream bos) throws IOException {
		if(targetFile.isDirectory()) {
			File[] files = targetFile.listFiles();
			if(files.length == 0) {  //空文件夹
				zOut.putNextEntry(new ZipEntry(name+"/"));  //处理空目录
			}
			for(File f:files) {
				zip(zOut,f,name+"/"+f.getName(),bos);
			}
		}else {
			zOut.putNextEntry(new ZipEntry(name));
			InputStream in = new FileInputStream(targetFile);
			BufferedInputStream bis = new BufferedInputStream(in);
			
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len = bis.read(bytes)) != -1) {
				bos.write(bytes,0,len);
			}
			bis.close();
		}
		
	}

	/**
	 * 解压
	 */
	private static void decompression(String targetFileName,String parent) {
		
		try {
			//构造解压的输入流
			ZipInputStream zIn = new ZipInputStream(new FileInputStream(targetFileName));
			ZipEntry entry = null;
			File file = null;
			while((entry = zIn.getNextEntry()) != null && !entry.isDirectory()) {
				file = new File(parent,entry.getName());
				if(!file.exists()) {
					new File(file.getParent()).mkdir();  //创建此文件的上级目录
				}
				OutputStream out = new FileOutputStream(file);
				BufferedOutputStream bos = new BufferedOutputStream(out);
				byte[] bytes = new byte[1024];
				int len = -1;
				while((len = zIn.read(bytes)) != -1) {
					bos.write(bytes,0,len);
				}
				bos.close();
				System.out.println(file.getAbsolutePath()+"解压成功");
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

IO常用类

装饰者模式

  • Component 被装饰对象基类: 定义对象的接口,可以给这些对象动态增加职责
  • ConcreteComponent 具体被装饰对象: 定义具体的对象,Decorator可以给它增加额外的职责
  • Decorator 装饰者抽象类: 维护指向Component示例的引用,定义与Component一致的接口
  • ConcreteDecorator 具体装饰者: 给内部特有的具体被装饰对象增加具体的职责

①接口

public interface Drink {
	float cost();
	
	String description();
}

②具体对象

public class SoyaBeanMilk implements Drink{
	@Override
	public float cost() {
		return 5f;
	}
	@Override
	public String description() {
		return "纯豆浆";
	}
}

③装饰者抽象类

public abstract class Decorator implements Drink{
	private Drink drink;
	
	public Decorator(Drink drink) {
		this.drink = drink;
	}
	
	@Override
	public float cost() {
		return drink.cost();
	}
	public String description() {
		return drink.description();
	}
}

④具体装饰者

public class SugarDecorator extends Decorator{

	public SugarDecorator(Drink drink) {
		super(drink);
	}
	
	@Override
	public float cost() {
		return super.cost()+1.0f;
	}
	
	@Override
	public String description() {
		return super.description()+"+糖";
	}

}
public class EggDecorator extends Decorator{

	public EggDecorator(Drink drink) {
		super(drink);
	}
	
	@Override
	public float cost() {
		return super.cost()+2.0f;
	}
	
	@Override
	public String description() {
		return super.description()+"+蛋";
	}

}
public class BlackBeanDecorator extends Decorator{

	public BlackBeanDecorator(Drink drink) {
		super(drink);
	}
	
	@Override
	public float cost() {
		return super.cost()+2.0f;
	}
	
	@Override
	public String description() {
		return super.description()+"+黑豆";
	}

}

测试

public class Test {

	public static void main(String[] args) {

		Drink drink = new SoyaBeanMilk();
		SugarDecorator sugar = new SugarDecorator(drink);
		EggDecorator egg = new EggDecorator(sugar);
		BlackBeanDecorator blackBean = new BlackBeanDecorator(egg);
		
		System.out.println("你点的豆浆是"+blackBean.description());
		System.out.println("一共花了:"+blackBean.cost());
	}

}

/**
* 结果
*你点的豆浆是纯豆浆+糖+蛋+黑豆
*一共花了:10.0
*/

常见的字符编码

ISO8859-1   单字节编码  表示0-255的字符范围 英文
GBK/GB2321  双字节  汉字
unicode  使用16进制表示的编码 2字节
UTF  不定长编码
public class codeDemo {
	public static void main(String[] args) {
		String info = "小河流水哗啦啦";
		try {
			String newInfo = new String(info.getBytes("utf-8"),"ISO8859-1");
			System.out.println(newInfo);
			
			String newInfo2 = new String(newInfo.getBytes("ISO8859-1"),"utf-8");
			System.out.println(newInfo2);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
}

New IO

  • 缓冲区: 在NIO库中,所有数据都是用缓冲区处理的,在读取数据时,它是直接读到缓冲区中的。在写入数据中,它是写入缓冲区中的。任何时候访问NIO中的数据,都是将它放到缓冲区中。缓冲区实质上是一个数组,通常是一个字节数组,也可以使用其他种类的数组。缓冲区还提供了对数据的结构化访问,而且可以跟踪系统的读/写进程
  • 缓冲区类型
ByteBuffer;
CharBuffer;
ShortBuffer;
IntBuffer;
LongBuffer;
FloatBuffer;
DoubleBuffer

在这里插入图片描述

public class NIODemo {

	public static void main(String[] args) {
		//创建一个字节缓冲区,申请内存空间为8字节
		ByteBuffer buf = ByteBuffer.allocate(8);
		
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		System.out.println("----------------");
		
		//向缓冲区中写入数据
		buf.put((byte)10);
		buf.put((byte)20);
		buf.put((byte)30);
		buf.put((byte)40);
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		System.out.println("----------------");
		
		//缓冲区反转 (limit = position & position=0)  写入取出数据时需要反转
		buf.flip();
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		System.out.println("----------------");
		
		//告知在当前位置和限制之间是否有元素
		if(buf.hasRemaining()) {
			//返回当前位置和限制之间的元素数
			for(int i=0; i<buf.remaining(); i++) {
				byte b = buf.get(i);
				System.out.println(b);
			}
		}
		
	}

}
  • 通道channe
public class CopyFileChannelDemo {

	public static void main(String[] args) {
		try {
			randomAccessFileCopy();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static void randomAccessFileCopy() throws Exception {
		RandomAccessFile in = new RandomAccessFile("E:\\test\\test.txt","r");
		RandomAccessFile out = new RandomAccessFile("E:\\test\\test\\test.txt","rw");
		FileChannel fcIn = in.getChannel();
		FileChannel fcOut = out.getChannel();
		
		long size = fcIn.size();  //输入流的大小
		//输入输出流的缓冲区(映射)
		MappedByteBuffer inBuf = fcIn.map(MapMode.READ_ONLY, 0, size);
		MappedByteBuffer outBuf = fcOut.map(MapMode.READ_WRITE, 0, size);
		
		for(int i=0; i<size; i++) {
			outBuf.put(inBuf.get());
		}
		//关闭(关闭通道时会写入数据块)
		fcIn.close();
		fcOut.close();
		in.close();
		out.close();
	}
	
	/**
	 * 通过文件通道实现文件的复制
	 * @throws Exception
	 */
	public static void copyFile() throws Exception {
		//创建一个输入文件的通道
		FileChannel fcIn = new FileInputStream("E:\\test\\test.txt").getChannel();
		//创建一个输出文件的通道
		FileChannel fcOut = new FileOutputStream("E:\\test\\test\\test.txt").getChannel();
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		while(fcIn.read(buf) != -1) {
			buf.flip();
			fcOut.write(buf);
			buf.clear();
		}
		fcIn.close();
	}

}

  • IO性能比较

内存映射->NIO读写文件->使用缓存的IO流->无缓存IO流

  • Paths
public class PathFilesDemo {

	public static void main(String[] args) {
		
		File file = new File("E:\\test\\test.txt");
		
		//path
		Path p1 = Paths.get("E:\\test","test.txt");
		System.out.println(p1);
		
		Path p2 = file.toPath();
		System.out.println(p2);
		
		Path p3 = FileSystems.getDefault().getPath("E:\\test","test.txt");
		System.out.println(p3);
		
		
	}

}
/**

E:\test\test.txt
E:\test\test.txt
E:\test\test.txt

*/
  • Files工具类
		//Files工具类

		Path p = Paths.get("E:\\test\\test.txt");
		String info = "哈哈哈哈哈哈";
		//写
		try {
			Files.write(p, info.getBytes("gb2312"), StandardOpenOption.APPEND);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		//读
		try {
			byte[] bytes = Files.readAllBytes(p);
			System.out.println(new String(bytes));
		} catch (IOException e) {
			e.printStackTrace();
		}

方法:

//复制 移动 删除
static path copy(Path source,Path target,CopyOption...options);
static path move(Path source,Path target,CopyOption...options);
static void delete(Path path)  //如果path不存在文件将抛出异常
static boolean deleteIfExists(Path path)
    
//创建文件和目录
Files.createDirectory(path);  //创建新目录,除了最后一个部件,其他必须是已存在的
Files.createDirectories(path);  //创建路径中的中间目录,能创建不存在的中间部件
Files.createFile(path);  //创建一个文件,文件存在抛出异常

// 添加前/后缀创建临时文件或临时目录
Path newPath = Files.createTempFile(dir,prefix,suffix);
Path newPath = Files.createTempDirectory(dir,prefix);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值