黑马程序员_IO

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------

IO

IO(Input  Output)

IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的对象都在IO包中

流按操作数据分为两种:字节流与字符流。

流按流向分为:输入流,输出流。

 

IO流常用基类

字节流的抽象基类

InputStream OutputStream

字符流的抽象基类

Reader Writer

注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

如:InputStream的子类FileInputStream

如:Reader的子类FileReader

 

IO程序的书写

导入IO包中的类

进行IO异常处理

finally中对流进行关闭

 

字符流——创建文件

创建流对象,建立数据存放文件

FileWriter fw = new FileWriter(“Test.txt”);

调用流对象的写入方法,将数据写入流

fw.write(“text”);

关闭流资源,并将流中的数据清空到文件中

fw.close();

 

字符流——读取文件

建立一个流对象,和指定的文件数据关联。

FileReader fr = new FileReader(“Test.txt”);

创建一个临时存放数据的数组。

char[] ch = new char[1024];

调用流对象的读取方法将流中的数据读入到数组中。

fr.read(ch);

 

注意:

定义文件路径时,可以用“/”或者“\\”。

在创建一个文件时,如果目录下有同名文件将被覆盖。

在读取文件时,必须保证该文件已存在,否则出异常。

 

字符流的缓冲区

缓冲区的出现提高了对数据的读写效率。

对应类

BufferedWriter

BufferedReader

缓冲区要结合流才可以使用。

在流的基础上对流的功能进行了增强。

代码演示1:

/*
字符流的特点:
既然IO流是用于操作数据的
那么数据的最常见体现形式是文件

需求:在硬盘上创建一个文件,并写入一些数据
找到一个专门用于操作文件的Writer子类对象FileWriter 
*/
package FileWriterDemo;

import java.io.*;

class FileWriterDemo 
{
	public static void main(String[] args) 
	{
		FileWriter fw = null;
		try
		{
			
			/*创建一个FileWriter对象,该对象一初始化就必须要有被操作的文件
			而且该文件会被创建到指定目录下,如果该目录下已有同名文件,该文件会被覆盖
			其实该步就是在明确数据存放的目的地*/
			fw = new FileWriter("Demo.txt",true);
			
			//调用字符串,将字符串写入到流中
			fw.write("\r\nnihao\r\nxiexie");

			//刷新流对象中的缓冲数据,将数据刷到目的地中
			fw.flush();
			
		}
		catch (IOException e)
		{
			System.out.println("catch:"+e.toString());
		}
		finally
		{
			try
			{
				if(fw!=null)
					//关闭流资源,但是在关闭之前会刷新一次内部缓冲的数据
					fw.close();
			}
			catch (IOException e)
			{

			}
			
		}
		
	} 	
}

/*
演示对已有文件的续写

	//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据续写
	FileWriter fw = new FileWrier("demo.txt",true);
*/


代码演示2:

package FileReaderDemo;

import java.io.*;

class FileReaderDemo 
{
	public static void main(String[] args) 
	{
		method_1();
		//method_2();
	}
	 
	public static void method_1()
	{
		FileReader fr = null;
		try
		{
			//创建一个读取流对象,和指定的文件相关联
			//要保证该文件是一件存在的,如果该文件不存在,会出现FileNotFoundException
			fr = new FileReader("Demo.txt");
			
			int ch = 0;
			
			//调用读取流对象的read方法
			//read()一次读取一个字符,自动往下读
			while((ch=fr.read())!=-1)
			{
				System.out.print("Ch="+(char)ch+" ");
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("读取失败");
		}
		finally
		{
			try
			{
				if(fr!=null)
					//关闭流
					fr.close();
			}
			catch (IOException e)
			{
			}
		}
		
		
	}

	//通过字符数组进行读取
	public static void method_2()
	{	
		FileReader fr = null;
		try
		{
			fr = new FileReader("Demo.txt");

			//定义一个字符数组,用于存储读到的字符
			//该read(buf)返回的是读到的字符数
			char[] buf = new char[1024];

			int len = 0;
			while((len = fr.read(buf))!=-1)
			{
				//打印数组
				System.out.print("len="+len+"..."+new String(buf,0,len));
			}
		}
			catch (IOException e)
		{
			throw new RuntimeException("读取失败");
		}
		finally
		{
			try
			{
				if(fr!=null)
					fr.close();
			}
			catch (IOException e)
			{
			}
		}		
	}
}


代码演示3:

/*
需求:将C盘下的一个文件复制到D盘

复制的原理:
其实就是将C盘下的文件数据存储到D盘下的一个文件中

步骤:
1,在D盘创建一个文件,用于存储C盘文件的数据
2,定义文件读取流和C盘文件关联
3,通过不断的读写完成数据的储存
4,关闭资源
*/


class CopyTest 
{
	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
	}
	
