Java:IO流之:探究字节流和字符流

前言----

本来不想写前言了,但是写完,发现写得太好了,遇到就好好看一看啊!!!!

注:欢迎转载,转载请注明来处

目录

一. 简单理解什么是流?

二.字节输入流

三.字节输出流

四.流的正确关闭方式

五.字符输入流

六.字符输出流

七.字节流和字符流的比较


 

一. 简单理解什么是流?

我是把流理解成一个导管,这个导管连接了硬盘中的某个文件和程序.

输入流:输入数据到程序(既从文件中读)

输出流; 程序输出数据到文件(既写到文件)

二.字节输入流

正如我们所知, 计算机底层都是0和1, 有很多种编码规则, 其作用就是将各自字符定义成特定的01串.,方便计算机识别.我们如果要从文件中读取字符,可以按字节来进行读取,这边我们用FileInputStream来进行读取,字节流,按字面意思我们就知道要用byte或者byte数组来进行读取.

FileInputStream:

FileInputStream是继承了抽象类InputStream。FileInputStream可以通过

1.int read()             从此输入流中读取一个字节。

2int read(byte[] b )  从此输入流中将最多 b.length 个字节的数据读入一个 byte数组中。

测试文件:

:

demo(请细看代码和注释)

package Test;

import java.io.*;
public class ByteStream {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		ByteStream myTest = new ByteStream();

		myTest.testInputStream();
		

	}
	public void creatFile(File f) {
		
		if(!f.exists()) {//先判断文件存不存在
			
			//不存在的话,判断判断目录存不存在
			if(f.getParentFile().exists()!=true) {
			
				f.getParentFile().mkdirs();//不存在就创建
			}
		    
			//创建该文件
			try {
			
				f.createNewFile();
			}catch(Exception e) {
			e.printStackTrace();
			}
		}
	}

	public void testInputStream() {
		
	
		File f = new File("D:/data.txt");
		creatFile(f);//若不存在可以自动创建
		
		FileInputStream fis =null;// 先创建一个输入流,初始为null
		
		try { //流创建失败时会抛出异常,应该try...catch或者throws
			 fis = new FileInputStream(f);
            
            //创建一个大小等于文件字节大小的byte[]数组
			byte [] myByte = new byte[(int)f.length()];
			
            //从文件中一次读取多个字节
			fis.read(myByte);
            
            //将byte字节转化为对应的字符
			String str =new String(myByte);
			System.out.println(str);
			
		}catch(Exception e) {
			
			e.printStackTrace();
		}finally {
			
			if(fis!=null) {
			   
				try {
				fis.close();//记得关闭流,可能会关闭失败,所以也要捕获或者throws
				}catch(Exception e) {
					e.printStackTrace();
				}
			}
		}

		
		

		
		
		
	}

}

结果:

三.字节输出流

FileOutputStream 继承了抽象类OutputStream, 意为文件输出流,是用于将数据写入File,通过write方法将数据写到文件

1.void write(byte[] b)

将 b.length 个字节从指定 byte 数组写入此文件中。

2.void write(int b)   将指定字节写入此文件。

  • 写入时不设置追写 的话, 会先清空文件再写入

   测试文件:

   

   demo(不要错过注释)

	public void testOutputStream() {
	
		File f = new File("D:data.txt");
		creatFile(f);
		
		try( FileOutputStream fos = new FileOutputStream(f) ){
		    
			//用输出字节流写入文件的时候,如果文件不存在,但是父路径存在,此时会自动创建对应的文件
			//如果对应的父目录不存在的话就会抛出异常
			
			byte [] myByte = { 97,32,98,32,99};
			
			fos.write(myByte);//一次写到文件的字节长度为myByte的长度

			
			/*
			for(int i = 0 ;i <myByte.length; i++) {
			   fos.write(myByte[i] );//一个字节一个字节的写入
			   fos.write("\r\n".getBytes());//换行写入,在Windows写换行符为"\r\n"
			   
			   
			}
			*/
		
			
		}catch(Exception e) {
			
			e.printStackTrace();
		}
	
	}

  测试结果:原先的内容被清空了, 97,98,99对应的字符是abc, 32对应空格符

  • 在原文件的基础上追加写入(   使用FileOutputStream(f, true)  )

   测试文本:

   

  demo:

	//字节输出流,追加写入
	public void testOutputStream() {
	
		File f = new File("D:/data.txt");
		creatFile(f);
		
		
		//追加写入
		try( FileOutputStream fos = new FileOutputStream(f,true) ){
		    
			//用输出字节流写入文件的时候,如果文件不存在,但是父路径存在,此时会自动创建对应的文件
			//如果对应的父目录不存在的话就会抛出异常
			//参数为true代表追加写入
			
			byte [] myByte = { 97,32,98,32,99};
			
			fos.write(myByte);//一次写到文件的字节长度为myByte的长度

			
			/*
			for(int i = 0 ;i <myByte.length; i++) {
			   fos.write(myByte[i] );//一个字节一个字节的写入
			   fos.write("\r\n".getBytes());//换行写入,在Windows写换行符为"\r\n"
			   
			   
			}
			*/
		
			
		}catch(Exception e) {
			
			e.printStackTrace();
		}
		
		
	
	}

 测试结果:在原文件的内容上成功追加写入,而不会覆盖掉

