黑马程序员-java-流(IO)

来源:互联网 发布:数组转换json格式 编辑:程序博客网 时间:2024/04/28 18:36

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


对于Reader和Writer类,大体功能和InputStream、OutputStream两个类相同,但并不是它们的代替者,


只是在处理字符串时简化了我们的编程。


PipedInputStream与PipedOutputStream类


   一个PipedInputStream对象必须和一个PipedOutputStream对象进行连接而产生一个通信管道,


PipedOutputStream可以向管道中写入数据,PipedInputStream可以从管道中读取PipedOutputStream写


入的数据。


    这两个类主要用来完成线程之间的通信,一个线程的PipedInputStream对象能够从另外一个线程的


PipedOutputStream对象中读取数据。


例子代码:


Thread t1=new Sender();


Thread t2=new Receiver();


PipedOutputStream out=t1.getOutputStream();


PipedInputStream  in=t2.getInputStream();


out.coonect(in);


JDK中还提供了PipedWriter和PipedReder这两个类用于字符文本的管道通信。


 


ByteArrayInputStream与ByteArrayOutputStream类


    这两个类用于以IO流的方式来完成对字节数组内容的读写,来支持类似内存虚拟文件或者内存映像


文件的功能。


ByteArrayInputStream的两个构造函数:


ByteArrayInputStream(byte[] buf);


ByteArrayInputStream(byte[] buf,int offse,int length);


ByteArrayOutputStream也有两个构造函数:


ByteArrayOutputStream();


ByteArrayOutputStream(int);


与ByteArrayInputStream和ByteArrayIOutputStream类对应的字符串读写类分别是StringReader和


StringWriter。


 


重视IO程序代码的复用


    System.in连接到键盘,是InputStream类型的实例对象System.out连接到显示器,是PrintStream类


的实例对象。


    不管各种底层物理设备用什么方式实现数据的终止点,InputStream的read方法总是返回-1来表示输


入流的结束。


注意:这种方式只能判断文本文件是否结束,不能判断一个二进制文件是否结束。


    在Windows下,按下Ctrl+Z组合键可以产生键盘输入流的结束标记,在Linux下,则是按下Ctrl+D组


合键来产生键盘输入流的结束标记。


 


过滤流与包装类


DataOutputStream类提供了往各种输出流对象中写入各种类型的数据(包括浮点小数)的方法。中需传


递一个FileOutputStream输出流对象给DataOutputStream实例对象给DataOutputStream实例对象,就可


以向文件中写入各种类型的数据。


DataOutputStream并没有对应到任何具体的流设备,一定要给它传递一个对应具体流设备的输出流对象


,完成类似DataOutputStream功能的类就是一个包装类,也叫过滤流类或处理流类。


DataOutputStream包装类的构造函数语法:


public DataOutputStream(OutputStream out)


DataOutputStream包装类的部分方法列表:


public final void writeBoolean(boolean v)


public final void writeShort(int v)


public final void writeChar(int v)


public final void writeInt(int v )


    为什么DataInputStream类中有一个readUTF方法,而没有readBytes和readChars呢?


这是因为在DataOutputStream类中只有writeUTF方法向目标设备写入了字符串的长度。而另两个方法没


有,则无法读取。


BufferedInputStream与BufferedOutputStream类


    对IO进行缓冲是一种常见的性能优化,缓冲流为IO流增加了内存缓冲区。增加缓冲区有两个基本目


的:


1.允许java程序一次不只操作一个字节,这样提高了程序的性能。


2.由于有了缓冲区,使得在流上执行skip、mark和reset方法都成为可能。


    这两个类是Java提供的两个缓冲区包装类,不管底层系统是否使用了缓冲区,这两个类在自己的实


例对象中创建缓冲区。


    对输入流进行缓冲可以实现部分字符的回流。除了InputStream中常用的read和skip方法,


BufferedInputstream还支持mark和reset方法。


BufferedReader和BufferedWriter类:


BufferedReader的readLine方法可以一次读取一行文本,BufferedWriter的newLine方法可以向字符流中


写入不同操作系统下的换行符。


注意:如果正在使用一个流栈,程序关闭最上面的一个流也就关闭了栈中的所有底层流对象。


 


PrintStream类:


    这个类提供了一系列的print和println方法,可以实现将基本数据类型的格式化成字符串输出。


    IO包中提供了一个与printStream对应的printWriter类,printerWriter类即使遇到换行符(/n)也


不会自动清空缓冲区,只在设置了autoflush模式下使用了println方法后才自动清空缓冲区。如果我们


希望程序能够生成平台相关的文本换行,而不是在各种平台下都用"/n"作为文本换行,我们就应该使用


printWriter的println方法时,PrintWtiter的println方法能根据不同的操作系统而生成相应的换行符





ObjectInputStream与ObjectOutputStream类


    这两个包装类,用于从底层输入流中读取对象类型的数据和将对象类型的的数据写入到底层输出流





     这两个类所读写的对象必须实现了Serializable接口。对象中的transient和static类型的成员变


量不会被读取和写入。


     使用ObjectInputStream与ObjectOutputStream类保存和读取对象的机制叫序列化。


序列化的好处:


    它可以将任何实现了Serializable接口的对象转换为连续的字节数据,这些数据以后仍可以还原为


原来的对象状态。即使这些数据通过网络传输也没问题。序列化能处理不同操作系统上的差异,我们可


以在windows上产生某个对象,将它们序列化存储,然后通过网络传到linux机器上,该对象仍然可以被


