黑马程序员--Java学习18--IO流

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

IO流用来处理设备间的数据传输;Java对数据的操作是通过流的方式完成的;Java用来操作流的对象都存在IO包中;流按操作数据分为两种:字节流和字符流;流按流向分为输入流和输出流。关于字符流和字节流:在操作文本数据时,当我们读写字符的时候,使用字符流更为方便,他可以替我们自动解码编码。字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组、字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是有Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频、视屏、歌曲,就用字节流好点,如果是关系到中文(文本),用字符流好。

下面我分别介绍操作字符流和字节流的对象。

一、字符流的操作

1、1 Reader 和 Writer

字符流的抽象基类:Reader 和 Writer

Writer是操作字符输出流的类,其中的方法为

Reader是操作字符输入流的,其中的方法为:

FileWriter和FileReader是用来写入字符文件的便捷类。我以FileWriter和FileReader为例来演示字符流对文件的操作。

首先介绍FileWriter的创建以及其中方法的演示:

import java.io.*;
class FileWriterDemo4 {
	public static void main(String[] args) throws IOException {

		//创建一个FileWriter对象,该对象一被初始化就必须明确被操作的文件。
		//而且该文件会被创建到指定目录下,如果该目录已有同名文件,将被覆盖。
		//其实改步就是在明确数据要存放的目的地。
		FileWriter fw = new FileWriter("demo.txt");
		
		//调用Writer方法,将字符串写入到流中。
		fw.write("abcjd");

		//刷新流对象中的缓冲中的数据,
		//将数据刷新到目的地。
		fw.flush();

		//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
		//将数据刷到目的地中。
		//和flush区别,flush刷新后,流可以继续使用,close刷新后,会将流关闭。
		fw.close();
		fw.write("hahha");//close后出现此步,编译错误

	}
}

查阅API文档可知,操作IO包中的对象时会产生IOException,对于IO异常的处理如下:

import java.io.*;
class FileWriterDemo5 {
	public static void main(String[] args) {
		
		FileWriter fw=null;//保证fw在整个程序内都有效
		try {
			fw=new FileWriter("Demo.txt");

			fw.write("abcd");
		}
		catch (IOException e) {
			System.out.println(e.toString());
		}
		finally {
			try {
				if(fw!=null)//预防空指针异常
					fw.close();
			}
			catch (IOException e) {
				System.out.println(e.toString()); 
			}
		}
	}
}


 演示对已有文件的数据续写。

import java.io.*;
class FileWriterDemo6 {
	public static void main(String[] args) {

		//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据续写。
		FileWriter fw=null;//保证fw在整个程序内都有效
		try {
			fw=new FileWriter("Demo.txt",true);

			fw.write("abcd");
		}
		catch (IOException e) {
			System.out.println(e.toString());
		}
		finally {
			try {
				if(fw!=null)//预防空指针异常
					fw.close();
			}
			catch (IOException e) {
				System.out.println(e.toString); 
			}
		}
	}
}

文件的读取:第一种方式

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

		//创建一个文件读取流对象,和指定名称的文件相关联,
		//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException。
		FileReader fr= new FileReader("Demo.txt");

		//调用读取流对象的read方法、
		//read():一次读一个字符,而且会自动往下读。如果已达到流的末尾,则返回-1.
		/*
		int ch=fr.read();
		System.out.println("ch="+(char)ch);
		*/

		int ch=0;
		while ((ch=fr.read())!=-1) {
			System.out.println((char)ch);
		}
		fr.close();
	}
}


文件的读取:第二种方式

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

		FileReader fr=new FileReader("demo.txt");


		//定义一个字符数组,用于存储读到字符。
		//该read(char[]):返回的是读到字符个数。

		char[] buf=new char[];

		int num=0;

		while ((num=fr.read(buf))!=-1) {
			System.out.print("num"+num+"..."+new String(buf,0,num));//这地方不应该别换行,
		}
		fr.close();
	}
}

将C盘一个文件复制到D盘。