四.流的正确关闭方式

无论是输入流还是输出流,在使用完毕之后都应该进行关闭,否则会占有资源, 如果为关闭的流很多的话,对程序的性能会有影响

1.在try{}内关闭,是不安全的关闭方式

2.在finally内关闭-----安全的写法

3.用try-with-resource自动关闭

在JDK7以前,Java没有自动关闭外部资源的语法特性,直到JDK7中新增了try-with-resource语法,才实现了这一功能.

五.字符输入流

在不同的编码规则下:一个字符可以占多个字节,那么能不能一个字符一个字符地读取到文件呢?当然是可以的,我们用FileReader的read()进行读取字符, 由于是字符流,自然是用char或char数组来存储读取的字符

1.public int read(char[] cbuf)  一次性读取cbuf.length个字符到cbuf中

2.public int read(char c) 一次读取一个字符

测试文件:

demo:

	 public void testFileReader() {
		
		File f = new File("D:/data.txt");
		
		try(FileReader fRe = new FileReader(f)){
			
            //由于一个字符有多个字符,长度设为文件的字节长度,肯定够用
			char [] myChar =new char[(int)f.length()];
			
		   fRe.read(myChar);

			
		   for(char i : myChar) {
			   System.out.print(i);
		   }
			
		}catch(Exception e) {
			
			e.printStackTrace();
		}
		
	 }

测试结果:

六.字符输出流

用FileWriter把字符写到文件中, 用到它的write()方法:

  • demo(不进行追写,覆盖掉原文件)

测试之前:

	 public void testFileWriter() {
		 
		 File f = new File("D:/data.txt");
		 isCreatFile(f);
		 
		 try (FileWriter fWr = new FileWriter(f)){
			 
			 char [] myChar= {'1','2','3','4','5'};
			 String myChar2 = "234324   34343";
			 
			 fWr.write(myChar);
			 fWr.write("\r\n");//写入换行符
			 fWr.write(myChar2);
		
			 
		 }catch(Exception e) {
			 e.printStackTrace();
		 }
	 }

测试结果:

  • demo(      用new FileWriter(f,true)   在原文件的基础上追写,不覆盖掉原文件   )

测试之前:

	 public void testFileWriter() {
		 
		 File f = new File("D:/data.txt");
		 isCreatFile(f);
		 
		 try (FileWriter fWr = new FileWriter(f,true)){
			 
			 char [] myChar= {'1','2','3','4','5'};
			 String myChar2 = "234324   34343";
			 
			 fWr.write(myChar);
			 fWr.write("\r\n");
			 fWr.write(myChar2);
		
			 
		 }catch(Exception e) {
			 e.printStackTrace();
		 }
	 }

测试结果:

七.字节流和字符流的比较

问:字符流和字节流的差别在哪里,为什么它能做到按字符读取

答:

1.字符流的本质还是字节流,文件的底层存储中都是01数字串,不存在字符的,我们打开文件看到的字符都是经过解码后呈现出来的.

2.字符流的本质用到缓冲区,二者的工作示意图如下所示:

大概就是说字符流可以在缓冲区的byte数组里面形成一个byte数组,然后直接传byte数组给程序,而字节流每次只能传一个字节而已

猜你喜欢

转载自blog.csdn.net/CCSGTC/article/details/84189304