11.26日笔记

DataOutputStream和DataInputStream

 都属于数据流:可以针对Java基本数据类型的数据进行读写操作

DataOutputStream构造方法

public DataOutputStream(OutputStream out)
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataStreamDemo {
	public static void main(String[] args) throws IOException {	
	write();	
	read();
	}

	//读数据
	private static void read() throws FileNotFoundException, IOException {
		//读数据
		//创建数据输入流对象
		DataInputStream dis = new DataInputStream(
				new FileInputStream("EDG.txt"));
		
		//读数据
		byte b = dis.readByte() ;
		int i = dis.readInt() ;
		short s = dis.readShort() ; 
		long l = dis.readLong() ;
		char ch = dis.readChar() ;
		boolean flag = dis.readBoolean() ;
		float f = dis.readFloat() ;
		double d = dis.readDouble() ;
		
		//释放资源
		dis.close() ;
		
		System.out.println(b);
		System.out.println(i);
		System.out.println(s);
		System.out.println(l);
		System.out.println(ch);
		System.out.println(flag);
		System.out.println(f);
		System.out.println(d);
	}
	
	
	//写数据
	private static void write() throws FileNotFoundException, IOException {
		//创建数据输出流对象
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(
				"dos.txt"));
		
		//写数据
		dos.writeByte(100) ;
		dos.writeInt(1000) ;
		dos.writeShort(120) ;
		dos.writeLong(1000000L);
		dos.writeChar('A') ;
		dos.writeBoolean(true) ;
		dos.writeFloat(12.34F) ; 
		dos.writeDouble(12.56) ;
		
		//释放资源
		dos.close() ;
	}
}

 ByteArrayInputStream和ByteArrayOutStream(重点)

 内存操作流:针对内存的数据进行操作的,程序一结束,这些内存中的数据就消失掉了!

 特点:针对小文件进行操作!(聊天室项目中使用它进行发送文件)

 ByteArrayOutputStream:

 public ByteArrayOutputStream():创建默认的缓冲区大小的内存操作输出流(单位是字节)

成员方法:

public byte[] toByteArray()创建一个新分配的 byte数组(将内存操作输出流对象转换成字节数组)

void reset():重置内存操作输出流

ByteArrayInputStream:内存操作输入流:

public ByteArrayInputStream(byte[] buf):参数数一个字节数组(缓冲数组)

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ByteArrayStreamDemo {
	public static void main(String[] args) throws IOException {
		//创建内存操作输出流对象
		ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
		//写数据
		for(int x = 0 ; x <5 ; x ++){
			baos.write(("hello"+x).getBytes()) ;
		}
		/**
		 * 内存操作流:查看其释放流对象的源码:
		 * public void close() throws IOException {}
		 * 并没有具体的关闭流对象,所以此流对象可以不关闭
		 */
		//关闭资源
//		baos.close() ;
		//将内存操作输出流对象转换成字节数组
		//public byte[] toByteArray()创建一个新分配的 byte 数组(将内存操作输出流对象转换成字节数组)
		byte[] buffer = baos.toByteArray() ;
		//创建内存操作输入流对象
		ByteArrayInputStream bais = new ByteArrayInputStream(buffer) ;
		//一次读取一个字节
		int by = 0 ;
		while((by=bais.read())!=-1){
			System.out.print((char)by);
		}
		//关闭
//		bais.close() ;
	}
}

打印流:

字节打印流:PrintStream

字符打印流:PrintWriter

打印流特点:

1)在复制文件的,打印流不能操作数据源,只能操作目的地的数据(只能输出数据)

2)打印流可以有自动刷新的功能

3)打印流可以直接针对文本文件进行操作:

什么情况下是直接可以针对文本文件进行操作?

查API的时候,看流中构造方法,只要构造方法的参数有File类或者是String类型,都可以针对文本文件进行操作

FileInputStream

FileOutputStream

FileReader

FileWriter

PrintWriter:

构造方法:

public PrintWriter(String fileName)
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterDemo {
	public static void main(String[] args) throws IOException {
		//创建字符打印流对象
		PrintWriter pw = new PrintWriter("pw.txt") ;
		//写数据
		pw.write("hello") ;
		pw.write("world") ;
		pw.write("Java") ;
		//刷新
		pw.flush() ;
		//释放资源
		pw.close() ;
	}
}

