Java--IO流;File类;文件目录拷贝;序列化与反序列化;Properties
Posted MinggeQingchun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--IO流;File类;文件目录拷贝;序列化与反序列化;Properties相关的知识,希望对你有一定的参考价值。
一、IO流
IO流用来处理设备之间的数据传输
数据传输是需要通道的,而IO流就是数据传输的通道;因此IO流可以形象的比喻为运送货物的传输带
I : Input
O : Output
通过IO可以完成硬盘文件的读和写
二、流分类
1、按流向
输入流 和 输出流
以内存作为参照物,
往内存中去,叫做输入(Input),读(Read)
从内存中取出,叫做输出(Output),写(Write)。
2、按数据操作类型
字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
字符流 : 字符流只能操作纯字符数据
字节流,读取二进制,是万能的,什么类型的文件都可以读取,可以处理一切文件,包括:纯文本文件、doc、Word、音频、视频、图片等。
字符流:文本文件,只能处理纯文本;无法读取Word文件
3、按实现功能
节点流(可以从或向一个特定的地方(节点)读写数据。如 FileReader)
处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如
BufferedReader 。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其 他流的多次包装,称为流的链接)三、流对象
Java中所有的流都是在:java.io.*包下
1、字节流
java.io.InputStream 字节输入流(abstract class,抽象类)
java.io.OutputStream 字节输出流(abstract class,抽象类)
2、字符流
java.io.Reader 字符输入流(abstract class,抽象类)
java.io.Writer 字符输出流(abstract class,抽象类)
所有的流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法
流是一个管道(内存和硬盘之间的通道),用完之后一定要关闭,不然会耗费(占用)很多资源
所有的输出流都实现了java.io.Flushable接口,都是可刷新的,都有flush()方法
刷新表示将通道/管道当中剩余未输出的数据
强行输出完(清空管道!)刷新的作用就是清空管道
如果没有flush()可能会导致丢失数据。
3、java.io包下主要流对象
(1)文件专属:
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.FileWriter
(2)转换流:(将字节流转换成字符流)
java.io.InputStreamReader
java.io.OutputStreamWriter
(3)缓冲流专属:
java.io.BufferedReader
java.io.BufferedWriter
java.io.BufferedInputStream
java.io.BufferedOutputStream
(4)数据流专属:
java.io.DataInputStream
java.io.DataOutputStream
(5)标准输出流:
java.io.PrintWriter
java.io.PrintStream
(6)对象专属流:
java.io.ObjectInputStream
java.io.ObjectOutputStream
FileInputStream测试代码:tempFile文件中是 abcdef 字符
package iostream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest
public static void main(String[] args)
FileInputStream fis = null;
FileInputStream fis1 = null;
FileInputStream fis2 = null;
try
// 创建文件字节输入流对象
// 文件路径:D:\\file\\temp.txt;绝对路径方式 (IDEA会自动把"\\"编程为"\\\\",java中\\表示转义)
//FileInputStream fisTemp = new FileInputStream("D:\\\\file\\\\temp.txt");
// 写成 D:/file/temp.txt 也可以
FileInputStream fisTemp = new FileInputStream("D:/file/temp.txt");
/**
* IDEA默认的当前路径是工程Project的根
* */
fis = new FileInputStream("tempFile");
// 读,采用byte数组,一次读取多个字节。最多读取“数组.length”个字节
byte[] bytes = new byte[4];
/**
int read(byte[] b)
一次最多读取 b.length 个字节。
减少硬盘和内存的交互,提高程序的执行效率。
*/
// 这个方法的返回值是:读取到的字节数量。(不是字节本身);大小一般取值为1024的整数倍
int readCount = fis.read(bytes);
System.out.println(readCount); // 第一次读到了4个字节。
// 将字节数组全部转换成字符串
//System.out.println(new String(bytes)); // abcd
// 读取了多少个字节,转换多少
System.out.println(new String(bytes));
readCount = fis.read(bytes); // 第二次只能读取到2个字节。
System.out.println(readCount); // 2
// 将字节数组全部转换成字符串
//System.out.println(new String(bytes)); // efcd,ef替换了ab,cd还存在
System.out.println(new String(bytes));
readCount = fis.read(bytes); // 1个字节都没有读取到返回-1
System.out.println(readCount); // -1
System.out.println("============================");
fis1 = new FileInputStream("src/iostream/tempFile1");
byte[] bytes1 = new byte[5]; // 一个5个长度的byte数组,一次最多读取5个字节
/**
* int readCount = fis.read(bytes);
* 返回值是:读取到的字节数量。(不是字节本身)
* 将字节数组全部转换成字符串,读取了多少字节,转换多少
*
* 转换为字符时,使用String(byte [ ] bytes,int offset,int length)
*/
int readCount1 = 0;
while ( (readCount1 = fis1.read(bytes1)) != -1)
System.out.print(new String(bytes1,0,readCount1));
System.out.println("============================");
fis2 = new FileInputStream("src/iostream/tempFile1");
/**
* int available():返回流当中剩余的没有读到的字节数量
* */
System.out.println("总字节数量:" + fis2.available());
// 可以读取剩下的字节数;这种方式不太适合太大的文件,因为byte[]数组不能太大。
byte[] restBytes = new byte[fis.available()];
//long skip(long n):跳过几个字节不读。
fis2.skip(5);//
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally // 在finally语句块当中确保流一定关闭。
// 关闭流的前提是:流不是空;流是null的时候没必要关闭
if (fis != null)
try
fis.close();
catch (IOException e)
e.printStackTrace();
if (fis1 != null)
try
fis1.close();
catch (IOException e)
e.printStackTrace();
if (fis2 != null)
try
fis2.close();
catch (IOException e)
e.printStackTrace();
FileOutputStream
public class FileOutStreanTest
public static void main(String[] args)
FileOutputStream fos = null;
try
// 以追加的方式在文件末尾写入,不会清空原文件内容。
fos = new FileOutputStream("src/iostream/outFile1",true);
byte[] bytes = 97,98,99,100;
fos.write(bytes);
String str = "这是强大的祖国,是我生长的地方!";
byte[] bytes1 = str.getBytes();
fos.write(bytes1);
//刷新管道
fos.flush();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (fos != null)
try
fos.close();
catch (IOException e)
e.printStackTrace();
BufferedWriter
/**
BufferedWriter:带有缓冲的字符输出流。
OutputStreamWriter:转换流
*/
public class BufferedWriterTest
public static void main(String[] args)
BufferedWriter bw = null;
try
FileOutputStream fos = new FileOutputStream("src/iostream/outFile2");
OutputStreamWriter osw = new OutputStreamWriter(fos);
// bw = new BufferedWriter(osw);
bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/iostream/outFile2")));
bw.write("Hello World!");
bw.write("\\n");
bw.write("Hello");
bw.flush();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (bw != null)
try
bw.close();
catch (IOException e)
e.printStackTrace();
BufferedReader
/**
BufferedReader:
带有缓冲区的字符输入流。
使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲。
转换流:InputStreamReader
*/
public class BufferedReaderTest
public static void main(String[] args)
BufferedReader br = null;
BufferedReader br1 = null;
try
/**
当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
像当前这个程序来说:FileReader就是一个节点流。BufferedReader就是包装流/处理流。
*/
FileReader fr = new FileReader("src/iostream/tempFile1");
br = new BufferedReader(fr);
String str = null;
while ((str = br.readLine()) != null)
System.out.println(str);
//字节流
FileInputStream fis = new FileInputStream("src/iostream/tempFile1");
/**
* 转换流
* 通过转换流转换(InputStreamReader将字节流转换成字符流)
* in是节点流。reader是包装流
*/
InputStreamReader isr = new InputStreamReader(fis);
/**
* 这个构造方法只能传一个字符流。不能传字节流。
* reader是节点流。br是包装流。
* */
//new BufferedReader(isr);
br1 = new BufferedReader(new InputStreamReader(new FileInputStream("src/iostream/tempFile1")));
String str = null;
while ((str = br1.readLine()) != null)
System.out.println(str);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (br != null)
try
// 对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭(源码)
br.close();
catch (IOException e)
e.printStackTrace();
if (br1 != null)
try
br1.close();
catch (IOException e)
e.printStackTrace();
DataOutputStream
/**
java.io.DataOutputStream:数据专属的流。
这个流可以将数据连同数据的类型一并写入文件。
注意:这个文件不是普通文本文档。(这个文件使用记事本打不开。)
*/
public class DataOutputStreamTest
public static void main(String[] args)
DataOutputStream dos = null;
try
// 创建数据专属的字节输出流
dos = new DataOutputStream(new FileOutputStream("src/iostream/dataInput"));
// 写数据
byte b = 100;
short s = 200;
int i = 300;
long l = 400L;
float f = 3.0F;
double d = 3.14;
boolean sex = false;
char c = 'a';
// 把数据以及数据的类型一并写入到文件当中。
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
dos.writeFloat(f);
dos.writeDouble(d);
dos.writeBoolean(sex);
dos.writeChar(c);
dos.flush();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (dos != null)
try
dos.close();
catch (IOException e)
e.printStackTrace();
DataInputStream
/**
DataInputStream:数据字节输入流。
DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。
读的顺序需要和写的顺序一致。才可以正常取出数据。
*/
public class DataInputStreamTest
public static void main(String[] args)
DataInputStream dis = null;
try
dis = new DataInputStream(new FileInputStream("src/iostream/dataInput"));
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
boolean sex = dis.readBoolean();
char c = dis.readChar();
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(sex);
System.out.println(c);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (dis != null)
try
dis.close();
catch (IOException e)
e.printStackTrace();
PrintStream
/**
* 日志工具
* */
public class Logger
public static void log(String message)
try
// 标准输出流不需要手动close()关闭
PrintStream printStream = new PrintStream(new FileOutputStream("src/iostream/log.txt",true));
// 修改输出方向,将输出方向修改到"log.txt"文件;标准输出流不再指向控制台,指向"log.txt"文件。
System.setOut(printStream);
Date date = new Date();
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String timeStr = sf.format(date);
printStream.println(timeStr + ": " + message);
catch (FileNotFoundException e)
e.printStackTrace();
四、File
1、File类父类是Object,因此File不能完成文件的读和写
2、File对象
文件和目录路径名的抽象表示形式;File只是一个路径名的抽象表示形式
C:\\Download 这是一个File对象;C:\\Drivers\\Download\\a.txt 也是File对象
一个File对象有可能对应的是目录,也可能是文件
public class FileTest
public static void main(String[] args)
//创建一个File文件
File file = new File("D:\\\\file");
// exists()判断文件是否存在
System.out.println(file.exists());
//如果不存在,以文件形式创建文件createNewFile()
if (!file.exists())
try
file.createNewFile();
catch (IOException e)
e.printStackTrace();
//isDirectory()判断是否文件夹
System.out.println(file.isDirectory());
//isFile()判断是否文件
System.out.println(file.isFile());
//getName()获取文件名
System.out.println(file.getName());
//length()获取文件大小(返回字节大小)
System.out.println(file.length());
//lastModified()判断最后一次修改时间
long millisecond = file.lastModified();
Date date = new Date(millisecond);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
System.out.println(sdf.format(date));
//mkdir()如果不存在,以文件夹目录形式创建文件
if (!file.exists())
// file.mkdir();
//mkdirs()以多重文件夹目录形式创建文件
File file2 = new File("D:\\\\file1\\\\file11\\\\file111");
// file2.mkdirs();
File file3 = new File("D:\\\\文件\\\\24节气.jpg");
//getParent()获取父类文件的路径
String parentPath = file3.getParent();
System.out.println(parentPath);
//getParentFile()获取父类文件
File parentFile = file3.getParentFile();
System.out.println(parentFile);
//getAbsolutePath()获取绝对路径
System.out.println("文件绝对路径:" + file3.getAbsolutePath());
System.out.println("==============================");
//listFiles() 获取当前目录下所有的子文件
File file4 = new File("D:\\\\文件");
File[] files = file4.listFiles();
for (File oneFile:files)
System.out.println(oneFile.getName());
五、文件、目录拷贝
拷贝原理
1、拷贝文件
public class FileCopy
public static void main(String[] args)
FileInputStream fis = null;
FileOutputStream fos = null;
try
fis = new FileInputStream("D:/file/养生.pdf");
fos = new FileOutputStream("D:/file/养生.pdf");
byte[] bytes = new byte[1024 * 1024];//读取1MB
int readCount = 0;
//边读边写
while ((readCount = fis.read(bytes)) != -1)
fos.write(bytes,0,readCount);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (fis != null)
try
fis.close();
catch (IOException e)
e.printStackTrace();
if (fos != null)
try
fos.close();
catch (IOException e)
e.printStackTrace();
2、拷贝文件目录(文件夹和文件
/**
* 将一个文件目录拷贝到另一个盘下
* */
public class FileAllCopy
public static void main(String[] args)
File srcFile = new File("D:\\\\temp");
File destFile = new File("D:\\\\TempFile\\\\");
copyFiles(srcFile,destFile);
/**
* 复制文件目录
*
* @param srcFile 源文件
* @param destFile 目标文件
*/
private static void copyFiles(File srcFile, File destFile)
//如果是文件,则终止递归;且将文件拷贝到目标路径下
if (srcFile.isFile())
System.out.println("文件:" + srcFile.getAbsolutePath());
FileInputStream fis = null;
FileOutputStream fos = null;
try
fis = new FileInputStream(srcFile);
//一次读取1MB
byte[] bytes = new byte[1024 * 1024];
//获取源文件目录路径
String srcPath = srcFile.getAbsolutePath().substring(3);
//目标文件目录路径
String tempPath = destFile.getAbsolutePath().endsWith("\\\\") ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + "\\\\";
String destPath = tempPath + srcPath;
fos = new FileOutputStream(destPath);
int readCount = 0;
while ((readCount = fis.read(bytes)) != -1)
fos.write(bytes,0,readCount);
//刷新
fos.flush();
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (fis != null)
try
fis.close();
catch (IOException e)
e.printStackTrace();
if (fos != null)
try
fos.close();
catch (IOException e)
e.printStackTrace();
return;
//获取源目录的所有子文件
File[] files = srcFile.listFiles();
//遍历所有子文件
for (File src:files)
//如果是文件夹,判断是否存在;存在继续递归新建;不存在创建文件夹且继续递归
if (src.isDirectory())
// System.out.println("文件夹:" + file.getAbsolutePath());
//获取源文件目录路径
String srcPath = src.getAbsolutePath().substring(3);
//目标文件目录路径
String tempPath = destFile.getAbsolutePath().endsWith("\\\\") ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + "\\\\";
String destPath = tempPath + srcPath;
// System.out.println("源文件目录路径:" + srcPath);
System.out.println("目标文件目录路径:" + destPath);
//不存在创建多重目录
File dest = new File(destPath);
if (!dest.exists())
dest.mkdirs();
//递归创建文件目录
copyFiles(src,destFile);
六、序列化与反序列化
1、java序列化
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流
化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象
流进行读写操作时所引发的问题
2、实现 java 序列化
序列化的实现,将需要被序列化的类实现Serializable 接口,该接口没有需要实现的方法,
implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如:
FileOutputStream)来构造一个 ObjectOutputStream(对象流)对象,接着,使用
ObjectOutputStream 对象的 write Object(Object obj)方法就可以将参数为 obj 的对象写出(即保
存其状态),要恢复的话则用输入流
3、参与序列化和反序列化的对象,必须实现 Serializable 接口,不然抛出异常 异常: java.io.NotSerializableException: iostream.bean.Student Student对象不支持序列化
4、序列化多个对象(集合)
(1)将对象放到集合当中,序列化集合。 参与序列化的ArrayList集合以及集合中的元素都需要实现 java.io.Serializable接口
(2)ArrayList 也实现了 java.io.Serializable 接口 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
5、参与序列化和反序列化的对象,必须实现Serializable接口
6、源码中,Serializable接口当中什么代码都没有,只是一个标志接口:
public interface Serializable
标志接口起到标识标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊操作 java虚拟机看到Serializable这个标志接口之后,会为该类自动生成一个序列化版本号
7、序列化版本号
(1)如果直接修改了Student类,再去反序列化,这时会抛出异常
java.io.InvalidClassException: iostream.bean.Student; local class incompatible:
stream classdesc serialVersionUID = 4869515950171901002,
local class serialVersionUID = 5648694406856253046
(2)Java中区分类的机制
【1】首先通过类名进行比对,如果类名不一样,肯定不是同一个类
【2】如果类名一样,再通过序列化版本号进行区分
(3)自动生成序列化版本号
Java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号
private static final long serialVersionUID = 5648694406856253046L;
即使没有手动写出来,java虚拟机会默认提供这个序列化版本号。
如果不同的程序员编写了同一个类,但“这两个类确实不是同一个类”
对于java虚拟机来说,这两个类都实现了Serializable接口;都有默认的序列化版本号,他们的序列化版本号不一样
(4)自动生成序列化版本号优缺点
优点:自动生成可以去分类
缺点:自定义对象创建之后不能再做修改,只要修改会重新编译,会导致生成全新的序列化版本号,这时java虚拟机会认为是一个新的类
8、一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号 即使这个类代码被修改,只要序列化版本号不变,java虚拟机会认为是同一个类
Student类
/**
1、参与序列化和反序列化的对象,必须实现 Serializable 接口,
不然抛出异常
java.io.NotSerializableException: iostream.bean.Student
Student对象不支持序列化
* */
public class Student implements Serializable
/**
* Java虚拟机看到Serializable接口之后,会自动生成一个序列化版本号
* 没有手动写出来,java虚拟机会默认提供这个序列化版本号
* IDEA也会自动生成序列化版本号
* */
//private static final long serialVersionUID = 5648694406856253046L;
/**
* 之后,Student类源代码被别的程序员改动,会重新编译,生成新的字节码文件,且class文件再次运行,java虚拟机也会自动生成新的序列化版本号
* java虚拟机识别一个类的时候先通过类名,如果类名一致,再通过序列化版本号
* 建议将序列化版本号手动的写出来不建议自动生成
* */
private static final long serialVersionUID = 1L;
private int age;
private String name;
/**
* 序列化之后被别的程序员修改,此时再反序列化会抛异常
* java.io.InvalidClassException: iostream.bean.Student;
* local class incompatible:
* stream classdesc serialVersionUID = 4869515950171901002,
* local class serialVersionUID = 5648694406856253046
*
* 加上固定的private static final long serialVersionUID = 1L; 就不会抛异常了
* */
// private String address;
public Student()
public Student(int age,String name)
this.age = age;
this.name = name;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
public String getName()
return name;
public void setName(String name)
this.name = name;
@Override
public String toString()
return "Student[age = " + this.age + ",name = " + this.name + "]";
ObjectOutputStream
public class ObjectOutputStreamTest
public static void main(String[] args)
ObjectOutputStream oos = null;
ObjectOutputStream oos1 = null;
try
System.out.println("========序列化单个对象========");
oos = new ObjectOutputStream(new FileOutputStream("src/iostream/student"));
// Java
Student s = new Student(18,"张小五");
// 序列化Java对象
oos.writeObject(s);
//刷新流
oos.flush();
System.out.println("========序列化数组对象========");
oos1 = new ObjectOutputStream(new FileOutputStream("src/iostream/students"));
/**
* 1、一次序列化多个对象
* 将对象放到集合当中,序列化集合。
* 参与序列化的ArrayList集合以及集合中的元素都需要实现 java.io.Serializable接口
* 2、ArrayList 也实现了 java.io.Serializable 接口
* public class ArrayList<E> extends AbstractList<E>
* implements List<E>, RandomAccess, Cloneable, java.io.Serializable
* */
//创建List数组
List<Student> list = new ArrayList<>();
Student s1 = new Student(17,"王五");
Student s2 = new Student(16,"李四");
Student s3 = new Student(19,"王二");
Student s4 = new Student(15,"铁蛋");
Student s5 = new Student(16,"二狗");
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
oos1.writeObject(list);
oos1.flush();
catch (IOException e)
e.printStackTrace();
finally
if (oos != null)
try
oos.close();
catch (IOException e)
e.printStackTrace();
if (oos1 != null)
try
oos1.close();
catch (IOException e)
e.printStackTrace();
ObjectInputStream
public class ObjectInputStreamTest
public static void main(String[] args)
ObjectInputStream ois = null;
ObjectInputStream ois1 = null;
try
System.out.println("========反序列化单个对象========");
ois = new ObjectInputStream(new FileInputStream("src/iostream/student"));
// 开始反序列化,读
Student s = (Student) ois.readObject();
System.out.println(s);//Student[age = 18,name = 张小五]
System.out.println("========序列化数组对象========");
ois1 = new ObjectInputStream(new FileInputStream("src/iostream/students"));
// 开始反序列化,读
List<Student> list = (List<Student>) ois1.readObject();
for (Student student:list)
System.out.println(student);
/*
Student[age = 17,name = 王五]
Student[age = 16,name = 李四]
Student[age = 19,name = 王二]
Student[age = 15,name = 铁蛋]
Student[age = 16,name = 二狗]
*/
catch (IOException | ClassNotFoundException e)
e.printStackTrace();
finally
if (ois != null)
try
ois.close();
catch (IOException e)
e.printStackTrace();
if (ois1 != null)
try
ois1.close();
catch (IOException e)
e.printStackTrace();
七、IO + Properties集合
IO+Properties的联合使用
1、设计理念:
经常改变的数据,可以单独写到一个文件中,使用程序动态读取。
以后只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启。就可以拿到动态的信息
以上机制的这种文件被称为配置文件
并且当配置文件中的内容格式是:
key=value
把这种配置文件叫做属性配置文件
2、Java规范中要求:
属性配置文件建议以 .properties 结尾,但不是必须的
这种以.Java规范中要求:属性配置文件
Properties是专门存放属性配置文件内容的类
userInfo.properties
#建议key和value之间使用=方式
#=左边是key,=右边是value
username=admin
password=123456
#尽量不要有空格
name = zhangsan
#尽量不使用冒号:
#usernamex:admin
#属性配置文件的key重复的话,value会自动覆盖!
#password=admin123
public class IOPropertiesTest
public static void main(String[] args)
FileReader fr = null;
try
//输入流对象
fr = new FileReader("src/iostream/userInfo.properties");
/**
Properties是一个Map集合,key和value都是String类型
将userinfo文件中的数据加载到Properties对象当中
*/
Properties ps = new Properties();
/**
* 调用Properties对象的load()方法将文件中的数据加载到Map集合中
* 文件中的数据顺着流管道加载到Map集合中,其中 等号= 左边是key,等号= 右边是value
* */
ps.load(fr);
String userName = ps.getProperty("username");
String passWord = ps.getProperty("password");
System.out.println(userName);
System.out.println(passWord);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
finally
if (fr != null)
try
fr.close();
catch (IOException e)
e.printStackTrace();
八、BIO、NIO、AIO
1、BIO BIO 就是传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是 说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调 用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很 低,容易成为应用性能瓶颈。 2、NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel 、 Selector 、 Buffer 等新的抽象,可以构建 多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。 3、AIO AIO 是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,所以 人们叫它 AIO ( Asynchronous IO ),异步 IO 是基于事件和回调机制实现的,也就是应用操 作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续 的操作以上是关于Java--IO流;File类;文件目录拷贝;序列化与反序列化;Properties的主要内容,如果未能解决你的问题,请参考以下文章