字节流、字符流、对象流、properties文件

根据流的类型,可分为字节流、字符流、对象流。

关于字节流和字符流:

有stream字眼的就是字节流。有Reader/Writer字眼的就是字符流。两种字眼都有的就是转换流。

缓冲流都要以原来的文件非缓冲流做参数,如字符缓冲流(文件字符流),字节缓冲流(文件字节流)。

而文件流都是以文件或文件路径做参数。如文件字符流(String FilePath),文件字节流(String FilePath)

字节流、字符流、对象流、properties文件_第1张图片

一、文件字节流

1.写入到文件(出现乱码即需要修改编码)

                     FileOutputStream fos = null;
			try {
	            //写出去,写到文件上(如果文件已存在,则清空再写)
				fos = new FileOutputStream("F:\\test.txt");
				fos.write(97);//a  
				fos.write('s');//as
				fos.write("卑鄙是卑鄙者的通行证".getBytes());//as卑鄙是卑鄙者的通行证
				
				fos.write('的');//写入单个中文字符将会改变文件编码使文件乱码,正确写入中文应为上方法
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				if (fos != null) {
					try {
						fos.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}

追加修改

//jdk1.7之后提供了自动关流的方式
		/**
		 * try(流定义语句){
		 * 
		 * }catch{}
		 */
			try (FileOutputStream fos = new FileOutputStream("F:\\test.txt",true)){
				//后面的参数代表是否追加,默认false(清空再写)
				
				fos.write(98);//在不改动原文件基础上追加b
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

2.文件输入流

try(FileInputStream fis = new FileInputStream("F:\\test.txt")){//文件里:ab
			int a;
			while((a=fis.read())!=-1) {//读取到-1时表示没有文件可读了
				System.out.println(a);//我本来以为会打印 97 98,实际上打印239 187 191 97 98
				//查阅得知(239 187 191)是utf-8的BOM头
			}
		}catch(Exception e){
			
		}
try(FileInputStream fis = new FileInputStream("F:\\test.txt")){//文件里:哈哈
			for(int i=0;i<3;i++) fis.read();//跳过BOM文件头
			
			int a1=fis.read();//229
			int a2=fis.read();//147
			int a3=fis.read();//136
			
			byte[] bs = {(byte) a1,(byte) a2,(byte) a3};//一个中文是三个字节
			System.out.println(new String(bs));//哈
		}catch(Exception e){
			
		}

每次读取固定长度

            try(FileInputStream fis = new FileInputStream("F:\\test.txt")){//文件里:哈哈
			
			byte[] bs = new byte[1024];
			
			int len;
			while((len=fis.read(bs))!=-1) {
				System.out.println(new String(bs,0,len));//哈哈
			}
		}catch(Exception e){
			e.printStackTrace();
		}

3.拷贝文件

                    try(	
				FileInputStream fis = new FileInputStream("F:\\view.jpg");//从磁盘读
				FileOutputStream fos = new FileOutputStream("F:\\view2.jpg");//写入磁盘
				){
			byte[] bs = new byte[512];
			int len;
			while((len=fis.read(bs))!=-1) {
				fos.write(bs, 0, len);
			}
			
		}catch (Exception e) {
			// TODO: handle exception
		}

 

 

二、缓存字节流

try(	BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\\test.txt"));

){
			bos.write("我欲乘风破浪".getBytes());
			bos.flush();//将缓冲区的内容写入磁盘,close()之前会默认调用。但一般使用缓冲输出流的时候,都会显式地写出来
			
		}catch (Exception e) {
			// TODO: handle exception
		}

缓冲文件流也能够实现文件的读写、复制,而且速度更快。

 

 

三、转换流(字符流)

由于字节流操作中文不是特别方便,java提供了转换流。将字节流转换成字符流。

InputStreamReader/outputStreamWriter 是字节流通向字符流的桥梁:它使用指定的编码读写字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,默认接受平台设置的字符集。

需要注意的是,字符流只能操作纯文本文件。所以不要用该流去拷贝、传输图片、视频等非文本文件。

字符流=字节流+编码表。

//使用指定编码写到磁盘
		try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\test.txt"),"GBK")){
			osw.write("借问梅花何处落");
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		//用指定编码读
		try(InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\test.txt"), "GBK")){
			char[] chs = new char[1024];
			int len;
			while((len=isr.read(chs))!=-1) {
				System.out.println(new String(chs,0,len));
			}
		}catch(Exception e) {
			
		}

 

 

四、文件字符流(字符流)

来读取、写入字符文件的快捷类

try (FileWriter fw = new FileWriter("F:\\test.txt");
					){
				fw.write("心心相印");
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			
try (FileReader fr = new FileReader("F:\\test.txt")){
				char[] chs = new char[10];
				int len;
				while((len=fr.read(chs))!=-1) {
					System.out.println(new String(chs,0,len));
				}
				
			} catch (Exception e) {
				// TODO: handle exception
			}

 

 

五、缓冲字符流

高效读写字符文件。

try (BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\test.txt"))){
				bw.write("我欲乘风破浪");
				bw.newLine();//换行
				bw.write("踏遍黄沙海洋");
			} catch (Exception e) {
				// TODO: handle exception
			}
		
			
try(BufferedReader br = new BufferedReader(new FileReader("F:\\test.txt"))) {
			String str;
			while((str=br.readLine())!=null) {//按行读取,拷贝文件最好还是按字符数组读取
				System.out.println(str);
			}
				
			} catch (Exception e) {
				// TODO: handle exception
		
		}
try (
BufferedReader br = new BufferedReader(new FileReader("F:\\test.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\test.txt"));
					){
				bw.write("你就是天选之人");
				bw.close();//当我们使用输入输出流操作同一个文件的时候,写完了以后要先关流。否则流继续占用文件,导致读不出来
				String str = br.readLine();
				System.out.println(str);
			} catch (Exception e) {
				// TODO: handle exception
			}

 

 

六、对象流和序列化

字节流、字符流、对象流、properties文件_第2张图片

1.对象实现序列化,实现序列化接口即可(Serializable)

try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\person1.ddl"))
					){//其实这里写什么文件名后缀都可以
			Person person1 = new Person("sponge", 10);
			
			
			oos.writeObject(person1);
			oos.flush();
				
			} catch (Exception e) {//如果person类没被序列化	java.io.NotSerializableException
				// TODO: handle exception
				e.printStackTrace();
			}
			
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\person1.ddl"))){
			Object o1 = ois.readObject();
			if(o1 instanceof Person) {
				Person o = (Person) o1;
				System.out.println(o.getName()+" "+o.getAge());
			}
			
			}catch(Exception e) {
				e.printStackTrace();
			}

2.浅谈序列化ID(serialVersionUID)

关于序列化和反序列化,上面都有简单的案例实现了。可是试想一下,如果我在用对象流写出了person类的实例p1到磁盘之后,修改了模板类Person,新增了一个字段,或者改了一个方法。那么p1还能反序列化回对象吗?

不行,它会抛java.io.InvalidClassException异常。

如果不想这样的结果,可以有如下的解决方案:

①.重写一次,再读。

②.在模板类上生成序列化ID。

网上大佬是这么说的,这个序列化ID起着关键的作用,它决定着是否能够成功反序列化!简单来说,java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

也就是说,你如果不实现序列化ID,那么序列化的时候会自动分配给模板类及类对象一个序列化ID,你要是改了模板类,那么这个类的序列化ID就变了,反序列化的时候,自然就不匹配,抛异常了。如果你实现了序列化ID,由于其final,那么不管你怎么改模板类(只要不改序列化ID的值),都是可以成功反序列化的(新增的字段将会赋默认值)。

 

 

七、properties文件

1.如何创建

2.

try {
			//1.创建一个properties对象
			Properties p = new Properties();;
			//2.使用p对象加载properties文件
			p.load(PropertiesTest.class.getClassLoader().getResourceAsStream("config.properties"));
			
			//3.获取单个值
			String  value = p.getProperty("charset");
			System.out.println(value);
			
			//4.遍历
			Set keySet = p.keySet();
			for(Object s:keySet) {
				System.out.println(s+" "+p.getProperty(s.toString()));
			}
			
		} catch (Exception e) {
			// TODO: handle exception
		} 
  

 

 

 

 

 

 

 

你可能感兴趣的:(你模糊的java基础)