	//从C盘读取一个字符,就往D盘写入一个字符
	public static void copy()
	{
		//创建目的地
		FileWriter fw = new FileWriter("Demo_copy.txt");

		//与已有文件关联
		FileReader fr = new FileReader("Demo.txt");

		int ch = 0;
		while((ch=fr.read())!=-1)
		{
			fw.write(ch);
		}

		fw.close();
		fr.close();
	}
}


代码演示4:

/*
缓冲区的出现是为了提高流的操作效率而出现的
所以在操作缓冲区之前要先有流对象
*/

import java.io.*;

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

		//为了提高字符写入效率,加入了缓冲技术
		//只要将需要提高效率的流对象作为参数,传递给缓冲区的构造函数即可
		BufferedWriter bufw = new BufferedWriter(fw);

		bufw.write("abcde");
		
		//换行
		bufw.newLine();

		//只要用到缓冲区,就要记得刷新
		bufw.flush();
		
		//其实关闭缓冲区,就是在关闭缓冲区中的流对象
		bufw.close();
	}
}

/*
字符读取流缓冲区
该缓冲区提供了一个一次读取一行的方法readLine() 方便对文本文件的获取
当返回null时,表示读到文件末尾

readLine()方法的原理:
无论是读一行,读取多个字符,其实最终都是在硬盘上一个一个的读取
所以最终还是调用的read()方法
*/


 

装饰设计模式

1 当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,提供加强功能

2 那么自定义的该类被称为装饰类

 

装饰类通常会通过构造方法接收被装饰的对象

并基于被装饰的对象功能,提供更强的功能

 

MyReader //专门用于读取数据的类

       |--MyTextReader

              |--MyBufferTextReader

       |--MyMediaReader

              |--MyBufferMediaReader

       |--MyDataReader

              |--MyBufferDataReader

 

class MyBufferReader

{

       MyBufferReader(MyTextReader text)

       {}

       MyBufferReader(MyMediaReader media)

       {}

}

 

上面这个类扩展性很差

找到其参数的共同类型,利用多态,可以提高扩展性

 

class MyBufferReader

{

       MyBufferReader(MyReader r)

       {}

}

 

MyReader //专门用于读取数据的类

       |--MyTextReader

       |--MyMediaReader

       |--MyDataReader

       |--MyBufferReader

装饰模式比继承体系要灵活,避免了继承体系臃肿

而且降低了类与类之间的关系

 

装饰类因为增强已有对象,具备的功能和已有的功能时相同的,只不过提供了更强功能

所以装饰类和被装饰的类都属于一个体系

字节流

基本操作与字符流类相同

但它不仅可以操作字符,还可以操作其他媒体文件

 

读取键盘录入:

System.out:对应的是标准输出设备,控制台

System.in:对应的标准输入设备,键盘

 

转换流

InputStreamReader,OutputStreamWriter

转换流的由来

字符流与字节流之间的桥梁

方便了字符流与字节流之间的操作

转换流的应用

字节流中的数据都是字符时,转成字符流操作更高效。

代码演示5:

/*
需求:
通过键盘录入一行数据并打印其大写,发现其实就是读一行的原理
也就是readLine()

能不能直接使用readLine方法来完成键盘录入的一行数据读取呢?

readLine方法是字符流BufferedReader类中的方法
而键盘录入的read()方法是字节流InputStream的方法
那么能不能将字节流转换成字符流再使用字符流缓冲区的readLine()方法呢?

*/
import java.io.*;

class TransDemo 
{
	public static void main(String[] args) 
	{
		//获取键盘录入对象
		InputStream in = System.in;

		//将字节流对象转换成字符流对象,使用InputStreamReader()
		InputStreamReader isr = new InputStreamReader(in);

		//为了提高效率,使用缓冲技术
		BufferedReader bufr = new BufferedReader(isr);

		String line = null;
		while((line=bufr.readLine())!=null)
		{
			if(line.equals("over");
				break;
			System.out.println(line.toUpperCase());
		}
		bufr.close();

		/*
		输出转换流
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		*/

	}
}

 

流操作规律:

1

源:键盘录入

目的:控制台

 

2          需求:把键盘录入的数据存储到一个文件中

源:键盘

目的:文件

 

3          需求:想要将一个文件的数据打印在控制台上

源:文件

目的:控制台

 

流操作的基本规律:通过两个明确来完成

1 明确源和目的

