黑马程序员_IO

来源:互联网 发布:淘宝开店基础知识 编辑:程序博客网 时间:2024/05/22 03:26

------- <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{//创建一个读取流对象,和指定的文件相关联//要保证该文件是一件存在的,如果该文件不存在,会出现FileNotFoundExceptionfr = 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);elseSystem.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:最多用三个字节来表示一个字符。

 

 

 

0 0