Java文件与IO

File类

代表计算机各个文件,目录的抽象表现形式,可以实现文件的创建,删除等

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 FileDemo {
	public static void main(String[] args) {
		//File类表示一个文件或目录
		//指定在哪里创建
		//第一种使用方法
		File f1 = new File("/home/xiaoming/音乐/java/vince.text");
		//第二种使用方法,使用类中的常量separator表示斜杠
		File f2 = new File(File.separator+"home"
				+File.separator+"xiaoming"
				+File.separator+"音乐"+File.separator
				+"java"+File.separator+"tey.text");
		//判断文件是否已经存在
		if(!f1.exists()) {
			try {
				f1.createNewFile();//创建文件
				System.out.println("文件创建成功");
			} catch (IOException e) {
				// 基本上IO操作都报这个错误
				e.printStackTrace();
			}
		}
		//判断对象是否是文件
		System.out.println(f1.isFile());
		//判断该对象是否为文件夹
		System.out.println(f1.isDirectory());
		
		//删除文件夹(前提文件夹里无文件)
		File f3 = new File("/home/xiaoming/音乐/java");
		boolean b = f3.delete();
		System.out.println(b);
		
		//列出所有文件名,若是文件夹,则列出文件夹名
		String[] name = f3.list();
		System.out.println(Arrays.toString(name));
		
		//列出当前目录下的所有文件,以file对象返回
		File[] f4 = f3.listFiles();
		for(File f:f4) {
			System.out.println(f.length());
			System.out.println(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));
		}
		
		//创建文件夹
		File f5 = new File("/home/xiaoming/音乐/java1");
		f5.mkdir();
		f5.mkdirs();//一次性创建所有指定文件夹
		
		//重命名与移动文件
		f5.renameTo(new File("/home/xiaoming/音乐/Text1"));
		
		//过滤器
		File[] files = f5.listFiles(new FileFilter() {
			
			//从写此方法,用于查找出指定文件
			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".text");
			}
		});
		//第二种写法
		File[] files_s  = f5.listFiles((pathname)->pathname.getName().endsWith(".text"));
		for(File f:files) {
			System.out.println(f.getName());
		}
	}
}

字节输出,输入流