       源:InputStream Reader

       目的:OutputStream Writer

2 操作的数据是否是纯文本

       是:字符流

     不是:字节流

4 当体系明确后再确定使用哪个对象

     源设备:内存,键盘,硬盘

       目的设备:内存,硬盘,控制台

File

用来将文件或者文件夹封装成对象

方便对文件与文件夹的属性信息进行操作。

File对象可以作为参数传递给流的构造函数。

 

File类常见的方法

创建

boolean createNewFile() 在指定位置创建文件,如果该文件已经存在,则不创建。返回false

       和输出流不一样,输出流对象一旦创建文件,而且文件已经存在,会覆盖

       boolean mkdir()          创建文件夹

       boolean mkdirs() 创建多级文件夹

删除

boolean delete()  删除失败,返回false如果文件正在使用,则不能删除,返回false

       void deleteOnExit() 在程序退出时删除指定文件

判断

       boolean exists() 文件是否寻在

       isFile();

       isDirectory();

       isHidden();

       isAbsolute();

获取信息

       getName();

       getPath();

getParent();//该方法返回的是绝对路径下的父目录,如果获取的是先对路径,返回null

                            //如果该相对路径中有上一层目录,那么该目录就是返回结果

       getAbsolutePath();

 

       long lastModified();

       long length();

 代码演示6:

import java.io.*;

class FileDemo 
{
	public static void main(String[] args) 
	{
		listDemo_1();
	}

	public static void method_1() 
	{
		try
		{
			//将file.txt封装成文件对象
			File f = new File("file.txt");

			sop("create:"+f.createNewFile());	//

			sop("canExcute:"+f.canExecute());	//测试应用程序是否可以执行这个文件

			sop("parent:"+f.getParent());		//返回父目录的路径名字符串

			sop("existe:"+f.exists());		//测试此文件或目录是否存在

			sop("delete:"+f.delete());		//删除此抽象路径名表示的文件或目录

			sop("AbsPath:"+f.getAbsolutePath());//返回此抽象路径名的绝对路径名形式

			File dir = new File("abc");

			sop("mkdir:"+dir.mkdir());	//在dir文件目录下创建一个文件夹

			File f1 = new File("d:\\java0217\\day20\\FileDemo1.java");
			File f2 = new File("d:\\java0217\\day20\\haha.java");

			sop("raname:"+f2.renameTo(f1));	//重新f2表示的文件

		}
		catch (IOException e)
		{
			throw new RuntimeException("file Exception");
		}	
	}

	public static void listRootsDemo()
	{
		File[] files = File.listRoots();//表示可用文件系统根的 File 对象数组
		
		for(File f : files)
		{
			System.out.println(f);
		}
	}

	public static void listDemo_1()
	{
		File f = new File("d:\\java0217\\day20\\");

		//返回一个字符串数组,这些字符串指定d:\java0217\day20\路径表示的目录中的文件和目录
		String[] names = f.list();	//调用list()的file对象必须封装了一个目录,该目录必须存在
		for(String name : names)
		{
			System.out.println(name);
		}
	}

	public static void listDemo_2()
	{
		//创建一个File对象
		File dir = new File("d:\\java0217\\day20");

		String[] arr = dir.list(new FilenameFilter()
		{
			//list方法依据accept方法的返回值判定是不是需要过滤文件
			public boolean accept(File dir ,String name)
			{
				return name.endsWith(".java");
			}
		});

		for(String name : arr)
		{
			System.out.println(name);
		}
	}

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


代码演示7:

import java.io.*;
/*
列出指定目录下文件或者文件夹,包含子目录中的内容
也就是列出指定目录下的所有内容

递归要注意:
1,限定条件
2,要注意递归的次数,避免内存的溢出
*/
class FileDemo2 
{
	public static void main(String[] args) 
	{
		File dir = new File("d:\\java0217\\day20");
		int level = 0;
		showDir(dir,level);
	}

	public static void showDir(File dir,int level)
	{
		System.out.println(getLevel(level)+"  "+dir.getName());

		level++;
		
		//列出指定目录下的所有文件
		File[] files = dir.listFiles();

		for(int x=0; x<files.length; x++)
		{
			//如果该文件对象是一个目录
			if(files[x].isDirectory())
				showDir(files[x],level);
			else
				System.out.println(getLevel(level)+"  "+files[x]);
		}
	}
	//根据不同的层级返回不同的空格数
	public static String getLevel(int level)
	{
		StringBuilder sb = new StringBuilder();

		for(int x=0; x<level; x++)
		{
			sb.append("  ");
		}
		return sb.toString();
	}
}


 

Properies

Propertieshashtable的子类

也就是说它具备map集合的特点,而且它里边存的键值对都是字符串

 

是集合中和IO技术相结合的集合容器

该对象的特点:可以用于键值对形式的配置文件

那么在加载数据时,需要数据有固定格式:健=

代码演示8:

import java.io.*;
import java.util.*;

class  PropertiesDemo
{
	public static void main(String[] args) 
	{
		method_2();
	}

