Properties类:
Properties类概述:
- Properties是hashtable的子类。也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串,不需要泛型定义。
- Properties是不仅可以操作键值对信息,而且可以操作硬盘上的键值对信息。是集合中和IO技术相结合的集合容器。
import java.io.*;
import java.util.*;
class PropertiesDemo
{
public static void main(String[] args) throws IOException
{
//method_1();
loadDemo();
}
public static void loadDemo()throws IOException
{
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("info.txt");
//将流中的数据加载进集合。
prop.load(fis);
//setProperty改变的是内存的结果
prop.setProperty("wangwu","39");
FileOutputStream fos = new FileOutputStream("info.txt");
//haha是注入信息,注释,#代表注释信息,不会被Properties所加载,Properties所加载的信息必须是键值对
//那么在加载数据时,需要数据有固定的格式,键=值
prop.store(fos,"haha");
// System.out.println(prop);
prop.list(System.out);
fos.close();
fis.close();
}
//演示,如何将流中的数据存储到集合中。
//想要将info.txt中键值数据存到集合中进行操作。
/*
1,用一个流和info.txt文件关联。
2,读取一行数据,将该行数据用"="进行切割。
3,等号左边作为键,右边作为值。存入到Properties集合中即可。
*/
public static void method_1()throws IOException
{
BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));
String line = null;
Properties prop = new Properties();
while((line=bufr.readLine())!=null)
{
//split是切割
String[] arr = line.split("=");
///System.out.println(arr[0]+"...."+arr[1]);
prop.setProperty(arr[0],arr[1]);
}
bufr.close();
System.out.println(prop);
}
//设置和获取元素。set和get方法
public static void setAndGet()
{
Properties prop = new Properties();
//setProperty设置键值对
prop.setProperty("zhangsan","30");
prop.setProperty("lisi","39");
// System.out.println(prop);
String value = prop.getProperty("lisi");
//System.out.println(value);
//89+""转化成字符型
prop.setProperty("lisi",89+"");
Set<String> names = prop.stringPropertyNames();
for(String s : names)
{
System.out.println(s+":"+prop.getProperty(s));
}
}
}
配置文件:用于记录应用程序的运行次数,当运行次数已到, 给出 注册的提示。并不再让该程序执行。
1·很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。
2·下一次在启动该程序,又重新开始从0计数。
这样不是我们想要的。
3·程序即使结束,该计数器的值也存在。
下次程序启动在会先加载该计数器的值并加1后在重新存储起来。
4·所以要建立一个配置文件。用于记录该软件的使用次数。
5·该配置文件使用键值对的形式。这样便于阅读数据,并操作数据。
6·键值对数据是map集合。数据是以文件形式存储,使用io技术。那么map+io -->properties.
配置文件可以实现应用程序数据的共享。
现在要用的配置文件有两种:键值对的和xml文件
dom4j: dom for java解析xml文件
import java.io.*;
import java.util.*;
class RunCount
{
public static void main(String[] args) throws IOException
{
Properties prop = new Properties();
File file = new File("count.ini");
if(!file.exists())
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
//将流中的数据加载到集合当中
prop.load(fis);
int count = 0;
String value = prop.getProperty("time");
if(value!=null)
{
count = Integer.parseInt(value);
if(count>=5)
{
System.out.println("您好,使用次数已到,拿钱!");
return ;
}
}
count++;
prop.setProperty("time",count+"");
FileOutputStream fos = new FileOutputStream(file);
//注入信息没写
prop.store(fos,"");
fos.close();
fis.close();
}
}
/*
name=zhangsan
age=20
<persons>
<person id="001">
<name>zhagnsan</name>
<age>30</age>
<address>bj</address>
</person>
<person>
<name>...
</person>
</persons>
*/
打印流:
打印流概述:
1、打印流包括:PrintStream和PrintWriter
2、该流提供了打印方法,可以将各种数据类型的数据都原样打印。
字节打印流:PrintStream
构造方法中可接收的参数类型:
1、file对象。File2、字符串路径:String 3、字符输出流:OutputStream
字符串打印流:PrintWriter
构造方法中可接受的参数类型
1、file对象:File2、字符串路径:String3、字节输出流:OutputStream4、字符输出流:Writer
import java.io.*;
class PrintStreamDemo
{
public static void main(String[] args) throws IOException
{
//读取键盘录入,这句话非常的重要,一定要背下来
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
//把文件封装到流里面,可以实现字符刷新
PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
out.close();
bufr.close();
}
}
序列流(合并流):
序列流(合并流)概述:
1.序列流SequenceInputStream没有直接对应OutputStream,表示其它输入流的逻辑串联
2·SequenceInputStream可以将多个流连接成一个源
3·构造函数:
SequenceInputStream(Enumeration<? extends FileInputStream> e)
class SequenceDemo
{
public static void main(String[] args) throws IOException
{
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(new FileInputStream("c:\\1.txt"));
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
//Enumeration是个接口不是类(列举)为了实现遍历枚举也用于将输入流指定到 SequenceInputStream 中。
//注:此接口的功能与 Iterator 接口的功能是重复的。此外,Iterator 接口添加了一个可选的移除操作,并使用较短的方法名。
//新的实现应该优先考虑使用 Iterator 接口而不是 Enumeration 接口。
Enumeration<FileInputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
//创建缓冲区
byte[] buf = new byte[1024];
int len =0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
切割流资源:
1、先关联文件FileInputStream
2、定义写入流变量:FileOutputStream
3、创建数组,并定义切割所需的大小|
4、循环读写数据,并每次创建一个新写入流,创建完后并写入文件中
5、关闭流资源
import java.io.*;
import java.util.*;
class SplitFile
{
public static void main(String[] args) throws IOException
{
//splitFile();
merge();
}
public static void merge()throws IOException
{
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x=1; x<=3; x++)
{
al.add(new FileInputStream("c:\\splitfiles\\"+x+".part"));
}
final Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\splitfiles\\0.bmp");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
public static void splitFile()throws IOException
{
FileInputStream fis = new FileInputStream("c:\\1.bmp");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while((len=fis.read(buf))!=-1)
{
fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}
对象序列化
将堆内存中的对象存入硬盘,保留对象中的数据,称之为对象的持久化(或序列化)
特有方法:
1、write(int val) ---> 写入一个字节(最低八位)
2、writeInt(int vale) ---> 吸入一个32为int值
/*
对象的序列化
*/
import java.io.*;
//对象序列化测试
class ObjectStreamDemo
{
public static void main(String[] args) throws Exception
{
//对象写入流
writeObj();
//对象读取流
readObj();
}
//定义对象读取流
public static void readObj()throws Exception
{
//ObjectInputStream对细节对象进行操作
//创建对象读取流
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
//通过读取文件数据,返回对象
Person p = (Person)ois.readObject();
System.out.println(p);
//最终关闭流对象
ois.close();
}
//定义对象写入流
public static void writeObj()throws IOException
{
//创建对象写入流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
//写入对象数据
oos.writeObject(new Person("lisi0",399,"kr"));
//关闭流资源
oos.close();
}
}
/*
没有方法的接口通常称为标记
*/
import java.io.*;
//创建Person类,实现序列化
class Person implements Serializable
{
//定义自身的序列化方式
public static final long serialVersionUID = 42L;
/*serialVersion
给类一个可被编译器识别的的序列号,在编译类时,会分配一个long型UID,通过序列号,
将类存入硬盘中,并序列化,即持久化。序列号根据成员算出的。
静态不能被序列化。如果非静态成员也无需序列化,可以用transien修饰。*/
//定义私有属性
private String name;
//age被transient修饰后就不能被序列化了,保证其值只在堆内存中存在,而不再文本文件中存在
transient int age;
//静态成员变量不能被序列化
static String country = "cn";
//构造Person类
Person(String name,int age,String country)
{
this.name = name;
this.age = age;
this.country = country;
}
//覆写toString方法
public String toString()
{
return name+":"+age+":"+country;
}
}
PipedInputStream和PipedOutputStream是涉及到多线程技术的IO流对象。
步骤:
1、要先创建一个读和写的两个类,实现Runnable接口,因为是两个不同的线程,覆盖run方法,注意,需要在内部抛异常
2、创建两个管道流,并用connect()方法将两个流连接
3、创建读写对象,并传入两个线程内,并start执行
/*
管道流技术,涉及多线程技术
*/
import java.io.*;
//创建Read类,实现run方法
class Read implements Runnable
{
private PipedInputStream in;
Read(PipedInputStream in)
{
this.in = in;
}
//实现run方法
public void run()
{
try
{
byte[] buf = new byte[1024];
//读取写入的数据
System.out.println("读取前。。没有数据阻塞");
int len = in.read(buf);
System.out.println("读到数据。。阻塞结束");
String s= new String(buf,0,len);
System.out.println(s);
in.close();
}
catch (IOException e)
{
throw new RuntimeException("管道读取流失败");
}
}
}
//创建Write类
class Write implements Runnable
{
private PipedOutputStream out;
//Write构造函数
Write(PipedOutputStream out)
{
this.out = out;
}
//实现run方法
public void run()
{
try
{
//写入数据
System.out.println("开始写入数据,等待6秒后。");
Thread.sleep(6000);
out.write("piped lai la".getBytes());
out.close();
}
catch (Exception e)
{
throw new RuntimeException("管道输出流失败");
}
}
}
class PipedStreamDemo
{
public static void main(String[] args) throws IOException
{
//创建管道流对象
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
//将读取流(输入流)和写入流(输出流)关联起来
in.connect(out);
Read r = new Read(in);
Write w = new Write(out);
//创建读写对象,并创建线程对象
new Thread(r).start();
new Thread(w).start();
}
}
RandomAccessFile 类
RandomAccessFile 类概述:
1、RandomAccessFile称之为随机访问文件的类,自身具备读写方法。
2、该类不算是IO体系中的子类,而是直接继承Object,但是它是IO包成员,因为它具备读写功能,内部封装了一个数组,且通过指针对数组的元素进行操作,同时可通过seek改变指针的位置。
3、可以完成读写的原理:内部封装了字节输入流
4、构造函数:RandomAccessFile(File file,String mode),可已从它的构造函数中看出,该类只能操作文件(也有字符串),而且操作文件还有模式。
模式传入值:”r“:以只读方式打开;”rw“:打开以便读写
如果模式为只读,则不会创建文件,会去读一个已存在的文件,若文件不存在,则会出现异常,如果模式为rw,且该对象的构造函数要操作的文件不存在,会自动创建,如果存在,则不会覆盖,也可通过seek方法修改。
5.RandomAccessFile的最大的作用是实现多线程的下载
特有方法:
1、seek(int n):设置指针,可以将指针设置到前面或后面
2、skipBytes(int n):跳过指定字节数,不可往前跳
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//writeFile_2();
//readFile();
//System.out.println(Integer.toBinaryString(258));
}
public static void readFile()throws IOException
{
//"r"代表模式,只读
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//seek和skipBytes的区别是:skipBytes不能往回跳,seek可以前后的跳,可以随意改变指针。
//调整对象中指针。
//raf.seek(8*1);
//跳过指定的字节数
raf.skipBytes(8);
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static void writeFile_2()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8*0);
raf.write("周期".getBytes());
raf.writeInt(103);
raf.close();
}
public static void writeFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.write("李四".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99);
raf.close();
}
}
操作基本数据类型的流对象
操作基本数据类型的流对象:DataInputStream和DataOutputStream
这两个读写对象,可用于操作基本数据类型的流对象,包含读写各种基本数据类型的方法
import java.io.*;
class DataStreamDemo
{
public static void main(String[] args) throws IOException
{
//writeData();
//readData();
//writeUTFDemo();
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
//
// osw.write("你好");
// osw.close();
// readUTFDemo();
}
public static void readUTFDemo()throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
public static void writeUTFDemo()throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));
dos.writeUTF("你好");
dos.close();
}
public static void readData()throws IOException
{
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num="+num);
System.out.println("b="+b);
System.out.println("d="+d);
dis.close();
}
public static void writeData()throws IOException
{
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9887.543);
dos.close();
ObjectOutputStream oos = null;
oos.writeObject(new O());
}
}