输出输入是从程序的角度看的
OutputStream,InputStream是所有类的超类,要向文件中进行操作,使用子类FileOutputStream,FileInputStream
write,read的具体实现都是一个字节一个字节进行读取的

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 IOStreamDemo {

	public static void main(String[] args) {
		out();
		in();
		
	}
	
	//文件输出流(写入文件)
	private static void out() {
		
		//确定目标文件
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		//构建一个文件输出流对象
		try {
			OutputStream out = new FileOutputStream(file,true);//第二个参数append默认为false,true时表示追加
			
			//输出(写入)的内容
			String info = "小桥流水人家\n";
			//把内容写入文件
			out.write(info.getBytes());//write方法接收byte类型参数
			//关闭流
			out.close();
			System.out.println("输出成功!");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//文件写入流(输出文件内容)
	private static void in() {
		//确定目标文件
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		//构建一个文件输入流对象
		try {
			InputStream in = new FileInputStream(file);
			
			byte[] bytes = new byte[1024];//单数用中文会造成乱码,解决办法使用字符流
			StringBuilder buf = new StringBuilder();
			int len = -1;//表示每次读取的长度
			//把数据读入数组中,并返回每次读取的字节数,当不等于-1时表示读取到数据,等于-1表示读取不到数据
			/*
			 * @Return
			 * the total number of bytes read into the buffer, 
			 * or -1 if there is no more data 
			 * because the end of the stream has been reached.
			 */
			while((len = in.read(bytes))!=-1) {
				//根据读取到的字节数组,再转换为字符串内容,添加到StringBuilder中
				//当读取的字符数多余字符数组大小时,新读的内容会自动替换掉从头已读的内容,但后面的原有已读内容任然保留,这时候需要加入len指定读取到的位置,避免最后读出的内容与前面重复
				buf.append(new String(bytes,0,len));
			}
			//打印内容
			System.out.println(buf);
			//关闭输入流
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

字符输出,输入流

字符流的内部实现还是字节流
字符输出流:Writer,对文件的操作使用子类FileWriter
字符输入流:Reader,对文件的操作使用子类FileReader
每次操作都是一个字符
文件字符操作流会自带缓存,默认大小为1024字节,在缓存满或手动刷新或关闭流时会写入文件,但是字节操作流没有缓存,直接写入
一般操作非文本文件时,使用字节流,操作文本文件时,使用字符流

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

//字符流
public class CharStreamDemo {
	public static void main(String[] args) {
		out();
		in();
	}

	// 字符输出流
	private static void out() {
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		try {
			Writer out = new FileWriter(file, true);
			out.write("小桥流水人家,古道西风瘦马\r\n");
			System.out.println("写入文件成功");
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 字符输入流
	private static void in() {
		File file = new File("/home/xiaoming/音乐/java/vince.text");

		try {
			Reader in = new FileReader(file);
			char[] cs = new char[5];
			int len = -1;
			StringBuilder buf = new StringBuilder();
			while((len = in.read(cs))!=-1) {
				buf.append(new String(cs,0,len));
			}
			System.out.println(buf);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

字节字符转换流

OutputStreamWriter:可以将输出的字符转换成字节流的输出形式
InputStreamReader:可以将输入的字节流转化为字符形式的输入流

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.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;

//字节字符转换流
public class StreamChangeDemo {
	
	public static void main(String[] args) {
		
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		InputStream in = null;
		OutputStream out = null;
		try {
			in = new FileInputStream(file);
			out = new FileOutputStream(file,true);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		read(in);
		write(out);
	}
	
	//输入流:字节转字符
	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));
			}
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//输出流:字符转字节
	private static void write(OutputStream out) {
		Writer writer = new OutputStreamWriter(out);
		
		try {
			writer.write("新年快乐!!!");
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

字节字符缓冲流

先将数据缓冲起来,再一起写入或者读取出来,提高效率
BufferedInputStream,BufferedOutputStream为两个字节缓冲流的类
内部默认缓存大小为8KB,每次写入时存储到缓存中的byte数组,当数组存满时,会把数组中的数据写入文件,并且缓存下标归零
BufferedReader
BufferedWriter

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;


public class BufferStreamDemo {
	public static void main(String[] args) {
		byteWriter();
		byteReader();
		
		charWriter();
		charReader();
	}
	
	//缓冲字节输出
	private static void byteWriter() {
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		
		try {
			OutputStream out = new FileOutputStream(file,true);
			//构造一个字节缓冲流
			BufferedOutputStream bos = new BufferedOutputStream(out);
			String info = "枯藤老树昏鸦\r\n";
			bos.write(info.getBytes());
			bos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//缓冲字节输入
	private static void byteReader() {
		
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		
		try {
			InputStream in = new FileInputStream(file);
			//构造缓冲流
			BufferedInputStream bis = new BufferedInputStream(in);
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len = bis.read(bytes))!=-1) {
				System.out.println(new String(bytes,0,len));
			}
			bis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//缓冲字符输出
	private static void charWriter() {
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		try {
			Writer writer = new FileWriter(file,true);
			//构造缓存器
			BufferedWriter bw = new BufferedWriter(writer);
			bw.write("夕阳西下\r\n");
			bw.flush();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	//缓冲字符输入
	private static void charReader() {
		File file = new File("/home/xiaoming/音乐/java/vince.text");
		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();
		}	
	}
}

打印流

便利输出
PrintStream
PrintWriter

File file = new File("xxxx");
OutputStream out = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(out);//加缓存
PrintStream ps = new PrintStream(bos);//增强打印流
ps.println("xxxxx");
ps.close;

对象流和序列化

序列化:将对象的状态信息转化为可以存储或传输的形式
反序列化:将已经序列化的对象重新转换成对象的状态信息
对象流的两个类:ObjectOutputStream将java对象的基本数据类型和图形写入OutputStream,ObjectInputStream对写入ObjectOutputStream的基本数据和对象进行反序列化
需要序列化的情况:

  1. 把对象保存到文件中
  2. 对象需要在网络中传输时
import java.io.Serializable;

//继承标记接口表示该类需要进行序列化,否则会报java.io.NotSerializableException错误
public class Dog implements Serializable{

	/**
	 * 定义版本号,防止两个不同对象因属性一样造成混乱
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	private String sex;
	//可以使用关键字transient声明一个变量在存储时不需要维持其具体值(默认0或null)
	private transient int id;
	public Dog() {
		super();
	}

	public Dog(String name, int age, String sex) {
		super();
		this.name = name;
		this.age = age;
		this.sex = 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 String toString() {
		return "Dog [name=" + name + ", age=" + age + ", sex=" + sex + ", getName()=" + getName() + ", getAge()="
				+ getAge() + ", getSex()=" + getSex() + "]";
	}

}

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.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class ObjectStreamDemo {
	public static void main(String[] args) {
		writeObject();
		readObject();
	}

	//对象序列化
	public static void writeObject() {
		Dog dog = new Dog("猪猪",6,"girl");
		//当要读取多个对象时,使用数组
		//Dog[] dogs = {dog1,dog2};
		File file = new File("/home/xiaoming/音乐/java/ObjectStream.text");
		try {
			OutputStream out = new FileOutputStream(file);
			ObjectOutputStream oos = new ObjectOutputStream(out);
			oos.writeObject(dog);//多个时改为dogs
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//对象反序列化
	public static void readObject() {
		Dog dog = new Dog("猪猪",6,"girl");
		File file = new File("/home/xiaoming/音乐/java/ObjectStream.text");
		try {
			InputStream in = new FileInputStream(file);
			ObjectInputStream ois= new ObjectInputStream(in);
			Dog dog2 = (Dog)ois.readObject();
			//多个时:Dog[] dog = (Dog[])ois.readObject();
			System.out.println(dog2);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

字节数组流

基于内存操作,内部维护着一个字节数组,可以利用流的读取机制来处理字符串
与文件操作无关,无需关闭
ByteArrayInputStream
ByteArrayOutputStream

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

public class ByteArrayStreamDemo {

	public static void main(String[] args) {
		byteArray();
	}
	
	private static void byteArray() {
		
		String s = "123456789sljtiegrgGRGFRTGAFWER(*&*^&%%$@#)";
		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());
	}
}

数据流

应用程序以与机器无关的方式从底层输出或输入java基本数据类型
DataInputStream
DataOutputStream

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
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("/home/xiaoming/音乐/java/vince.data");
		try {
			OutputStream out = new FileOutputStream(file);
			BufferedOutputStream bos = new BufferedOutputStream(out);
			DataOutputStream dos = new DataOutputStream(bos);
			dos.writeInt(15);//4个字节
			dos.writeByte(1);//写入1个字节
			dos.writeUTF("花花卡");
			
			dos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private static void read() {
		File file = new File("/home/xiaoming/音乐/java/vince.data");
		try {
			InputStream in = new FileInputStream(file);
			BufferedInputStream bis = new BufferedInputStream(in);
			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

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.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

/*
 * 文件的分割和合并
 */
public class FileDivisionMergeDemo {

	public static void main(String[] args) {
		//分割
		File file = new File(
				"/media/M_fM__VM__GM_fM_!M_#/编程语言/Java/课程/千锋Java基础教程-Java基础(完结-217集)/千锋java基础教程:第10章 多线程与并发(12集)/第10章 多线程与并发_12_线程生命周期与线程池_小结.mp4");
		division(file, 1024 * 1024 * 10);
		System.out.println("分割成功");
		
		//合并
		Vector<InputStream> v = new Vector<InputStream>();
		for(int i=1;i<=59;i++) {
			try {
				InputStream in = new FileInputStream(new File("/home/xiaoming/音乐/java/花花卡" + i + ".mp4"));
				v.add(in);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		Enumeration<InputStream> es = v.elements();
		merge(es);
	}

	/**
	 * 文件切割
	 * 
	 * @param file    要切割的文件
	 * @param cutSite 切割后每份文件的大小
	 */
	private static void division(File targetFile, long cutSize) {

		if (targetFile == null)
			return;
		// 计算文件的总分割数
		int num = (targetFile.length() % cutSize == 0) ? (int) (targetFile.length() / cutSize)
				: (int) ((targetFile.length() / cutSize) + 1);
		try {
			// 构造一个文件输入流
			BufferedInputStream in = new BufferedInputStream(new FileInputStream(targetFile));
			BufferedOutputStream out = null;

			byte[] bytes = null;// 每次希望读取的最大字节数
			int len = -1;// 每次读取的字节数
			int count = 0;// 每一个文件要读取的次数

			for (int i = 1; i < num; i++) {
				out = new BufferedOutputStream(new FileOutputStream("/home/xiaoming/音乐/java/花花卡" + i + ".mp4"));

				if (cutSize <= 1024) {
					bytes = new byte[(int) cutSize];
					count = 1;
				} else {
					bytes = new byte[1024];
					count = (int) cutSize / 1024;
				}

				// 边读边写入,不然会刷新数组,写入不了
				// 判断条件应该把读放在后面,防止多读一次
				while (count > 0 && (len = in.read(bytes)) != -1) {
					out.write(bytes);
					out.flush();
					count--;
				}

				// 如果余数不为零,数组不整除就需要多读一遍
				if ((int) cutSize % 1024 != 0) {
					bytes = new byte[(int) cutSize % 1024];
					len = in.read(bytes);
					out.write(bytes, 0, len);
					out.flush();
				}
				out.close();// 关闭本次输出流
			}
			in.close();// 最后才关闭输入流

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	
	private static void merge(Enumeration<InputStream> es) {
		//构造一个合并流
		SequenceInputStream sis = new SequenceInputStream(es);
		
		try {
			BufferedOutputStream bos = new BufferedOutputStream(
					new FileOutputStream("/home/xiaoming/音乐/java/花花卡.mp4"));
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len=sis.read(bytes))!=-1) {
				bos.write(bytes,0,len);
				bos.flush();
			}
			bos.close();
			sis.close();
			System.out.println("合并完成");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
}

字符串流

StringReader以一个字符串为数据源,来构造一个字符流
StringWriter无需关闭

import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;

//字符串流
public class StringStreamDemo {

	private static void stringReader() {
		String info = "中 大 奖,花 呗 免 单!";
		StringReader sr = new StringReader(info);
		//流标记器
		StreamTokenizer st = new StreamTokenizer(sr);
		
		int count = 0;//计算总数
		//TT_EOF表示读到流的末尾,ttype是每一次读取返回的类型
		while(st.ttype != StreamTokenizer.TT_EOF) {
			try {
				//TT_WORD表示读取的内容是文字
				if(st.nextToken()==StreamTokenizer.TT_WORD) {
					count++;
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		sr.close();
		System.out.println("count="+count);
	}
	public static void main(String[] args) {
		stringReader();
	}
}

RandomAccessFile

直接继承Object类,只可以对文件进行操作,有两种模式(r,rw)

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileDemo {

	public static void main(String[] args) {
		try {
			RandomAccessFile r = new RandomAccessFile("/home/xiaoming/音乐/java/vince.text", "r");
			RandomAccessFile w = new RandomAccessFile("/home/xiaoming/音乐/java/vince2.text","rw");
			
			byte[] bytes = new byte[1024];
			int len = -1;
			while((len = r.read(bytes))!= -1) {
				w.write(bytes,0,len);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("copy success");
	}
}

Properties文件操作类

主要用于读取配置文件

//properties配置文件
#update config
#Sun Feb 03 10:58:41 CST 2019
db.password=987654321
db.username=xiaoming
app.version=2

//对配置文件的操作
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.Properties;

public class PropertiesDemo {
	
	public static String version = "";
	public static String username = "";
	public static String password = "";
	
	//静态代码块,在创建对象时执行一次
		static {
			readConfig();
		}
	/**	
	 * 输出操作
	 */
	private static void readConfig() {
		
		Properties p = new Properties();
		try {
			InputStream inStream = new FileInputStream("config.properties");
			//当文件不在当前项目根目录下时,使用如下方式指定路径
//			InputStream inStream1 = Thread.currentThread().getContextClassLoader()
//					.getResourceAsStream("com/res/config.properties");
			p.load(inStream);//加载文件
			
			//从properties中获取数据
			
			version = p.getProperty("app.version");
			username = p.getProperty("db.username");
			password = p.getProperty("db.password");
			
			inStream.close();
		} 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
		p.put("app.version",version);
		p.put("db.username", username);
		p.put("db.password",password);
		try {
			OutputStream outStream = new FileOutputStream("config.properties");
			//写入文件,第二个参数是注释
			p.store(outStream, "update config");
			outStream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public static void main(String[] args) {
		//readConfig();
		writeConfig("2", "xiaoming", "987654321");
		System.out.println(PropertiesDemo.version);
		System.out.println(PropertiesDemo.username);
		System.out.println(PropertiesDemo.password);
	}
}

文件压缩和解压缩

压缩: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.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 压缩和解压缩实例
 * 
 * @author xiaoming
 *
 */
public class CompressionAndDecompressionDemo {

	public static void main(String[] args) {
		File file = new File("/home/xiaoming/音乐/12345");
		compression("/home/xiaoming/音乐/123456789.zip", file);

		decompression("/home/xiaoming/音乐/123456789.zip", "/home/xiaoming/音乐");

	}

	/**
	 * 压缩
	 * 
	 * @param zipFileName 希望压缩后的文件名(路径)
	 * @param targetFile  目标文件
	 * @return
	 */
	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();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("压缩完成!!!");
	}

	/**
	 * 执行具体的压缩操作
	 * 
	 * @param out            对文件进行压缩的类
	 * @param targetFile     目标文件
	 * @param targetFileName 要压缩文件的文件名
	 * @param bos            缓存流
	 * @throws IOException
	 */
	private static void zip(ZipOutputStream out, File targetFile, String targetFileName, BufferedOutputStream bos)
			throws IOException {
		// 判断是目录还是文件夹
		if (targetFile.isDirectory()) {
			// 如果是空目录
			if (targetFile.length() == 0) {
				out.putNextEntry(new ZipEntry(targetFileName));// 处理空目录
			}
			File[] files = targetFile.listFiles();
			for (File f : files) {
				zip(out, f, targetFileName + "/" + f.getName(), bos);
			}
		} else {
			out.putNextEntry(new ZipEntry(targetFileName));
			FileInputStream 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();
		}
	}

	/**
	 * 解压
	 * 
	 * @param targetFileName 要解压的文件名
	 * @param parent         解压到的位置
	 */
	private static void decompression(String targetFileName, String parent) {
		// 构造解压的输入流
		ZipInputStream zIn;
		try {
			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()).mkdirs();// 创建此文件的上级目录
				}
				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();
		}

	}
}

New IO(NIO)

原来的IO采用流的方式处理数据,为NIO以块的方式处理数据,效率更高,在NIO中,所有的数据都是在缓冲区处理,缓冲区实际上是一个数组

缓冲区

缓冲区的类型:

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • LongBuffer
  • DoubleBuffer
  • IntBuffer
  • FloatBuffer
package nio;

import java.nio.ByteBuffer;

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());
		
		//向缓冲区写入数据
		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());
		
		//缓冲区反转(把limit设置为position的值,并把positon置零),在取值前使用
		buf.flip();
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		
		//取值
		//判断当前位置与限制元素之间是否有元素
		if(buf.hasRemaining()) {
			//返回当前位置与限制之间的元素数
			for(int i=0;i<buf.remaining();i++) {
				byte b = buf.get(i);//取值
				System.out.println(b);
			}
		}		
	}
}

通道:Channel

数据通过通道进出缓冲区,Channel是一个类

/**
 * 文件复制实例
 */
package nio;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

public class CopyFileDemo {
	
	public static void main(String[] args) {
		try {
			copyFile();
			randomAccessFileCopy();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	//NIO方式
	private static void copyFile() throws IOException {
		//创建一个输入文件的通道
		FileChannel in = new FileInputStream("/home/xiaoming/图片/v2-c4a14410a05ed4ddede728e6d467effc_r.jpg").getChannel();
		//创建一个输出文件的通道
		FileChannel out = new FileOutputStream("/home/xiaoming/音乐/background.jpg").getChannel();
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		while(in.read(buf)!=-1) {
			buf.flip();
			out.write(buf);
			buf.clear();
		}
		in.close();
		out.close();
		System.out.println("copy success");
	}
	
	//印射方式
	private static void randomAccessFileCopy() throws IOException {
		RandomAccessFile in = new RandomAccessFile("/home/xiaoming/图片/v2-c4a14410a05ed4ddede728e6d467effc_r.jpg","r");
		RandomAccessFile out = new RandomAccessFile("/home/xiaoming/音乐/background1.jpg", "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();
		System.out.println("copy success");
	}
}

IO操作的性能比较:

  1. 内存印射最快
  2. NIO读写
  3. 使用缓存的IO流
  4. 普通无缓存IO

Path接口

Path表示一个目录名,表示具体路径

package nio;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;

public class PathFileDemo {

	public static void main(String[] args) {
		File file = new File("/home/xiaoming/音乐/background.jpg");
		
		//path,通过这种方式获取文件
		Path p1 = Paths.get("/home/xiaoming/音乐","background.jpg");
		System.out.println(p1);
		
		Path p2 = file.toPath();
		System.out.println(p2);
		
		//toPath方法的具体实现方法
		Path p3 = FileSystems.getDefault().getPath("/home/xiaoming/音乐","background.jpg");
		
		//Files工具类
		Path p4 = Paths.get("/home/xiaoming/音乐/工具类.text");
		String info = "一闪一闪亮晶晶";
		try {
			Files.write(p4, info.getBytes("gb2312"), StandardOpenOption.CREATE_NEW);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			byte[] bytes = Files.readAllBytes(p4);
			System.out.println(new String(bytes));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		//复制(第三个参数可选)
		try {
			Files.copy(p3, Paths.get("/home/xiaoming/音乐/background2.jpg"),StandardCopyOption.REPLACE_EXISTING);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//移动文件
		try {
			Files.move(p3, Paths.get("/home/xiaoming/音乐/background2.jpg"),StandardCopyOption.REPLACE_EXISTING);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//删除文件
		try {
			Files.delete(p3);
			Files.deleteIfExists(p3);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//创建目录文件
		try {
			Files.createDirectory(Paths.get("/home/xiaoming/音乐/abc"));//除了最后的一个部件,其他的必须是已存在的
			Files.createDirectories(Paths.get("/home/xiaoming/音乐/abc"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//创建文件
		try {
			Files.createFile(Paths.get("/home/xiaoming/音乐/abc.txt"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//添加前后缀创建临时文件或临时目录
		//Path newPath = Files.createTempFile(prefix, suffix, attrs);
		//Path newPath = Files.createTempDirectory(dir, prefix);

	}
	
}