PrintWriter:有自动刷新功能:

public PrintWriter(Writer out,booleanautoFlush)

第二个参数指定为true,则启动自动刷新

PrintWriter pw = new PrintWriter(newFileWriter("pw.txt"),true) ;

加入自动刷新功能并且在写数据的时候,使用println():换行

        

 println("hello")

相当于:

pw.write("") ;

pw.newLine() ;

pw.flush() ;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterDemo2 {
	public static void main(String[] args) throws IOException {
		//创建字符打印流对象
		PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true) ;//启动自动刷新功能
		//写数据
	/*	pw.write("hello") ;
		pw.write("world") ;
		pw.write("java") ;*/
		//使用println
		//public void println(String x):打印字符串,并且终止该行
		pw.println("hello") ;
		pw.println("world") ;
		pw.println("java") ;
		//关闭流资源
		pw.close() ;
		
		
	}
}

复制文件

需求:将当前项目下的DataStreamDemo.java中的内容复制到当前项目下Copy.java文件中

数据源:DataStreamDemo.java---->BufferedReader---->读数据--->readLine()

目的地:Copy.java------>BufferedWriter---->写数据


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		/*//1)封装数据源
		BufferedReader br = new BufferedReader(new FileReader("DataStreamDemo.java")) ;
	
		//2)封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")) ;
		
		//使用BufferedReader中的特有功能读写操作
		String line = null ;
		while((line=br.readLine())!=null){
			//写数据
			bw.write(line) ;
			//换行
			bw.newLine() ;
			//刷新流
			bw.flush() ;
		}
		//释放资源
		bw.close() ;
		br.close() ;*/
		
		//改进
//		1)封装数据源
		BufferedReader br = new BufferedReader(new FileReader("DataStreamDemo.java")) ;
		
		2)封装目的地
		//创建字符打印流对象,并且启动自动刷新功能
		PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true) ;
		
		//读写操作
		String line = null ;
		while((line=br.readLine())!=null){
			//写数据
			pw.println(line) ;
		}
		
		//关闭资源
		pw.close() ;
		br.close() ;
	}
}

键盘录入的两种方式

1)Scanner类

Scanner sc = new Scanner(System.in) ;

2)使用IO流的形式进行录入数据

BufferedReader br = new BufferedReader(newInputStreamReader(System.in)) ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class SystemInDemo {
	public static void main(String[] args) throws IOException {
		//创建一个字节输入流对象
		/*InputStream is = System.in ; //标准输入流
		
		//要一次读取一行数据使用BufferedReader的readLine()
		//BufferedReader字符缓冲输入流只能针对字符流进行操作
		//将当前is对象转换字符流,使用字符转换输入流
		InputStreamReader isr = new InputStreamReader(is) ;
		//在创建BufferedReader对象
		BufferedReader br = new BufferedReader(isr) ;*/
		//另一种录入数据的方式
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		//录入数据
		System.out.println("请输入一个字符串:");
		String line = br.readLine() ;
		System.out.println("您录入的字符串是:"+line);
		System.out.println("请输入一个整数数据:");
		String s = br.readLine() ;
		int a = Integer.parseInt(s) ;//long l = Long.pareLong(s) ;
		System.out.println("您输入的整数是:"+a);
	}
}

标准输入和输出流

System类中有两个字段:

in:----->InputStream is = System.in ;

out----->PrintStream ps = System.out ;

System.out.println();

import java.io.PrintStream;
public class SystemOutDemo {
	public static void main(String[] args) {
		//经常使用输出语句
		System.out.println("helloworld") ;
		System.out.println("helloworld") ;
		
		
		//字节打印流
		PrintStream ps = System.out ;
		//字节打印流调用PrintStream类中的方法
//		ps.print() ;这个方法不存在
		ps.println("javaweb") ;//打印一个字符串数据并且终止当前行
	}
}