/*
步骤:
1、在D盘创建一个文件,用于存储C盘文件中的 数据。
2、定义读取流和C盘文件关联。
3、通过不断的读写完成数据存储。
4、关闭资源。
*/
import java.io.*;
class CopyText9 {
	public static void main(String[] args) throws IOException  {
		//copy_1();
		copy_2();
	}

	//从C盘读取一个字符,就往D盘写
	public static void copy_1() throws IOException {
		FileReader fr=new FileReader("C:\\哈哈\\test.txt");
		FileWriter fw=new FileWriter("E:\\test.txt");
		//char[] ch=new char[1024];
		
		int num=0;
		while ((num=fr.read())!=-1) {
			fw.write((char)num);
		}
		fw.close();
		fr.close();
	}
	//从C盘读取一个字符数组,就往D盘写
	public static void copy_2() {
		

		FileReader fr=null;
		FileWriter fw=null;
		try {
			fr=new FileReader("C:\\哈哈\\test.txt");
			fw=new FileWriter("E:\\test.txt");
			char[] ch=new char[1024];
		
			int num=0;
			while ((num=fr.read(ch))!=-1) {
				fw.write(ch,0,num);
			}
		}
		catch (IOException e) {
		}
		finally {
		
			try {
				if(fr!=null)
					fr.close();
				
			}
			catch (IOException e) {

			}
			finally {
				try {
					if(fw!=null)
						fw.close();
				}
				catch (IOException e) {
				}
			}
		}
		
	}
}


1.、2 BufferedReader和BufferedWriter

        缓冲区的出现时为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要先有流对象。

       BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。含有的方法为:


其中的newLine是一个跨平台的换行符。

import java.io.*;
class BufferedWriterDemo1 {
	public static void main(String[] args) throws IOException{
		
		//创建一个字符写入流对象。
		FileWriter fw=new FileWriter("buf.txt");

		//为了提高字符写入流效率,加入了缓冲技术。
		//只要将需要被提高效率的流对象作为参数传递给缓冲的构造函数即可。
		BufferedWriter bufw=new BufferedWriter(fw);
		
		for (int x=1;x<6 ;x++ ) {
			bufw.write("abcde:"+x);
			bufw.newLine();
			bufw.flush();
		}
		

		//记住,只要用到缓冲区,就要记得刷新。
		//bufw.flush();

		//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
		bufw.close();

	}
}

BufferedReader: 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。其中的方法有:


该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。当返回null,表示读到文件的末尾。

readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。

readLine方法的原理:无论是读一行,获取读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是read方法一 次读一个的方法。

import java.io.*;
class BufferedReaderDemo2 {
	public static void main(String[] args) throws IOException {
		
		//创建一个读取流对象和文件相关联
		FileReader fr=new FileReader("buf.txt");

		//为了提高效率,加入缓冲技术,将字符流读取对象作为参数传递给缓冲对象的构造函数。
		BufferedReader bufr=new BufferedReader(fr);
		
		/*
		String s1=bufr.readLine();
		System.out.println(s1);
		String s2=bufr.readLine();
		System.out.println(s2);
		*/

		String line=null;
		while ((line=bufr.readLine())!=null) {
			System.out.println(line);
		}
		bufr.close();
	}
}

我们再看一个例子:通过缓冲区读取一个.java 文件。

import java.io.*;
class CopyTextByBuf3 {
	public static void main(String[] args) throws IOException {
		
		/*
		FileReader fr=new FileReader("buf.txt");
		BufferedReader bufr=new BufferedReader(fr);
		FileWriter fw=new FileWriter("E:\\buf.txt");
		BufferedWriter bufw=new BufferedWriter(fw);
		*/
		BufferedReader bufr=null;
		BufferedWriter bufw=null;

		try {
			bufr=new BufferedReader(new FileReader("buf.txt"));
			bufw=new BufferedWriter(new FileWriter("E:\\buf.txt"));
			String line=null;
			while ((line=bufr.readLine())!=null) {
				bufw.write(line,0,line.length());
				bufw.newLine();
				bufw.flush();
			}
		}
		catch (IOException e) {
			throw new RuntimeException("读写失败");
		}
		finally {
			try {
				bufw.close();
				bufr.close();
			}
			catch (IOException e) {
				throw new RuntimeException("关闭异常");
			}
		}		
	}
}


