Java中的IO框架流三

2017-05-21  本文已影响0人  征程_Journey

1      IO(三)No20

1.1    Properties 属性集

Properties属性集,主要用于操作配置属性,

是以键值对的方式来保存属性,并且都是String类型

继承自Hashtable类,所以是一个Map集合,具有Map接口中的所有方法,但是在保存和读取数据的时候不建议使用put和get方法,因为有可能会出现异常,建议使用Properties中特有的方法进行数据的存储

常用方法:

1、添加、获取

setProperty(String key,String value):添加键值对

getProperty(String key):通过键获取值《getProperty(Stringkey)

getProperty(Stringkey,StringdefaultValue)》如果键不存在返回默认值

2、保存、加载(配合IO流使用)

store():将数据通过输出流写到指定文件中

store(OutputStreamout,Stringcomments)

store(Writerwriter,Stringcomments)参数二:代表注释

load():通过输入流读取指定文件中的数据

load(InputStreaminStream)load(Readerreader)

3、遍历数据

list():将集合中的所有数据输出到指定的流中(一般用于调试)

list(PrintStreamout)list(PrintWriterout)

stringPropertyNames():获取集合中键的集合(键的类型是String类型)

1.1.1  示例程序

publicclass Demo {

public static void main(String[] args)throws IOException {

Properties prop = newProperties();

/*

* Properties类继承于Hashtable类,所以可以使用put方法添加键值对,

* 但是Properties类中的数据要求应该都是String类型,使用put方法返回可能会出问题

* 官方建议使用setProperty()方法添加键值对

*/

//               prop.put("textsize",18);

//               prop.get("textsize");

//保存值

prop.setProperty("textsize","18");

prop.setProperty("textcolor","red");

//获取值

String size =prop.getProperty("textsize");

String color=prop.getProperty("textcolor");

System.out.println(size);

System.out.println(color);

//将属性保存到磁盘上

//Properties的作用是将数据持久化保存,实际上就是将数据保存在磁盘上

//               prop.save(out, comments);

FileOutputStream fos = new FileOutputStream("prop.properties");

prop.store(fos, "注释");

//从磁盘上读取属性数据

Properties prop2 = newProperties();

FileInputStream fis = newFileInputStream("prop.properties");

prop2.load(fis);

System.out.println(prop2);

//遍历Properties集合(是Map集合)

//list方法一般是用于调试用的

prop2.list(System.out);

//传统的遍历Map集合的方式,通过keyset方法获取键的集合,但是元素都是Object类型

//               prop2.keySet();

Set     keyset = prop2.stringPropertyNames();

for (String key : keyset) {

String value =prop2.getProperty(key);

System.out.println(key+"..........."+value);

}

}

}

实例:写一个程序,要求用户只能打开5次,在第6次打开的时候就抛出异常提示“打开失败”