使用BufferedReader完成了录入数据:

 使该流封装字符转换输入流,然后使用字符转换输入流封装字节流

 按照上述方式,将BufferedWriter层层封装标准输出流,将数据打印控制台

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
public class SystemOutDemo2 {
	public static void main(String[] args)  {
		/*PrintStream ps = System.out ;
		//写入一个分隔符:newLine()是BufferedWriter类中的方法
//		BufferedWriter bw = new BufferedWriter(ps) ;
		//将字节打印流转换成字符流
		OutputStreamWriter osw = new OutputStreamWriter(ps) ;
		//创建字符缓冲输出流对象
		BufferedWriter bw = new BufferedWriter(osw) ;*/
			BufferedWriter bw = null ;
		try {
			bw = new BufferedWriter(new OutputStreamWriter(
					System.out));
			
			//写数据
			bw.write("hello") ;
			bw.newLine() ;
			bw.write("world") ;
			bw.newLine() ;
			bw.write("Javaweb") ;
			bw.newLine()  ;
			//刷新
			bw.flush() ;
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			//对流对象进行判断
			if( bw!=null){
				try {
					bw.close() ;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
}

5 java.io

RandomAccessFile:随机访问流:此类的实例支持对随机访问文件的读取和写入

不是实际意义上的流,因为它继承自Object类

常用的构造方法:

ublic RandomAccessFile(String name, Stringmode)

参数一:指定该文件的路径

参数二:指定的一种模式:常用的模式:"rw",这种模式是可以读也可以写

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
	public static void main(String[] args) throws IOException {
	write();
	read();
	}
	//读数据
	private static void read() throws FileNotFoundException, IOException {
		RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw") ;
		
		读数据
		//public long getFilePointer():返回此文件中的当前偏移量。 文件开头的偏移量(以字节为单位

		byte b = raf.readByte() ;
		System.out.println(b);
		System.out.println("getFilePointer:"+raf.getFilePointer());
		
		char ch = raf.readChar() ;
		System.out.println(ch);
		
		String	str	 = raf.readUTF() ;
		System.out.println(str);
		
		//关闭资源
		raf.close() ;
	}
	
	//写数据
	private static void write() throws FileNotFoundException, IOException {
		//创建随机访问流对象
		RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw") ;
		
		//写数据
		raf.writeByte(100) ;
		raf.writeChar('a') ;
		raf.writeUTF("中国") ;
		
		//关闭资源
		raf.close() ;
	}
}

 SequenceInputStream:合并流(读数据):表示其他输入流的逻辑串联

 合并流在复制文件的时候,只能操作数据源,不能操作目的地

 之前的操作:

a.txt-->b.txt

c.txt--->d.txt

现在有合并流(将两个文件中的内容复制到另一个文件中)

a.txt+b.txt--->c.txt文件中

构造方法:

 public SequenceInputStream(InputStreams1,InputStream s2)

需求:将DataStreamDemo.java和ByteArrayStreamDemo.java两个java文件中的内容复制到

Copy.java文件中

1)数据源:DataStreamDemo.java和ByteArrayStreamDemo.java----->SequenceInputStream----->分别读取第一个和第二个java文件

2)目的地:Copy.java----->BufferedOutputStream---->写数据

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStreampublic class SequenceInputStreamDemo {
	public static void main(String[] args) throws IOException {
		//分别封装这个两个java文件
		InputStream s1 = new FileInputStream("DataStreamDemo.java") ;
		InputStream s2 = new FileInputStream("ByteArrayStreamDemo.java") ;
		//创建合并流对象
		SequenceInputStream sis = new SequenceInputStream(s1, s2) ;
		//封装目的地
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream("Copy.java"));
		
		//一次一个字节数组
		byte[] bys = new byte[1024] ;
		int len = 0 ;
		while((len = sis.read(bys))!=-1){
			//写数据
			bos.write(bys, 0, len) ;
			bos.flush() ;
		}
		
//		释放资源
		sis.close() ;
		bos.close() ;
	}
}

SequenceInputStream的另一种构造方法:复制多个文件

 public SequenceInputStream(Enumeration<?extends InputStream> e)

 Vector集合中的特有功能:

 public Enumeration<E> elements()

 之前的操作:

        a.txt--->b.txt

        c.txt--->d.txt

         e.txt--->f.txt

 * 现在:a.txt+b.txt+e.txt---->f.txt

 需求:将DataStreamDemo.java,ByteArrayStreamDemo.java,以及CopyFileDemo.java将这三个文件中的内容复制到当前项目下:Copy.java文件中

分析:数据源:DataStreamDemo.java,ByteArrayStreamDemo.java,以及CopyFileDemo.java--->SequenceInputStream--->读数据

