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);