	//设置和获取元素
	public static void method_1()
	{
		Properties prop = new Properties();
		
		prop.setProperty("zhangsan","30");
		prop.setProperty("lisi","29");

		String value = prop.getProperty("zhangsan");	//返回zhangsan对应的值

		System.out.println(value);

		//返回该集合中所有的键值
		Set<String> names = prop.stringPropertyNames();	//1.6开始出现的stringPropertyNames()
		for(String s : names
		{
			System.out.println(s+"  "+prop.getProperty(s));
		}
	}
/*
想要将info.txt中的键值数据存储到集合中进行操作
1,用一个流和info.txt文件相关联
2,读取一行数据,将该行数据用=进行切割
3,等号左边作为键,右边作为值,存入到Properties集合中即可
*/
	public static void method_2()
	{
		BufferedReader bufr = null;
		try
		{
			bufr = new BufferedReader(new FileReader("info.txt"));
			String line = null;
			Properties prop = new Properties();

			while((line = bufr.readLine())!= null)
			{
				//切割每一行数据
				String[] arr = line.split("=");
				
				//将等号两边的内容存放到Properties集合中
				prop.setProperty(arr[0],arr[1]);
			}
			System.out.println(prop);
		}
		catch (IOException e)
		{
			throw new RuntimeException("read exception");
		}
		finally
		{
			try
			{
				if(bufr!=null)
					bufr.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("close failed");
			}
		}
		
	}
}


 

打印流:

PrintStream为其他输出流添加了功能,使他们能够方便的打印各种数据值表现形式

该流提供了打印方法,可以将各种数据类型的数据都原样打印

 

字节打印流:

PrintStream

构造函数可以接收的参数类型

1file对象   File

2,字符串路径 String

3,字节输出流 OutputStream

 

字符打印流:

1file对象   File

2,字符串路径 String

3,字节输出流 OutputStream

4,字符输出流 Writer

代码演示9:

class  PrintStreamDemo
{
	public static void main(String[] args) throws IOException
	{
		//读取键盘录入
		BufferedReader bufr = 
			new BufferedReader(new InputStreamReader(System.in));

		//创建一个字符打印流,将数据存储到指定的文件中,自动刷新
		PrintWriter pw = new PrintWriter(new FileWriter("a.txt"),true);

		String line = null;

		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			//打印并自动换行
			pw.println(line.toUpperCase());
			//pw.flush();
		}

		pw.close();
		bufr.close();
	}
}


 

IO包中的其他类

打印流

PrintWriterPrintStream

可以直接操作输入流和文件。

序列流 

SequenceInputStream

对多个流进行合并。

操作对象

ObjectInputStreamObjectOutputStream

被操作的对象需要实现Serializable (标记接口);

RandomAccessFile

随机访问文件,自身具备读写的方法。

通过skipBytes(int x),seek(int x)来达到随机访问。

管道流

PipedInputStreamPipedOutputStream

输入输出可以直接进行连接,通过结合线程使用。

操作基本数据类型

DataInputStreamDataOutputStream

操作字节数组

ByteArrayInputStreamByteArrayOutputStream

操作字符数组

CharArrayReaderCharArrayWrite

操作字符串

StringReader StringWriter

 

字符编码

字符流的出现为了方便操作字符。

更重要是的加入了编码转换。

通过子类转换流来完成。

InputStreamReader

OutputStreamWriter

在两个对象进行构造的时候可以加入字符集。

 

编码表的由来

1 计算机只能识别二进制数据,早期由来是电信号。

2 为了方便应用计算机,让它可以识别各个国家的文字。

3 就将各个国家的文字用数字来表示,并一一对应,形成一张表。

 

常见的编码表

ASCII:美国标准信息交换码。

用一个字节的7位可以表示。

ISO8859-1:拉丁码表。欧洲码表

用一个字节的8位表示。

GB2312:中国的中文编码表。

GBK:中国的中文编码表升级,融合了更多的中文文字符号。

Unicode:国际标准码,融合了多种文字。

所有文字都用两个字节来表示,Java语言使用的就是unicode

UTF-8:最多用三个字节来表示一个字符。

 

 

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值