目的地:Copy.java----->BufferedOutStream---->写数据

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vectopublic class SequenceInputStreamDemo2 {
	public static void main(String[] args) throws IOException {
		//创建一个Vector集合,泛型数据类型<InputStream>
		Vector<InputStream> v = new Vector<InputStream>() ;
		//封装者三个java文件
		InputStream s1 = new FileInputStream("DataStreamDemo.java") ;
		InputStream s2 = new FileInputStream("ByteArrayStreamDemo.java") ;
		InputStream s3 = new FileInputStream("CopyFileDemo.java") ;
		//添加到集合中
		v.add(s1) ;
		v.add(s2) ;
		v.add(s3) ;
		//调用特有功能:
		//public Enumeration<E> elements()
		Enumeration<InputStream> en = v.elements() ;
		//创建合并刘对象
		SequenceInputStream sis = new SequenceInputStream(en) ;
		//封装目的地
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream("Copy.java"));
		
		//一次读取一个字节数组
		byte[] bys = new byte[1024] ;
		int len = 0 ;
		while((len=sis.read(bys))!=-1){
			//写数据
			bos.write(bys, 0, len) ;
			bos.flush() ;
		}
		
		//释放资源
		bos.close() ;
		sis.close() ;
	}
}

7

序列化流:将对象像流的方式或者网络传输中的数据写数据.对象---->流数据:ObjectOutputStream

反序列化:将流数据或者网络传输中的流数据读取出来.流数据---->还原成对象:ObjectInputStream

ObjectOutputStream中的成员方法:

 public final void writeObject(Object obj):将obj对象写入到当前的序列化流中

 ObjectInputStream中的成员方法:

 public final Object readObject():从当前反序列化流中读取一个对象

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectStreamDemo {
	public static void main(String[] args) throws Exception {
		write() ;
		read();
	}
	//读数据
	private static void read() throws IOException, FileNotFoundException,
			ClassNotFoundException {
		//反序列化:将当前流数据--->对象
		//创建一个反序列化流对象
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				"oos.txt"));
		//使用反序列化:将流数据--->对象
		Object obj = ois.readObject() ;
		//关闭资源
		ois.close() ;
		System.out.println(obj);
	}
	//序列化
	private static void write() throws IOException {
		//创建一个对象
		Person p = new Person("高圆圆", 27) ;
		//创建一个序列化流对象
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
				"oos.txt"));
		//写数据
//		writeObject(Object obj)
		oos.writeObject(p) ;
		//释放资源
		oos.close() ;
	}
}

报异常了:NotSerializableException(没有实现序列化接口的异常)              

Serializeable:序列化接口

类通过实现java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化,如果自定义一个类没有实现这个接口,就不能使用

序列化或者是反序列化!如果一个接口中没有字段,没有构造方法,没有成员方法,叫做标记接口

 更改了Pereson类中的一个成员变量,重新去反序列化:出现异常:

 stream classdesc serialVersionUID =-1389484787812115752,

 local class serialVersionUID = -8105095612190351088

 如果一个类实现了标记接口:Serializable,那么对应的该类加载的时候,会产生一个ID

Person.class------->id ,假设id=100

成员变量:name和age---->对应一个固定id= 100

 后面重新改动了Person类的成员,Person.class---->id = 200 ;name,age-------->id = 200 ;

  序列化和反序列化版本号不一致,会出现InvalidClassException

解决这个异常两种方案:

 1)要么改动当前某个类中的数据之后,然后重新序列化和反序列化

 这种做法不符实实际要求,在实际开发中,可能直接读数据:将流数据--->还原成对象

 2)发现黄色警告线,点击它:生成一个固定ID

注意事项:

比如一个类中有很多成员变量,并不想让一些成员变量被序列化,Java提供了一个关键字:

transient:不用被序列化的时候用它修饰

  序列化和反序列化考点:

1)将对象--->流数据或者流数据--->对象,该对象所在的类要实现一个标记接口:serializable           多线程有一个关键字:同步机制(synchronized)

 2)序列化和反序列化生产的版本Id不一致的时候,会出现异常,所以使用生产随机ID或者固定ID解决

 3)transient:修饰的变量不会被序列化...

 

//如果启用序列化功能,那么必须实现一个接口:Serializable

public class Person implements Serializable{

         privatestatic final long serialVersionUID = 1L;