二、字节流的操作

字节流的抽象基类:InputStream 和 OutputStream

操作字节流的方法和字符流的相类似,我就不再一一列举了,我做了这样一个对照:

例:复制一个图片

/*
思路:
1、用字节读取流对象和图像关联。
2、用字节写入流对象创建一个图片文件,用于存储获取到的图片数据。
3、通过循环读写,完成数据的存储。
4、关闭资源。
*/
import java.io.*;
class CopyPic5 {
	public static void main(String[] args) {
		
		FileOutputStream fos=null;
		FileInputStream fis=null;
		try {
			fos=new FileOutputStream("E:\\keySet方法图示11.png");
			fis=new FileInputStream("E:\\keySet方法图示.png");

			byte[] by=new byte[1024];

			int num=0;
			while ((num=fis.read(by))!=-1) {
				fos.write(by,0,by.length);
			}
		}
		catch (IOException e) {
			throw new RuntimeException("图片读取错误");
		}
		finally {
			try {
				if (fis!=null)
					fis.close();
			}
			catch (IOException e) {
				throw new RuntimeException("读取关闭失败");
			}
			try {
				
				fos.close();
			}
			catch (IOException e) {
				throw new RuntimeException("写入关闭失败");
			}
		}
		
	}
}

例:演示flv的复制

import java.io.*;
class CopyMp6 {
	public static void main(String[] args)throws IOException {
		copy_1();
	}
	public static void copy_1() throws IOException {
		BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("E:\\如何组装计算机.flv"));
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream("E:\\硕鼠视屏\\如何组装计算机.flv"));

		byte[] by=new byte[1024];
		int num=0;
		while ((num=bis.read(by))!=-1) {
			bos.write(by);
		}
		bos.close();
		bis.close();
	}
}

 三、File类

        File类的对象主要用来获取文件本身的一些信息,例如文件所在的目录、文件的长度、文件读写权限等,不涉及对文件的读写操作。

 创建一个File对象的构造方法有3个:
        File (String  filename);
        File (String directoryPath, String  filename);
        File (File f,  String  filename);
        其中,filename是文件名字,directoryPath是文件的路径.f是指定成一个目录的文件。
        使用File(String filename)创建文件时,该文件被认为是与当前应用程序在同一目录中。

         1.文件的属性
        经常使用File类的下列方法获取文件本身的一些信息:
        ◆  public String getName()获取文件的名字。
        ◆  public boolean canRead()判断文件是否是可读的。
        ◆  public boolean canWrite()判断文件是否可被写入。
        ◆  public boolean exits()  判断文件是否存在。
        ◆  public long length()获取文件的长度(单位是字节)。
        ◆  public String getAbsolutePath()获取文件的绝对路径。
        ◆  public String getParcnt()获取文件的父目录。
        ◆  public boolean isFile()判断文件是否是一个正常文件,而不是目录。
        ◆  public boolean isDirectory()判断文件是否是一个目录。
        ◆  public boolean isHidden()  判断文件是否是隐藏文件。
        ◆  public long lastModified()获取文件最后修改的时间(时间是从1970年午夜至文件最后修改时刻的毫秒数)。

2.目录
       (1)创建目录
       File对象调用方法public boolean mkdir0创建一个目录,如果创建成功返回true,否则返回false(如果该目录已经存在,将返回false)o
       (2)列出目录中的文件
       如果File对象是一个目录,那么该对象可以调用下述方法列出该目录下的文件和子目录:
       ◆  public String口list0用字符串形式返回目录下的全部文件。
       ◆  public File[] listFiles()用File对象形式返回目录下的全部文件。
       有时需要列出目录下指定类型的文件,比如.java、.txt等扩展名的文件。可以使用File类的下述两个方法,列出指定类型的文件:
       ◆  public Stringo list(FilenameFilter obj)  该方法用字符串形式返回目录下的指定类型的所有文件。
       ◆  public File[] listFiles(FilenamcFilter obj)该方法用File对象返回目录下的指定类型所有文件。
       FilenameFilter是一个接口,该接口有一个方法:
       public boolean accept<File  dir, String name):
       使用list方法时,需向该方法传递一个实现FilenameFilter接口的对象。list方法执行时,参数不断回调接口方法accept(File dir,String name),accept中的参数name被实例化目录中的一个文件名,参数dir为调用list的当前目录对象,当接口方法返回true时,list方法就将目录dir中的文件存放到返回的数组中。
