相关文章推荐
私奔的硬盘  ·  python 3.x - binary ...·  1 年前    · 
乐观的甘蔗  ·  django - How to use ...·  1 年前    · 
老实的回锅肉  ·  Pandas ...·  1 年前    · 

字节流与字符流

在java.io包中操作文件内容的主要有两大类:字节流和字符流,两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使用InputStream,在字符流中输出主要是使用Writer类完成,输入主要是使用Reader类完成。 内容操作一共四个类:OutputStream、InputStream、Writer、Reader 操作流程: 在JAVA中IO操作也是有相应步骤的,以文件操作为例,主要操作流程如下: A、使用File类打开一个文件 B、通过字节流或字符流的子类,指定输出的位置。 C、进行读/写操作 D、关闭输入/输出 从以上的定义可以发现,此类是一个抽象类,如果要想使用此类的话,则首先必须通过子类实例化对象,那么如果现在要操作的是一个文件,则可以使用:FileOutputStream类。通过向上转型之后,可以为OutputStream实例化。 Closeable表示可以关闭的操作,因为程序运行到最后肯定要关闭。 Flushable接口表示刷新,清空内存中的数据。 OutputStream类的常用方法: 1、 public void close() throws IOException 关闭输出流 2、 public void flush() throws IOException 刷新缓冲区 3、 public void write(byte[] b) throws IOException 将一个byte数组写入数据流 4、 public void write(byte[] b,int off,int len) throws IOException 将一个指定范围的byte数组写入数据流 5、 public abstract void write(int b) throws IOException 将一个字节数据写入数据流 要想使用以上方法,必须使用子类实例化,此时使用FileOutputStream子类,此类的构造方法如下: public FileOutputStream(File file) throws IOException
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo01{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		OutputStream out = null ;	// 准备好一个输出的对象
		out = new FileOutputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行写操作
		String str = "Hello World!!!" ;		// 准备一个字符串
		byte b[] = str.getBytes() ;			// 只能输出byte数组,所以将字符串变为byte数组
		out.write(b) ;						// 将内容输出,保存文件
		// 第4步、关闭输出流
		out.close() ;						// 关闭输出流
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo02{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		OutputStream out = null ;	// 准备好一个输出的对象
		out = new FileOutputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行写操作
		String str = "Hello World!!!" ;		// 准备一个字符串
		byte b[] = str.getBytes() ;			// 只能输出byte数组,所以将字符串变为byte数组
		for(int i=0;i<b.length;i++){		// 采用循环方式写入
			out.write(b[i]) ;	// 每次只写入一个内容
		// 第4步、关闭输出流
		out.close() ;						// 关闭输出流
 以上的操作中在写入数据之前,文件之前的内容已经不存在了,因为在IO操作中默认的情况是将其进行覆盖的,那么现在要想执行追加的功能,则必须设置追加的操作,找到FileOutputStream类: 
 追加新内容 
 之前的所有操作中,如果重新执行程序,则肯定会覆盖文件中的已有内容,那么此时就可以通过FileOutputStream向文件中追加内容,FileOutputStream的另外一个构造方法: 
 public FileOutputStream(File file,boolean append) throws FileNotFoundException 
 在构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容。 
 程序代码如下: 
 
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo03{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		OutputStream out = null ;	// 准备好一个输出的对象
		out = new FileOutputStream(f,true)  ;	// 此处表示在文件末尾追加内容
		// 第3步、进行写操作
		String str = "Hello World!!!" ;		// 准备一个字符串
		byte b[] = str.getBytes() ;			// 只能输出byte数组,所以将字符串变为byte数组
		for(int i=0;i<b.length;i++){		// 采用循环方式写入
			out.write(b[i]) ;	// 每次只写入一个内容
		// 第4步、关闭输出流
		out.close() ;						// 关闭输出流
};
执行完毕后打开文件test.txt如下:
程序本身是可以追加内容的,但是没有换行,是直接在末尾追加的。
如果在文件操作中想换行的话,使用"\r\n" 完成。 代码如下:
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo04{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		OutputStream out = null ;	// 准备好一个输出的对象
		out = new FileOutputStream(f,true)  ;	// 此处表示在文件末尾追加内容
		// 第3步、进行写操作
		String str = "\r\nHello World!!!" ;		// 准备一个字符串
		byte b[] = str.getBytes() ;			// 只能输出byte数组,所以将字符串变为byte数组
		for(int i=0;i<b.length;i++){		// 采用循环方式写入
			out.write(b[i]) ;	// 每次只写入一个内容
		// 第4步、关闭输出流
		out.close() ;						// 关闭输出流
 

字节输入流:InputStream

 既然程序可以向文件中写入内容,则就可以通过InputStream从文件中读取出来,首先看InputStream类的定义: public abstract class InputStream extends Object implements Closeable 与OutputStream类一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,子类肯定是FileInputStream。观察FileInputStream类的构造方法: public FileInputStream(File file) throws FileNotFoundException InputStream类的常用方法如下: 1、public int available() throws IOException  可以取得输入文件的大小。 2、public void close() throws IOException  关闭输入流 3、public abstract int read() throws IOException 读取内容数字的方式读取 4、public int read(byte[] b) throws IOException 将内容读取到byte数组之中,同时返回读入的个数 程序代码如下:
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo01{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		InputStream input = null ;	// 准备好一个输入的对象
		input = new FileInputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行读操作
		byte b[] = new byte[1024] ;		// 所有的内容都读到此数组之中
		input.read(b) ;		// 读取内容
		// 第4步、关闭输出流
		input.close() ;						// 关闭输出流
		System.out.println("内容为:" + new String(b)) ;	// 把byte数组变为字符串输出
  
此时,内容确实已经被读取出来了,但是存在问题。 初步修改代码后如下:
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo02{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		InputStream input = null ;	// 准备好一个输入的对象
		input = new FileInputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行读操作
		byte b[] = new byte[1024] ;		// 所有的内容都读到此数组之中
		int len = input.read(b) ;		// 读取内容
		// 第4步、关闭输出流
		input.close() ;						// 关闭输出流\
		System.out.println("读入数据的长度:" + len) ;
		System.out.println("内容为:" + new String(b,0,len)) ;	// 把byte数组变为字符串输出
  
以上代码还是存在问题,现在文件没有那么大,但是开辟了很大的数组空间,肯定浪费很多内存,应该根据文件的大小来开辟数组空间。如果想知道文件的大小,直接使用File类即可: public long length() 开辟指定大小的空间
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo03{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		InputStream input = null ;	// 准备好一个输入的对象
		input = new FileInputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行读操作
		byte b[] = new byte[(int)f.length()] ;		// 数组大小由文件决定
		int len = input.read(b) ;		// 读取内容
		// 第4步、关闭输出流
		input.close() ;						// 关闭输出流\
		System.out.println("读入数据的长度:" + len) ;
		System.out.println("内容为:" + new String(b)) ;	// 把byte数组变为字符串输出
 
以上是直接使用byte数组的方式完成的,还可以使用以下方式进行读取 public abstract int read() throws IOException逐个字节进行内容读取 代码如下:
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo04{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		InputStream input = null ;	// 准备好一个输入的对象
		input = new FileInputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行读操作
		byte b[] = new byte[(int)f.length()] ;		// 数组大小由文件决定
		for(int i=0;i<b.length;i++){
			b[i] = (byte)input.read() ;		// 读取内容
		// 第4步、关闭输出流
		input.close() ;						// 关闭输出流\
		System.out.println("内容为:" + new String(b)) ;	// 把byte数组变为字符串输出
 
以上的操作,只适合于知道输入流大小的时候,如果现在不知道大小呢? 需要根据读取的标志-1进行判断是否结束,代码如下:
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo05{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		InputStream input = null ;	// 准备好一个输入的对象
		input = new FileInputStream(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行读操作
		byte b[] = new byte[1024] ;		// 数组大小由文件决定
		int len = 0 ; 
		int temp = 0 ;			// 接收每一个读取进来的数据
		while((temp=input.read())!=-1){
			// 表示还有内容,文件没有读完
			b[len] = (byte)temp ;
			len++ ;
		// 第4步、关闭输出流
		input.close() ;						// 关闭输出流\
		System.out.println("内容为:" + new String(b,0,len)) ;	// 把byte数组变为字符串输出
};
当不知道读取的内容有多大的时候,就只能以读取的数据是否为-1为读完的标志。 在程序中一个字符等于2个字节,那么JAVA提供了Reader、Writer两个专门操作字符流的类。

字符输出流:Writer

Writer本身是一个字符流的输出类,此类的定义如下: public abstract class Writer extends Object implements Appendable,Closeable,,Flushable 此类也是一个抽象类,如果要想使用此类,则肯定要使用其子类。此时如果是向文件中写入内容,所以应该使用FileWriter的子类。 FileWriter类的构造方法定义如下: public FileWriter(File file) throws IOException Writer类的常用方法 1、public abstract void close() throws IOException  关闭输出流 2、public void write(String str) throws IOException 将字符串输出 3、public void write(char[] cbuf) throws IOException 将字符数组输出 4、public abstract void flush() throws IOException 强制性清空缓存 字符流的操作比字节流操作好在一点,就是可以直接输出字符串。不在用再像之前那样进行字节转换操作了。
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo01{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		Writer out = null ;	// 准备好一个输出的对象
		out = new FileWriter(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行写操作
		String str = "Hello World!!!" ;		// 准备一个字符串
		out.write(str) ;						// 将内容输出,保存文件
		// 第4步、关闭输出流
		out.close() ;						// 关闭输出流
};
使用字符流默认情况下依然是覆盖已有的文件,如果想追加的话,则直接在FileWriter上增加一个可追加的标记即可。
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo02{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		Writer out = null ;	// 准备好一个输出的对象
		out = new FileWriter(f,true)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行写操作
		String str = "\r\n刘勋\r\nHello World!!!" ;		// 准备一个字符串
		out.write(str) ;						// 将内容输出,保存文件
		// 第4步、关闭输出流
		out.close() ;						// 关闭输出流
  

字符输入流:Reader

Reader是使用字符的方式从文件之中取出数据,Reader类的定义如下: public abstract class Reader extends Object implements Readable,Closeable Reader本身也是抽象类,如果现在要从文件中读取内容,则可以直接使用FileReader子类。 FileReader的构造方法定义如下: public FileReader(File file) throws FileNotFOundException Reader类的常用方法: 1、public abstract void close() throws IOException 关闭输出流 2、public int read() throws IOException 读取单个字符 3、public int read(char[] cbuf) throws IOException 将字符读取到字符数组之中,返回读入的长度。 import java.io.FileReader ; public class ReaderDemo01{ public static void main(String args[]) throws Exception{ // 异常抛出,不处理 // 第1步、使用File类找到一个文件 File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象 // 第2步、通过子类实例化父类对象 Reader input = null ; // 准备好一个输入的对象 input = new FileReader(f) ; // 通过对象多态性,进行实例化 // 第3步、进行读操作 char c[] = new char[1024] ; // 所有的内容都读到此数组之中 int len = input.read(c) ; // 读取内容 // 第4步、关闭输出流 input.close() ; // 关闭输出流 System.out.println("内容为:" + new String(c,0,len)) ; // 把字符数组变为字符串输出 };
也可以通过循环的方式,通过判断文件是否读取到底的形式读取《如下所示:
import java.io.File ;
import java.io.Reader ;
import java.io.FileReader ;
public class ReaderDemo02{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		Reader input = null ;	// 准备好一个输入的对象
		input = new FileReader(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行读操作
		char c[] = new char[1024] ;		// 所有的内容都读到此数组之中
		int temp = 0 ;	// 接收每一个内容
		int len = 0 ;		// 读取内容
		while((temp=input.read())!=-1){
			// 如果不是-1就表示还有内容,可以继续读取
			c[len] = (char)temp ;
			len++ ;
		// 第4步、关闭输出流
		input.close() ;						// 关闭输出流
		System.out.println("内容为:" + new String(c,0,len)) ;	// 把字符数组变为字符串输出
  

字节流与字符流的区别

字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的。 import java.io.OutputStream ; import java.io.FileOutputStream ; public class OutputStreamDemo05{ public static void main(String args[]) throws Exception{ // 异常抛出,不处理 // 第1步、使用File类找到一个文件 File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象 // 第2步、通过子类实例化父类对象 OutputStream out = null ; // 准备好一个输出的对象 out = new FileOutputStream(f) ; // 实例化 // 第3步、进行写操作 String str = "Hello World!!!" ; // 准备一个字符串 byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组 out.write(b) ; // 写入数据 // 第4步、关闭输出流 // out.close() ; // 关闭输出流
在使用字节流操作中,即使没有关闭,最终也是可以输出的 使用字符流,如果不关闭,如下:
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo03{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		Writer out = null ;	// 准备好一个输出的对象
		out = new FileWriter(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行写操作
		String str = "Hello World!!!" ;		// 准备一个字符串
		out.write(str) ;						// 将内容输出,保存文件
		// 第4步、关闭输出流
		// out.close() ;						// 此时,没有关闭
import java.io.FileWriter ;
public class WriterDemo04{
	public static void main(String args[]) throws Exception{	// 异常抛出,不处理
		// 第1步、使用File类找到一个文件
		File f= new File("d:" + File.separator + "test.txt") ;	// 声明File对象
		// 第2步、通过子类实例化父类对象
		Writer out = null ;	// 准备好一个输出的对象
		out = new FileWriter(f)  ;	// 通过对象多态性,进行实例化
		// 第3步、进行写操作
		String str = "Hello World!!!" ;		// 准备一个字符串
		out.write(str) ;						// 将内容输出,保存文件
		// 第4步、关闭输出流
		out.flush() ;	// 强制性清空缓冲区中的内容
		// out.close() ;						// 此时,没有关闭
  开发中是使用字节流好还是使用字符流好 
  在所有的硬盘上保存文件或是进行传输的时候都是以字节的方式进行的,包括图片也是按照字节完成,而字符是只有在内存中才会形成的,所以使用字节操作是最多的。 
 文件拷贝:在DOS命令中存在一个文件的拷贝命令(copy),例如:现在要将D盘中的test.txt文件拷贝到D盘中的demo.txt文件中,则只要在命令行输入copy即可完成 
 copy命令的语法格式如下: 
 copy 源文件 目标文件 
 如果要采用以上的格式,则肯定要使用初始化参数的形式,输入两个路径,所以此时就必须对输入参数的个数进行验证,判断其是否为2 
 是使用字符流还是使用字节流呢?答案是肯定选择字节流,因为万一拷贝的是一个图片。 
   实现一:将源文件中的内容全部读取进来,之后一次性的写入到目标文件 
   实现二:边度边写的方式 
 很明显是使用第二种方式 
 程序代码如下: 
 
import java.io.* ;
public class Copy{
	public static void main(String args[]){
		if(args.length!=2){		// 判断是否是两个参数
			System.out.println("输入的参数不正确。") ;
			System.out.println("例:java Copy 源文件路径 目标文件路径") ;
			System.exit(1) ;	// 系统退出
		File f1 = new File(args[0]) ;	// 源文件的File对象
		File f2 = new File(args[1]) ;	// 目标文件的File对象
		if(!f1.exists()){
			System.out.println("源文件不存在!") ;
			System.exit(1) ;
		InputStream input = null ;		// 准备好输入流对象,读取源文件
		OutputStream out = null ;		// 准备好输出流对象,写入目标文件
			input = new FileInputStream(f1) ;
		}catch(FileNotFoundException e){
			e.printStackTrace() ;
			out = new FileOutputStream(f2) ;
		}catch(FileNotFoundException e){
			e.printStackTrace() ;
		if(input!=null && out!=null){	// 判断输入或输出是否准备好
			int temp = 0 ;	
				while((temp=input.read())!=-1){	// 开始拷贝
					out.write(temp) ;	// 边读边写
				System.out.println("拷贝完成!") ;
			}catch(IOException e){
				e.printStackTrace() ;
				System.out.println("拷贝失败!") ;
				input.close() ;		// 关闭
				out.close() ;		// 关闭
			}catch(IOException e){
				e.printStackTrace() ;
  1、掌握流的概念 
  2、掌握字节流和字符流操作文件的基本步骤(以后所有操作都可以使用以上代码完成) 
  3、字节流和字符流的区别 
      字节流:没有使用到缓冲区 
      字符流:使用到了缓冲区 
  4、边度边写的方式是开发中非常有用的方式 
1. 判断使用输入流还是输出流的依据
以当前程序(也就是内存)为参照物,从硬盘向内存中读取数据,使用输入流 FileInputStream。从内存向硬盘写出数据,使用输出流 FileOutputStream。
2. FileInputStream 读取文件
 使用FIleInputStream读取文件时,我们通常维护一个缓冲数组来提高读取效率。假如我们维护的这个缓冲字...
                                    字节的数据是以byte类型为主实现的操作,在进行字节内容输出的时候可以使用OutputStream类完成,类的基本定义:
public abstract class OutputStream extends Object implements Closeable,Flushable
首先可以发现这个类实现了两个接口,于是基本定对应关系如下:
Closeable
			Flushable
ByteArrayOutputStream和ByteArrayInputStream详解 
ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,然后利用ByteArrayOutputStream和ByteArray...
                                    1. ByteArrayOutputStream使用说明
字节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中。创建字节数组输出流对象有以下几种方式。
下面的构造方法创建一个32字节(默认大小)的缓冲区。
OutputStream bOut = new ByteArrayOutputStream();
另一个构造方法创建一个大小为n字节的缓冲区。
Outp...
                                    一、ByteArrayInputStreamInputStream的一个子类,它可以把一个字节数组在内存中变成一个输入流(或者说,它把数组进行了包装,数组具有了流的属性,可以顺序读下去)。
ByteArrayInputStream的主要特征:从字节数组中读取数据
ByteArrayInputStream类的构造方法:
ByteArrayInputStream(byte[] buf)//通过一个字节数组buf创建一个字节输入流对象
ByteArrayInputStream(byte[] buf,int of
                                    什么是IO流?byte序列的读写,Java中的IO流是实现输入/输出的基础.1)InputStream : 抽象类读取数据的过程 包含读取方法read();in 模仿了读取小说的过程简单说 : in是读取文件的OutputStream:抽象了写出数据的过程 
包含写出方法write();out模仿了写笔记记录的过程简单说 : out是写入文件的基本的b...