         /**

          * default Servial ID

          */

生成一个ID

 

 

 

 

 

 

 

 

Properties:属性集合类,该类继承自Hashtable<K,V>,该类属于Map集合

Properties 类表示了一个持久的属性集。

Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串(一般情况:它用作配置文件去使用,MySQL或者Oracle中用它做配置文件)

构造方法:

public Properties():创建一个空属性列表

import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
	public static void main(String[] args) {
		//创建属性集合类对象
//		Properties<String,String> prop = new Properties<String,String>() ;
		Properties prop = new Properties() ;
		//既然是Map集合怎么添加元素?
		prop.put("RNG", "666") ;
		prop.put("EDG", "233") ;
		prop.put("LGD", "334") ;
			
		//遍历集合
		//获取所有的键的集合
		Set<Object> keySet = prop.keySet() ;
		//增强for遍历
		for(Object key :keySet){
			Object value = prop.get(key) ;
			System.out.println(key+"="+value);
		}
	}
}

属性集合类:Properties有自己的遍历和添加元素的功能

 给属性列表中添加元素:

public Object setProperty(String key,Stringvalue)

public Set<String>stringPropertyNames():获取当前属性列表中所有的键的集合,键值都是String类型

public String getProperty(String key)用指定的键在此属性列表中搜索属性值

import java.util.Properties;
import java.util.Set;
public class PropertiesDemo2 {
	public static void main(String[] args) {
		//创建属性集合类对象
		Properties prop = new Properties() ;
		//添加元素
		//public Object setProperty(String key,String value)
		prop.setProperty("RNG", "666") ;
		prop.setProperty("EDG", "233") ;
		prop.setProperty("LGD", "334") ;
		
		//遍历属性列表:public Set<String> stringPropertyNames()
		Set<String> keySet = prop.stringPropertyNames() ;
		for(String key:keySet){
			//通过键搜索值
			//public String getProperty(String key)
			String value = prop.getProperty(key) ;
			System.out.println(key+"="+value);
		}
		
	}
}

Properties 可保存在流中或从流中加载。

将文件中的数据加载到属性集合中:public void load(Reader reader)

将属性集合中的数据保存到文件中:public void store(Writer writer,String comments)

第二个参数:comments:对当前属性列表的描述

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo {
	public static void main(String[] args) throws IOException {
		myStore();
		myLoad() ;
	}
	//将文件中的数据加载到属性集合中
	private static void myLoad() throws IOException {
		//public void load(Reader reader)
		//创建属性集合类对象
		Properties prop = new Properties() ;
=		//创建字符输入流对象
		FileReader fr = new FileReader("name.txt") ;
		//调用方法
		prop.load(fr) ;
		//释放资源
		fr.close() ;
		//显示输出
		System.out.println(prop);
	}

	private static void myStore() throws IOException {
		//创建属性集合类对象
		Properties prop = new Properties();
		//给属性集合中添加数据
		prop.setProperty("RNG", "666") ;
		prop.setProperty("EDG", "233") ;
		prop.setProperty("LGD", "334") ;
		//将属性列表中的数据保存到文件中
//		public void store(Writer writer,String comments)
		//创建字符输出流
		FileWriter fw = new FileWriter("name.txt") ;
		//调用方法
		prop.store(fw, "names content") ;
		//释放资源
		fw.close() ;
	}
}

课堂练习

 有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。

 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”

 分析:

  1)将user.txt文件中的内容加载到属性集合类中

  2)遍历属性列表:获取所有的键的集合:stringPropertyNames(Stringkey );

  判断:如果"lisi"这个键中key值相等

  修改:setProperty(key,"100");             

  3)重新将属性集合中的数据写到user.txt中

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Properties;
import java.util.Set;
public class PropertiesTest {
	public static void main(String[] args) throws IOException {
		//创建属性集合类对象
		Properties prop = new Properties() ;
		//创建字符输入流对象
		Reader r = new FileReader("user.txt") ;
		//加载到属性集合中
		prop.load(r) ;
		//关闭流资源
		r.close() ;
		//遍历属性列表
		Set<String> keySet = prop.stringPropertyNames() ;
		for(String key:keySet){
			//判断
			if("lisi".equals(key)){
				//修改
				prop.setProperty(key, "100") ;
			}
		}
		//创建字符输出流丢向
		Writer w = new FileWriter("user.txt") ;
		//调用功能
		prop.store(w, "content") ;
		//释放资源
		w.close() ;
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值