publicclass Ex {

public static void main(String[] args){

System.out.println("程序开启.......");

//检测使用的次数

check();

System.out.println("程序正常运行.......");

System.out.println("程序结束.......");

}

private static void check() {

/*

* 思路:记录用户打开程序的次数,每次打开的时候都记一次,将次数保存在配置文件中,

* 每次打开的时候读取上一次记录的次数,如果超出上限,就提示用户

*/

//

FileInputStream fis =null;

FileOutputStream fos = null;

try {

Properties prop =new Properties();

File file = newFile("prop_ex.properties");

//要保证文件存在

if(!file.exists()){

file.createNewFile();

}

fis = new FileInputStream(file);

//从文件中加载数据到Properties集合中

prop.load(fis);

//通过键获取值,如果键值对不存在,就返回指定的默认值

int count=Integer.parseInt(prop.getProperty("count","0"));

count ++;

//判断打开的次数是否已经超过了上限

if(count>5){

throw newRuntimeException("适用用次数已经超过5次上限,请续费!.......");

}else{

//如果没有超过

fos = newFileOutputStream(file);

prop.setProperty("count",String.valueOf(count));

prop.store(fos,"open count");

}

} catch (IOException e) {

// TODO: handleexception

}finally{

if(fos != null){

try {

fos.close();

fos= null;

} catch(IOException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

if(fis != null){

try {

fis.close();

fis= null;

} catch(IOException e) {

//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

}

1.2    内存流

数组流

byte[] bytes ={97,98,99,100,101};//源字节数组

ByteArrayInputStream bais =//在源数组上创建一个内存输入流

newByteArrayInputStream(bytes);

int n=0;

byte[] buf = new byte[4];

//读4个字节放到缓冲buf中,返回有效读取数

while((n=bais.read(buf))!=-1){

for(int i=0;i

System.out.println(buf[i]);  //打印

}

}

}

//不需要关闭

//创建一个内存输出流,可以通过它向内置的字节数组中写字节

ByteArrayOutputStream baos=new ByteArrayOutputStream();

baos.write(65);//往内置字节数组中写一个字节

baos.write(66);

baos.write(67);

//从中拿出之前写的字节生成的数组

byte[] array =baos.toByteArray();

for(byte b : array){//遍历打印,用于验证

System.out.println(b);

}

//源文件流

FileInputStream fis = newFileInputStream("g:/output.txt");

//目标内存输出流

ByteArrayOutputStream baos=new  ByteArrayOutputStream();

int n=0;

byte[] buf = new byte[4];//缓冲数组创建

//每次从文件读4个字节方法缓冲中,有效字节数赋给n,和-1比较判断是否读完

while((n=fis.read(buf))!=-1){

baos.write(buf,0,n);   //没有读完就将有效字节写到内存输出流

}

fis.close();//需要关闭

//               baos.close();//不需要关闭

byte[]array=baos.toByteArray();   //获取字节数组

for (byte b : array) {//遍历,验证

System.out.println((char)b);

}

FileInputStream fis =new FileInputStream(

"g:/MySQL-connector-Java-5.1.7-bin.jar");

ByteArrayOutputStream baos =new ByteArrayOutputStream();

int n = 0;

byte[] buf = newbyte[1024];//缓冲

while ((n = fis.read(buf)) !=-1) {//从文件读1024字节,有效字节数赋值给n,和-1比较判断是否结束

baos.write(buf, 0,n);//把有效字节写到内存输出流

}

fis.close();

byte[] array =baos.toByteArray(); //用写进的字节生成数组

//准备从这个字节数组中读字节

ByteArrayInputStream bais =new ByteArrayInputStream(array);

FileOutputStream fos = newFileOutputStream("g:/copy.jar");

while ((n = bais.read(buf))!= -1) {//从数组读1024字节,有效字节数赋给n,和-1比较

fos.write(buf, 0,n); //把有效字节写到copy.jar

}

fos.close();

FileInputStream fis = newFileInputStream("g:/mysql-connector-java-5.1.7-bin.jar");

ByteArrayOutputStream baos=new ByteArrayOutputStream();

int n= 0;

byte[] buf = new byte[1024];

while((n=fis.read(buf))!=-1){//读源文件只进行一次

baos.write(buf,0,n);

}

fis.close();

byte[] array =baos.toByteArray();

//把文件放到内存中,这些动作不重复进行,这些动作包含了对磁盘的操作

//把内存中的内容拷贝到文件,重复进行

for(int i=1;i<=100;i++){

ByteArrayInputStreambais = new ByteArrayInputStream(array);

FileOutputStream fos= new FileOutputStream("g:/100/"+i+".jar");

//这里也要读100次,但是每次都是读内存数组,所以效率大大提高

while((n=bais.read(buf))!=-1){

fos.write(buf,0,n);

}

fos.close();

}

内存流(字节数组)节点流、字节流

ByteArrayInputStream

ByteArrayOutputStream

构造方法:

ByteArrayInputStream(byte[]bytes)创建一个内存流,可以从参数字节数组中读取字节

常用方法:

int read()

int read(byte[] buf)

不需要调用close()方法

构造方法:

ByteArrayOutputStream()创建一个内存输出流,无参数,可以往内置的字节数组中写字节

常用方法:

write(int b)

write(byte[] buf,intoff,int len)

不需要调用close()方法

toByteArray()获得字节数组(之前写到其中的字节组成的字节数组)

在文件小且不经常变更的情况下,可以用内存流先进行缓存,避免反复磁盘操作

实例:

public static void main(String[] args)throws IOException {

//字节数组输出流

//是以数组作为数据源,将数据写到数组中

//当数组输出流被创建的时候内部会自动创建一个数组

ByteArrayOutputStream baso =new ByteArrayOutputStream();

//将数据写出到数组流内部的数组(内存)中

baso.write("强风125".getBytes());

//取出流中的字节数组

byte[]buf  =baso.toByteArray();

System.out.println(newString(buf));

//在这里因为操作的是内存,所以不需要释放存放

//               baso.close();

//使用场景:从网上下载图片并显示在界面上

//从内存数组中去数据

ByteArrayInputStream bais =new ByteArrayInputStream(buf);

byte[] cubf  = new byte[1024];

bais.read(cubf);

System.out.println(newString(cubf));

//如果一个数组中的数据比较多,需要分批读取,那么使用数组流能简化我们的代码

//比如:现在有一个字节数组大小为1000,每次读取300个字节,自到将数据读完

}

1.3    对象流

对象流是一种处理流、字节流

对象流

ObjectInputStream

readObject()

ObjectOutputStream

writeObject()

注意事项:

1、被对象流操作的对象必须先进行序列化(实现Serializable接口)

1)需要在类中定义一个静态常量(序列值,static final longserialVersionUID)

2)在数据序列化的时候不会对静态字段(static )和瞬态字段(transient)进行序列化

2、一个文件只能存储一个对象

实例:

publicclass Demo {

public static void main(String[] args)throws IOException, ClassNotFoundException {

//               test1();

//               writeObj();

readObj();

}

private static void readObj() throwsIOException, ClassNotFoundException {

FileInputStream fis = newFileInputStream("objdemo.object");

ObjectInputStream ois = new ObjectInputStream(fis);

//内部自动进行了反序列化

Student stu =(Student)ois.readObject();

System.out.println(stu);

}

private static void writeObj() throwsIOException {

Student stu = new Student("小强", "男", 18);

//对象流,用于直接操作对象

FileOutputStream fos = newFileOutputStream("objdemo.object");

ObjectOutputStream oos = newObjectOutputStream(fos);

//将对象写出到指定设备

//注意:对象流操作的对象必须进行序列化

//序列化:只需要实现Serializable

oos.writeObject(stu);

oos.close();

}

private static void test1() throwsIOException, FileNotFoundException {

Student stu = newStudent("小强","男", 18);

FileWriter fw =  newFileWriter("object.txt");

fw.write(stu.name+"|");

fw.write(stu.gender+"|");

fw.write(stu.age +"");

fw.close();

//从磁盘上读取对象的数据并生成对象

BufferedReader br = new BufferedReader(newFileReader("object.txt"));

String line = br.readLine();

String[] strs = line.split("\\|");

String name = strs[0];

String gender = strs[1];

int age = Integer.parseInt(strs[2]);

Student stu2 = new Student(name, gender, age);

System.out.println(stu2);

}

}

classStudent implements Serializable/*标记接口*/{

/**

* 序列值,用于标记类的唯一性

* 如果没有指定序列值,那么编译器会自动根据类中的成员来自动生成一个序列值

* 建议:在序列化的时候最好要写上序列值

*/

private static final long serialVersionUID= 10000L;

/**

* static 修饰的类成员不会被序列化

*/

String name;

String gender;

transient int age;     //瞬态的(不会进行序列化)

public Student(String name, Stringgender, int age) {

this.name = name;

this.gender = gender;

this.age = age;

}

@Override

public String toString() {

return "Student[name=" + name + ", gender=" + gender + ", age=" + age

+"]";

}

}

1.3.1  ObjectOutputStream

//文件的文件输出流

FileOutputStream fos = newFileOutputStream("g:/obj");

//用对象输出流去处理、装饰fos文件输出流

ObjectOutputStream oos = newObjectOutputStream(fos);

oos.writeObject("1000phone");//写一个字符串对象到流中

oos.close();

//对象流装饰文件流

ObjectOutputStream oos = newObjectOutputStream(

newFileOutputStream("g:/elephant"));

//初始化对象

Elephant mike = newElephant("Mike", 1000);

oos.writeObject(mike);    //把大象塞进去

oos.close();

构造方法:ObjectOutputStream(OutputStream os)参数是它要处理、装饰的流,增加了写对象的功能

writeObject(Objectobj)

1.3.2  ObjectInputStream

ObjectInputStream ois= //用对象流装饰文件流

newObjectInputStream(new FileInputStream("g:/obj"));

String str =(String)ois.readObject();   //读一个对象

System.out.println("从obj文件中拿出来了:"+str);

ois.close();

ObjectInputStream ois= new ObjectInputStream(

newFileInputStream("g:/elephant"));

//把大象从流中拖出来,拿到的是Object类型,强转为大象类型

Elephant e =(Elephant)ois.readObject();

System.out.println(e.getName()+"   "+e.getWeight());

ois.close();

构造方法:ObjectInputStream(InputStream is)参数是它要处理、装饰的流,增加了读对象的功能

Object readObject()

对象流读写,写的和读的类型一定要一致。

对象流读写的对象必须要可序列化,必须实现Serializable接口,这个接口无抽象方法。

用途:信息的存储、信息在网络上的传递、信息在组件间传递

1.4    输出流(打印流)

PrintWriterpw = new PrintWriter(

newFileOutputStream("g:/answer.txt",true));

//由于构造方法第二个参数为true ,println会自动刷缓存

pw.println("1000phone");//打印1000phone到文件中并换行

pw.println("Android");//打印android到文件中并换行

pw.println("java");//打印java到文件中并换行

pw.close();

PrintWriter输出流、字符流、处理流

构造方法:

PrintWriter(OutputStreamos,boolean autoFlush)第一个参数是所要装饰的字节输出流,第二个参数是表示是否自动刷缓存

PrintWriter(Writerwriter,boolean autoFlush)装饰字符流

PrintWriter(Stringpath,String csn)在以第一个参数为路径的文件上建立打印流,字符集由第二个参数指定

println()打印并且换行,在autoFlush为true时,会自动刷缓存

PrintStream用法和PrintWriter差不多,构造方法少一点

实例

publicstatic void main(String[] args) throws IOException {

// 打印流(只有输出流)PrintStream(字节打印流)  PrintWriter (字符打印流)

//               PrintStream ps = new PrintStream(newFileOutputStream("print.txt"));

PrintStream ps = newPrintStream("print.txt");

/*ps.print(true);

ps.print("中");

ps.print("f");*/

ps.print(18);    //编码

ps.write(97);    //字面值

ps.close();

}

1.5    数据流

DataOutputStream dos= //用数据流装饰文件流

newDataOutputStream(new FileOutputStream("g:/answer.txt"));

dos.writeInt(101);//向数据流中写100

dos.writeInt(100);

dos.writeInt(70);

dos.writeInt(66);

dos.close();//关闭处理会自动关闭所装饰的流

DataInputStream dis =new DataInputStream(

new FileInputStream("g:/answer.txt"));

int a=dis.readInt();//用数据流装饰文件流

System.out.println(a);

System.out.println(dis.readInt());//打印读出的int数据

System.out.println(dis.readInt());

System.out.println(dis.readInt());

dis.close();

DataOutputStream数据输出流,字节流、处理流

DataOutputStream(OutputStreamos)构造方法参数为它所装饰的字节输出流,添加了写基本类型数据的功能

writeInt(int i)

writeXXX(xxx i)

DataInputStream数据输入流

DataInputStream(InputStreamis)构造方法参数为它所装饰的字节输入流,添加了读基本数据类型的功能

int readInt()

xxx readXXX()

实例:

publicstatic void main(String[] args) throws IOException {

//数据流(过滤流)

FileOutputStream fos = newFileOutputStream("data.txt");

DataOutputStream oos = newDataOutputStream(fos);

oos.writeByte(100);

oos.writeChar('中');

oos.writeShort(1000);

oos.writeInt(1022);

oos.writeLong(12025);

oos.writeFloat(12.2f);

oos.writeDouble(15.4524);

oos.writeBoolean(true);

oos.close();

//读取数据

FileInputStream fis = new FileInputStream("data.txt");

DataInputStream dis = new DataInputStream(fis);

System.out.println(dis.readByte());

System.out.println(dis.readChar());

System.out.println(dis.readShort());

System.out.println(dis.readInt());

System.out.println(dis.readLong());

System.out.println(dis.readFloat());

System.out.println(dis.readDouble());

dis.close();

}

1.6    装饰模式

装饰模式:

1、把被装饰者通过构造方法传入装饰者

2、被装饰者和装饰者具有相同的方法(方法名、返回、参数)、具有相同的接口或父类

3、被装饰者以属性的形式存在于装饰者中

1.7    随机访问文件

RandomAccessFile raf= new RandomAccessFile("g:/answer.txt", "rw");

raf.write(65);//A|

raf.write(66);//AB|

raf.seek(0);//将游标一下子跳到第一个位置|AB

raf.write(67);

raf.write(68);

raf.close();

RandomAccessFile raf=new RandomAccessFile("g:/answer.txt", "r");

System.out.println(raf.read());

System.out.println(raf.read());

raf.seek(0);  //游标放到最前

System.out.println(raf.read());

System.out.println(raf.read());

raf.close();

RandomAccessFile随机访问文件,不是InputStream、OutputStream、Reader、Writer中的任一个子类

RandomAcceessFile(Stringpath,String mode)

构造方法第一个参数表示文件路径,第二个参数打开模式,如果是"rw"表示可读可写,如果是"r"表示只读

seek(int pos)定位,游标可以随便向前向后跳,只要不超出范围(Stream、Reader、Writer只能往后不能往前)

上一篇下一篇

猜你喜欢

热点阅读