正确重建出来,在这期间,我们完全不用担心不同机器上不同的数据表示方式。


 


字节流与字符流的转换


InputStreamReader和OutputStreamWriter,这两个类是字节流和字符流之间转换的类,


InputStreamReader可以将一个字节流解码成字符,OutputStreamWriter将写入的字符编码成字节后写入


一个字节流。


    为了达到最好的效率,避免频繁地进行字符与字节的相互转换,最好不要直接使用这两个类进行读


写,就尽量使用BufferedWriter类包装OutputStreamWriter类,用BufferedReader类包装


InputStreamReader类。例如:


BufferedReader in=new BufferedReader(new InputStreamReader(System.in));


BufferedWriter out=new BufferedWriter(new OutputStreamReader(System.out));


 


Decorator设计模式:


在程序中用一个对象包装另外一个对象,这是一种被称为Decorator的设计模式。


    如果要设计自己的IO包装类,这个类需要继承以Fileterxxx命名的类,从而扩展了对输入输出流的


支持。


 


Exception类从Throwable类继承的三个printStackTrace方法的定义如下:


1.public void printStackTrace()


2.public void printStackTrace(printStream s)


3.public void printStackTrace(printWriter s)


它们分别把异常的详细信息打印到标准输出流(屏幕上),或者其他的printStream和printWriter流中





字符编码


    为了解决各个国家和地区使用本地化字符编码带来的不利影响,人们将全世界所有的符号进行了统


一编码,称为Unicode编码。


    要正确地在屏幕打印中文字符,我们写入屏幕输出流的字节内容必须是该中文字符GB2312码,要将


中文正确的存入硬盘文件也是一样的道理。


UTF-8编码


    ASCII码字符保持原样,仍然只占用一个字节,对于其它国家的字符,UTF-8使用两个或三个字节来


表示。


    使用UTF-8编码的文件,通常都要有EF BB BF作为文件开头的三个字节数据。


字符的UTF-8编码与Unicode编码之间的转换关系对应下列规则:


-/u0001和/u007f之间的字符,UTF-8编码为:(byte)c。


-/u0000或其范围在/u0080和/u07ff之间的字符,UTF-8编码为:


      (byte)(0xc0|(ox1f&(c>>6))),(byte)(0x80|(0x3f&c))。


-/u0800和/uffff之间的字符,UTF-8编码为:


  (byte)(0xe0|(0x0f&(c>>12))),(byte)(ox80|(0x3f&(c>>6))),(byte)(0x80|(0x3f&c))


/u0001-/u007f         0xxxxxxx


/u0000或/u0080-/u07ff 110xxxxx  10xxxxxx


/u0800-/uffff         1110xxxx  10xxxxxx  10xxxxxx


UTF-8编码的优点:


1.不出现内容为0x00的字节


2.便于应用程序检测数据在传输过程中是否发生了错误


3.直接处理使用ASCII码的英文文档


UTF_8的缺点:


某些字符要占用3个字节,尤其是中文、日文及韩文等。


 


Java程序与其它进程的数据通信


    在Java程序中可以产生其他的应用程序的进程,在Java程序中启动的进程称为子进程,启动子进程


的Java程序称为父进程。


    在Java程序中可以用Process类的实例对象来表示子进程,子进程的标准输入和输出不再连接到键盘


和显示器,而是以管道流的形式连接到父进程的一个输出流和输入流对象上。调用Process类的


getOutputStream和getInputStream方法可以得到这个输出流和输入流对象.


代码:

import java.io.*;/*    思路;   |-- 首先定义一个方法,用来copy单个文件,        |-- 创建一个带缓冲的字符读取流与源文件相关联|-- 在创建一个带缓冲的字符写入流与目标文件相关联|-- 完成读写操作|-- 关闭资源   |-- 然后定义一个用来判断File对象是目录还是文件,用递归来遍历整个文件夹        |-- 如果是目录,就递归该目录|-- 如果是文件就调用文件copy方法复制文件*/class CopyFilesDemo2 {public static void main(String[] args) {File sour = new File("e:\\Open_Sourse");File targ = new File("e:\\copy");targ.mkdir();findFile(sour,targ);}public static void findFile(File sour,File targ){File[] files = sour.listFiles();for(File file:files){if(file.isDirectory()){String dir = file.getName();File newFile = new File(targ+"\\"+dir);newFile.mkdirs();findFile(file,newFile);}else{try{String fileName = file.getName();String[] newFileName = fileName.split("\\.");File new2File = new File(targ+"\\"+newFileName[0]+".java");new2File.createNewFile();copyFile(file,new2File);}catch (IOException e1){e1.printStackTrace();throw new RuntimeException("文件复制失败!");}}}}public static void copyFile(File sour,File targ){BufferedReader fr = null;BufferedWriter fw = null;try{if(!sour.isFile())throw new RuntimeException("sour不是一个文件");fr = new BufferedReader(new FileReader(sour));fw = new BufferedWriter(new FileWriter(targ));String line = null;while((line = fr.readLine())!= null){fw.write(line);fw.flush();}}catch (IOException e){e.printStackTrace();throw new RuntimeException("文件复制失败!");}finally{    try    {if(fr != null)fr.close();    }    catch (IOException efr)    {efr.printStackTrace();    }try{if(fw != null)fw.close();}catch (IOException efw){efw.printStackTrace();}}}}



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


详情请查看:http://edu.csdn.net


0 0
原创粉丝点击