黑马程序员——————java中的IO

来源:互联网 发布:linux 重命名文件夹 编辑:程序博客网 时间:2024/04/18 10:22

------- android培训、java培训、期待与您交流! ----------

Java中的IO:

Java中的IO流分为两种,即字节流和字符流

字节流有两个基类:InputStream 和 OutputStream

字符流有两个基类:Writer  和 Reader

现在我们通过字节流来复制一个mp3文件:(没次读取并写入一个字符)

impor java.io.*;

 

classStreamDemo

{

       public static void main(String[]args)

       {

           FileInputStream fi=newFileInputStream("C:"+File.separator+"1.mp3");

               FileOutputStream fo=new FileOutputStream("C:"+File.separator+"2.mp3");

 

               int ch=0;

               while((ch=fi.read())!=-1)

              {

                   fo.write(ch);      

              }

              fi.close();

              fo.close();

       }

}


也可以定义一个字节数组作为中专站:

import   java.io.*;

 

class StreamDemo

{

       public static void main(String[]args)

       {

           FileInputStream fi=newFileInputStream("C:"+File.separator+"1.mp3");

               FileOutputStream fo=newFileOutputStream("C:"+File.separator+"2.mp3");

 

               byte[] buf=new byte[1024];

               int len=0;

               while((len=fi.read(buf))!=-1)

              {

                   fo.write(buf,0,len);      

              }

              fi.close();

              fo.close();

       }

}

为了提高效率我们可以通过字节流缓冲区进行文件的复制:

importjava.io.*;

 

classStreamDemo

{

       public static void main(String[]args)

       {

           FileInputStream fi=newFileInputStream("C:"+File.separator+"1.mp3");

               FileOutputStream fo=newFileOutputStream("C:"+File.separator+"2.mp3");

 

               BufferedInputStream bufr=newBufferedInputStream(fi);

               BufferedOutputStream bufw=newBufferedOutputStream(fo);

 

               byte[] buf=new byte[1024];

               int len=0;

               while((len=bufr.read(buf))!=-1)

              {

                   bufw.write(buf,0,len);      

              }

              bufr.close();

              bufw.close();

       }

}




如果要操作的是字符文件,我们就用FileWriterFileReader对文件的读取和写入与上面的字节流类似


File类:

File类是在java的IO操作中常用的一个类,

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

方便对文件和文件夹进行操作,

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

在File类中有很多常用的方法。

importjava.io.*;

classFileDemo

{

       public static void main(String[]args)

       {  

              //File类的构造函数的演示:

          File f1=new File("a.txt");

              File f2=newFile("C:\\abc","b.txt");

 

              File f3=newFile("C:\\abc");

              File f4=newFile(f3,"c.txt");

 

              File f4=new File("C:"+File.separator+"abc"+File.separator+"r.txt");

       }

}



File类中的常用的方法:

创建文件夹:mkdir() 只能创建一级目录。mkdirs()创建多级目录。          

创建文件:createNewFile();

删除:delete();   deleteOnExit()在程序退出时删除文件

判断:exists()判断文件是否存在  isFile()判断是否是文件  isDirectory()判断是否是目录

 

现在我们看一个File操作的例子(理解递归的思想)

importjava.io.*;

classFileDemo3

{

       public static void main(String[]args)

       {

         File dir=new File("E:\\test");

         showDir(dir);

       }

 

       public static void showDir(File dir)

       {

          System.out.println(dir);

              File[] files=new dir.listFiles();

              for(int x=0;x<dir.length;x++)

              {

                 if(files[x].isDirectory())

                     {

                         show(files[x]);

                     }

                     else

                            System.out.println(files[x]);

              }

       }

}



      

字符编码的问题:

在Java中,字符只以一种编码形式存在

但“在Java中”到底是指在哪里呢?就是指在JVM中,在内存中,在你的代码里声明的每一个char,String类型的变量中。

JVM的这种约定使得一个字符存在的世界分为了两部分:JVM内部和OS的文件系统。在JVM内部,统一使用UTF-16表示,

当这个字符被从JVM内部移到外部(即保存为文件系统中的一个文件的内容时),就进行了编码转换。


因此可以说,所有的编码转换就只发生在边界的地方,JVM和OS的交界处,也就是你的各种输入输出流(或者Reader,Writer类)起作用的地方。


尽管看上去混乱繁杂,但是所有的IO基本上可以分为两大阵营:面向字符的Reader啊Wrtier啊,以及面向字节的InputStream啊OutputStream啊。

下面我来逐一分解,其实一点也不难。

面向字符和面向字节中的所谓“面向”什么,是指这些类在处理输入输出的时候,在哪个意义上保持一致。如果面向字节,那么这类工作要保证系统

中的文件二进制内容和读入JVM内部的二进制内容要一致。不能变换任何0和1的顺序

这种输入输出方式很适合读入视频文件或者音频文件,或者任何不需要做变换的文件内容。

而面向字符的IO是指希望系统中的文件的字符和读入内存的“字符”(注意和字节的区别)要一致。例如我们的中文版WindowsXP系统上有

一个GBK的文本文件,其中有一个“汉”字,这个字的GBK编码是0xBABA(而UTF-16编码是0x6C49),当我们使用面向字符的IO把它读入内存

并保存在一个char型变量中时,我希望IO系统不要傻傻的直接把0xBABA放到这个char型变量中,我甚至都不关心这个char型变量具体的二进

制内容到底是多少,我只希望这个字符读进来之后仍然是“汉”这个字。从这个意义上也可以看出,面向字符的IO类,也就是Reader和Writer类,

实际上隐式的为我们做了编码转换,在输出时,将内存中的UTF-16编码。字符使用系统默认的编码方式进行了编码,而在输入时,将文件系统中已经编

码过的字符使用默认编码方案进行了还原。我两次提到“默认”,是说

Reader和Writer的聪明也仅此而已了,它们只会使用这个默认的编码来做转换,你不能为一个Reader或者Writer指定转换时使用的编码。这也意味着,

如果你使用中文版WindowsXP系统,而上面存放了一个UTF-8编码的文件,当你使用Reader类来读入的时候,它会傻傻的使用GBK来做转换,转换后的

内容当然驴唇不对马嘴!

这种笨,有时候其实是一种傻瓜式的功能提供方式,对大多数初级用户(以及不需要跨平台的高级用户)来说反而是件好事。

但我们不一样啦,我们都是国家栋梁,肩负着赶英超美的责任,必须师夷长技以治夷,所以我们总还要和GBK编码以外的文件打交道。

说了上面这些内容,想必聪明的读者已经看出来,所谓编码转换就是一个字符与字节之间的转换,因此Java的IO系统中能够指定转换编码的地方,

也就在字符与字节转换的地方,那就是:InputSteamReader和OutputStreamWriter!

 

------- android培训、java培训、期待与您交流! ----------


原创粉丝点击