’     3.文件的创建与删除
       当使用File类创建一个文件对象后,例如:
       File f = new File("C:\\myletter", "Ietter. txt"),
       如果C:\myletter目录中没有名字为letter.txt丈件,文件对象f调用方法:
       public boolean  createNewFile()
       可以在C:\myletter目录中建立一个名字为letter.txt的文件。
       文件对象调用方法:
       public boolean delete()
       可以删除当前文件,例如:
       f .delete();

import java.io.*;

class FileDemo1 {
	public static void main(String[] args) {

		consMethod();
		//System.out.println("Hello World!");
	}

	//创建File对象
	public static void consMethod() {
		
		//将a.txt封装成对象。可以将已有的和未出现的文件或文件夹封装成对象
		File f1 = new File("c:\\abc\\a.txt");

		//
		File f2 =new File("c:\\abc","b.txt");

		//
		File d=new File("c:\\abc");
		File f3=new File(d,"c.txt");

		sop("f1:"+f1);
		sop("f2:"+f2);
		sop("f3:"+f3);

		//目录分隔符,用于跨平台
		sop(File.separator);
	}

	public static void sop(Object obj) {
		System.out.println(obj);
	}
}

例:删除有内容的目录文件

import java.io.*;
class RemoveDir4 {
	public static void main(String[] args) {
		
		File f=new File("G:\\picture1");
		deleteDemo(f);
		
		
		
		//System.out.println("Hello World!");
	}
	public static void deleteDemo(File f) {
		File[] files=f.listFiles();
		for (int x=0;x<files.length;x++) {
			if (!(files[x].isHidden())&&files[x].isDirectory()) {
				deleteDemo(files[x]);
			System.out.println("delete::"+files[x]+"::is::"+files[x].delete());
			}
		}
		System.out.println("delete::"+f+"::is::"+f.delete());
		
		
	}
}

 例:练习:
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。建立一个java文件列表。

/*
思路:
1、对指定的目录进行递归
2、获取递归过程所有的java文件的路径。
3、将这些路径存到集合中
4、将集合中的数据写入到一个文件中。


实用价值:可以将列出文件清单,便于查阅
*/
import java.io.*;
import java.util.*;
class FileDemo5 {
	public static void main(String[] args) {
		
		File dir=new File("G:\\Thedayoflearnjava");

		List<File> list=new ArrayList<File>();

		filesToList(dir,list);
		System.out.println(list.size());

		writeToFile(list,"e:\\haha.txt");
		
		//System.out.println("Hello World!");
	}
	public static void filesToList(File dir,List<File> list) {
		File[] files=dir.listFiles();
		for(File file:files) {
			if (file.isDirectory()) {
				filesToList(file,list);
			}
			else 
				if (file.getName().endsWith(".java")) {
					list.add(file);
				}
		}
	}
	public static void writeToFile(List<File> list,String javaListFile) {
		BufferedWriter bufw=null;
		try {
			bufw=new BufferedWriter(new FileWriter(javaListFile));
			for(File f:list) {
				String path=f.getAbsolutePath();
				bufw.write(path);
				bufw.newLine();
				bufw.flush();
			}

		}
		catch (Exception e) {
			throw new RuntimeException();
		}
		finally {
			try {
				if (bufw!=null) {
					bufw.close();
				}
			}
			catch (Exception e) {
				throw new RuntimeException("关闭异常");
			}
		}
	}
}


---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值