黑马学习日记_IO篇(第二部分)_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 黑马学习日记_IO篇(第二部分)

黑马学习日记_IO篇(第二部分)

 2014/4/6 12:15:46  小驴变黑马  程序员俱乐部  我要评论(0)
  • 摘要:----------------------android开发、java培训、期待与您交流!----------------------转换流转换流是字符流与字节流之间的桥梁,是为了方便字符流与字节流之间的操作。当字节流中都是字符时,转成字符流操作更为高效,例如:能不能使用readLine方法完成键盘录入的一行数据的读取呢,但是readLine是BufferedReader的方法,而System.in是InputStream的方法,这样就用到了转换流(InputStreamReader
  • 标签:学习
----------------------class="Apple-converted-space">?android开发、java培训、期待与您交流! ---------------------- 转换流 ?转换流是字符流与字节流之间的桥梁,是为了方便字符流与字节流之间的操作。 ?当字节流中都是字符时,转成字符流操作更为高效, ?例如:能不能使用readLine方法完成键盘录入的一行数据的读取呢,但是readLine是BufferedReader的方法, ??而System.in是InputStream的方法,这样就用到了转换流(InputStreamReader) ?InputStreamReader是一个字符流,要想转换字节流那就要在构造函数的时候把字节流当参数传入 ?读取转换流 ??BfferedReader bufr = ????new BufferedReader(new InputStreamReader(System.in)); ?写入转换流:字符转字节,比如录入的是字符,把它存到硬盘上是字节 ??BufferedWriter bufw = ????new BufferedWriter(new OutputStreamWriter(System.out)); ? 转换流规律: ?操作流的时候流对象有很多该用哪个呢?通过三个明确来完成。 ?1.明确源和目的 ?有的时候可能只有源或目的,要先明确 ??源:因为是源所以使用读取流,即 InputStream ,Reader ??目的: 写入流 即 OutputStream , Writer ?2.明确操作的数据是否为纯文本 ?即是明确用字节流还是字符流 ??是:用字符流 ??不是:用字节流 ?3.明确设备 ?就是明确用那个对象,就是看用不用转换流 ??源设备: 内存 ,硬盘 ,键盘 ??目的设备:内存 ,硬盘,控制台 ??然后再确定下需不需要提高效率,就是确定需不需要缓冲流。 ?例如: ?1,将一个文本文件中数据存储到另一个文件中。复制文件。 ??这个明确了源和目的都有, ??源:InputStream ?Reader ??是纯文本吗?是。明所以用字符流 就是Reader ??源设备:硬盘 ?不需要转换流 ??这时候就可以确定了用 FileReader ??是否需要提高效率?是。加入缓冲区 BufferedReader、 ??FileReader fr = new FileReader("Demo.txt"); ??BufferedReader bfr ?= new BufferedReader(fr); ??目的:OutputStream ???Writer ??是纯文本吗?是。所以用字符流 Writer. ??目的设备:硬盘 ?不需要转换流。 ??所以就可以确定用 FileWriter了。 ??是否需要提高效率?是。加入缓冲区 BufferedWriter ??FileWriter fw = new FileWriter(); ??BufferedWriter bfw = new BufferedWriter(fw); ?2,需求:将键盘录入的数据保存到一个文件中。 ?? ??明确1这个既有源也有目的 ??源: InputStream ??Reader ??是否为纯文本?是,键盘录入的也是字符,用Reader ??源设备:键盘。对应的对象是 System.in。这时就想了上面不是明确了用Reader了吗,但是 ??System.in是字节流啊,所以既然明确了用Reader这时就需要用转换流了InputStreamReader。 ??需要提高效率吗?需要。所以要用BufferedReader。 ??InputStreamReader isr = new InputStreamReader(System.in); ??BufferedReader bfr = new BufferedReader(isr); ??目的:OutputStream ??Writer ??是否为纯文本?是, 用Writer ??目的设备:一个文件文件 在硬盘 不需要转换流,可以确定用FileWriter ??FileWriter fw = new FileWriter("Demo.txt"); ??需要提高效率吗?需要。 ??BufferedWriter bufw = new BufferedWriter(fw); -------------------------------------------------------------------------------------------- ? ?扩展:想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。 ??源和上面的一样,不变。 ??目的:OutputStream ?Writer ??是否为纯文本?是,Writer ??目的设备:硬盘 一个文件 ?用 FileWriter ??FileWriter是按默认的编码(GBK)存的。但是要求按照指定的编码(utf-8)存数据 ??而指定编码表只有转换流能制定,所以使用的对象是OutputStreamWriter,而转换流 ??又要接收一个字节流,而且该字节流还能操作文件,所以就是 FileOutputStream ??需要提高效率吗?需要。所以要用到BufferedReader ??OutputStreamWriter osw =? ????new OutputStreamWriter(new FileOutputStream("Demo.txt"),"UTF-8"); ??所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时, ??需要用到转换流。 ?改变标准输入输出流设备: ??系统默认的标准输入输出设备是 System.in 和 System.out ??但是可以通过System类中setIn,setOut方法对默认设备进行改变。 ??System.setIn(new FileInputStream(“1.txt”));//将源改成文件1.txt。 ??System.setOut(new FileOutputStream(“2.txt”));//将目的改成文件2.txt --------------------------------------------------------------------------------------------------------------------------------- ? File类 ?流在操作的只有数据,而数据最明显的体现形式就是文件,文件又包含了很多的属性和行为信息, ?比如说前缀名、扩展名、文件自己的大小时间等,所以文件是一个复杂的事物而这个事物有很多, ?所以java就对文件这类的事物进行了描述,也把它封装成了对象,方面了我们对文件或文件夹的 ?属性进行操作。而File类的对象也主要用来获取文件本身的一些信息,如文件大小权限等,不涉 ?及对文件的读写操作。 ?查看API知道java提供了三种创建方法来生成一个文件对象。 ?(1)根据参数指定的文件路径创建一个File文件对象,就是把某个文件封装成对象 ??File file1 ?= new File("D:\\abc\\123.txt"); ?(2)根据给定的目录创建一个File实体对象,其中"d:\\abc"为目录,"123.txt"为文件的名称 ??File file2 ?= new File("D:\\abc","123.txt"); ?(3)可以根据已知的目录文件对象File创建一个新的File实体对象 ??File d = new File("D:\\abc"); ??File file3 = new File(d,"123.txt"); ?File类所提供的方法中,有的是针对文件的处理,有的是针对目录的处理,可以通过一些方法来 ?判断文件是否存在以及文件的相对路径和绝对路径等,File类的常见方法有: ?1,创建。 ??boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。 ??????和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。 ??boolean mkdir():创建目录文件夹。 ??boolean mkdirs():创建多级文件夹。 ?2,删除。 ??boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。 ??void deleteOnExit();在程序退出时删除指定文件。 ?3,判断。 ??boolean exists() :文件是否存在. ??isFile(): 是否为文件 ??isDirectory();是否为目录 ??isHidden(); ??isAbsolute(); ?4,获取信息。 ??getName()://获取文件名 ??getPath()://获取相对路径 ??getParent()://返回的绝对路径的文件父目录 ??getAbsolutePath() //获取绝对路径 ??long lastModified()? ??long length()? ?部分代码: ??
class  FileDemo
  {
   public static void main(String[] args) throws IOException
   {
    File f = new File("abc.txt");//把文件封装成对象
     sop(f.createNewFile());//创建一个文件创建成功返回true,如果已存在创建不成功,返回false
    File f = new File("abc");
    sop(f.mkdir());//创建一个目录,mkdirs能创建多级目录
   //在判断文件对象是否是文件或者目录时,一定要先判断该文件对象封装的内容是否存在
    isexists();//因为封装了一个文件对象,如果没创建的话,系统里就没有的所以要先判断下。
    isFile();//判断你创建的是否为文件
    isDirectory();//判断是否为目录
    File f = new File("abc\\abc.txt");
    getParent();//获取绝对路径的文件父目录,你创建时是相对路径会返回null
       //如果相对路径中有上一层目录那么该目录就是返回结果。如上返回父目录abc
   
   }
   public static void sop(Object obj)
   {
    System.out.println(obj);
   }
  }
?文件列表: ?listRoots();//能列出我们机器里面有效的盘符,它是一个静态方法,返回的是File数组 ?String[] list();//返回值类型是是String数组, ?File f = new File("d:\\"); ?Stringp[] names = f.list();//打印的是d盘下所有文件和文件夹的名称,所以返回的是字符串数组 ???????//但是要确定调用list方法的File对象必须是封装了一个目录,并且该目录还必须存在 ? ?for(String name : names)//不然你封装了一个文件对象,那它返回的数组就为null,那就不能遍历数组了 ?{ ??System.out.println(name); ?} ?File[] files = f.listFile(); ?for(String file : files) ?{ ??System.out.println(file.getName()+"::"+file.length());//因为返回的是文件对象仍然能调用方法 ?} ----------------------------------------------------------------------------------------------------------------------------------? ? 递归:在遍历文件夹的时候,遍历的结果中仍有文件夹,这事是不是还要在遍历一次啊,比如说,你打开d盘 ???里面是不是有很多文件夹啊,然后是不是就要点开看看啊,然后里面还有文件夹是不是还要打开?这 ???样是不是在重复一个操作,就是遍历文件夹里的元素,里面有文件夹的话就再遍历....这样我们在 ???写代码的时候是不是再重复用同一个方法,就是用一个方法遍历文件夹,如果里面有文件夹的话,就在 ???调用本方法。也就是函数自身调用自身。这种编程手法就是递归。 ???部分代码: ??? ??
class  FileDemo
  {
   public static void main(String[] args) throws IOException
   {
    File dir = new File("f:\\javademo");
    showDir(dir);
   }
   public static void showDir(File dir)
   {
    File[] files = dir.listFiles();
    for(int x=0; x
    {
     if(files[x].isDirectory())//判断,如果便利中碰到文件夹
      showDir(files[x]);//就再调用此方法进行遍历
     else
      System.out.println(files[x]);
    }
   }
  }
???递归要注意: ??1,限定条件。没条件限定的话,函数里面又调用它自身不就相当于死循环啦。 ??2,要注意递归的次数。尽量避免内存溢出。每次递归都会在栈内存中开辟空间,不限定的话会内存溢出 ------------------------------------------------------------------------------------------------------------------------------------? ? Properties类: ?Properties是hashtable的子类。一个可以将键值进行持久化存储的对象。 ?也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。 ?是集合中和IO技术相结合的集合容器。 ? ?该对象的特点:可以用于键值对形式的配置文件。 ?那么在加载数据时,需要数据有固定格式:键=值。 ?特点: ?1:可以持久化存储数据。 ?2:键值都是字符串。 ?3:一般用于配置文件。 ???|-- load():将流中的数据加载进集合。 ?   原理:其实就是将读取流和指定文件相关联,并读取一行数据,因为数据是规则的key=value,所以获 ??取一行后,通过 = 对该行数据进行切割,左边就是键,右边就是值,将键、值存储到properties集合中。 ? |-- store():写入各个项后,刷新输出流。 ? |-- list():将集合的键值数据列出到指定的目的地。 -------------------------------------------------------------------------------------------------------------------------------- ? IO包中的其他类: ?打印流? ??PrintWriter与PrintStream 可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类 ??型的数据都原样打印。 ??字节打印流:PrintStream ? ???构造函数可以接收的参数类型: ???1,file对象。File ???2,字符串路径。String ???3,字节输出流。OutputStream ??字符打印流:PrintWriter ???构造函数可以接收的参数类型: ???1,file对象。File ???2,字符串路径。String ???3,字节输出流。OutputStream ???4,字符输出流,Writer。 ----------------------------------------------------------------------------------------------------------------------------------- ?序列流 ? ??SequenceInputStream 对多个流进行合并。它的构造函数接收的是两个输入流,或者是接收一个输 ???入流的枚举。 ??比如说要把三个文件的内容复制到另一个文件中,是不是要一个一个的重复Copy文件的那个动作啊, ??就是每复制一个文件都要创建一个写入流和输出流,然后再进行读写操作,复制三个文件是不是就 ??要重复三次啊,并且创建目的文件的时候还要写成可续写格式,不然就会被覆盖掉,而序列流就解 ??决了这个问题,他可以把多个流合并在一起,然后再进行其他操作。 ?? ??//把三个文件复制到另一个文件中 部分代码: ?
 public static void main(String[] args) throws IOException
  {
   //枚举只有list集合里的vector有所以要创建一个集合来装输入流
   Vector v = new Vector();
   //把三个文件的读取流对象添加到集合里
   v.add(new FileInputStream("d:\\1.txt"));
   v.add(new FileInputStream("d:\\2.txt"));
   v.add(new FileInputStream("d:\\3.txt"));
   //获取集合的枚举Enumeration
   Enumeration en = v.elements();
   //将输入流的枚举传给序列流,之后操作这个流就行了
   SequenceInputStream sis = new SequenceInputStream(en);
   //创建一个写入流再然后进行频繁的读写就行了
   FileOutputStream fos = new FileOutputStream("c:\\4.txt");
   byte[] buf = new byte[1024];
   int len =0;
   while((len=sis.read(buf))!=-1)
   {
    fos.write(buf,0,len);
   }
   fos.close();
   sis.close();
  }
  能合并就能切割://切割一图片  
  public static void spilt() throws IOException
  {
   FileInputStream fis = new FileInputStream("E:\\0.PNG");
   FileOutputStream fos = null;
   byte[] arr = new byte[1024*1024];
   int len = 0;
   int x=1;
   //每一次循环是不是都创建了一个流就是创建了一个文件啊?
   while((len=fis.read(arr))!=-1)
   {
    fos=new FileOutputStream("E:\\spilte\\"+(x++)+".part");
    fos.write(arr,0,len);
    fos.close();
   }
   fis.close();
  }
?------------------------------------------------------------------------------------------------------------------------------ ? ? ?操作对象的流 ??ObjectInputStream与ObjectOutputStream 被操作的对象需要实现Serializable (标记接口); ??流是可以操作数据的,现在数据被封装成对象了,我们知道对象是存放在堆内存中的,用完之后 ??就成了垃圾了,一被清理之后这个对象是不是就不存在了?而现在讲的这个流就可以操作对象, ??把这个对象的数据存放在硬盘上,对象里都封装了一些数据,那这些数据是不是就随着对象也存到 ??了硬盘上啦?这样的话即使这个程序结束了对象被清理了,我们是不是仍然能够获得这个对象里的 ??数据啊,因为它已经被存放到硬盘上了。 ??另外操作的那个对象的类要能被序列化,某个类要想能被序列化,就得实现java.io.Serializable 接口。 ? ??部分代码: ???ObjectOutputStream的目的是把对象和流相结合,是不是先把对先把流当参数传给它啊,所 ???以ObjectOutputStream在构造函数时一定要接收个流,什么流呢?就是把对象怎么着的流?也 ???就是目的。 ??? ???//既然要把对象写进文件那就要创建一个写入流 ???FileOutputStream fos = new FileOutputStream("t.tmp"); ???//把写入流当参数传给ObjectOutputStream ???ObjectOutputStream oos = new ObjectOutputStream(fos); ???//操作的这类person对象的类要实现Serializable接口 ???oos.writeObject(new Person());//将指定对象写入ObjectOutputStream。 ???oos.writeInt(12345); ???oos.close(); ----------------------------------------------------------------------------------------------------------------------------------------- ? ?管道流 ??PipedInputStream和PipedOutputStream输入输出可以直接进行连接,通过结合线程使用。 ??管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据 ??由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。 ??不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在 ??缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在, ??则认为该管道已损坏。? ?------------------------------------------------------------------------------------------------------------------------------------- ? ?RandomAccessFile类 ??该类不是算是IO体系中子类。而是直接继承自Object。但是它是IO包中成员。因为它具备读和写 ??功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获 ??取指针位置,同时可以通过seek改变指针的位置。 ??其实完成读写的原理就是内部封装了字节输入流和输出流。 ??通过构造函数可以看出,该类只能操作文件。而且操作文件还有模式:只读r,,读写rw等。 ? ??如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。 ??如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。 ??java语言提供了一个RandomAccessFile类来处理对一部分文件的输入/输出。RandomAccessFile类 ??创建的流于前面的输入输出流不一样,它既不是输入流InputStream的子类也不是输出流类OutputS- ??-tream的子类,但是RandomAccessFile类创建的流的指向既可以做为源也可以作为目的,换句话说 ??如果相对一个文件进行读取操作时,可以创建一个指向该文件的RandomAccessFile流,这样既可以 ??从这个流中读取文件的数据,也可以从这个流中写入数据到文件。 ??可以用以下两种方式打开一个随机存取文件: ?字符编码 ??字符流的出现为了方便操作字符。更重要是的加入了编码转换。 ??通过子类转换流来完成。 InputStreamReader OutputStreamWriter ??在两个对象进行构造的时候可以加入字符 集。 ??编码:字符串变成字节数组。 ??解码:字节数组变成字符串。 ??String-->byte[]; ?str.getBytes(charsetName); ??byte[] -->String: new String(byte[],charsetName); ?部分代码:
  class  EncodeDemo
  {
   public static void main(String[] args)throws Exception 
   {
    String s = "哈哈";
    byte[] b1 = s.getBytes("GBK");
    System.out.println(Arrays.toString(b1));
    String s1 = new String(b1,"utf-8");
    System.out.println("s1="+s1);
    //对s1进行iso8859-1编码。
    byte[] b2 = s1.getBytes("utf-8");
    System.out.println(Arrays.toString(b2));
    String s2 = new String(b2,"gbk");
    System.out.println("s2="+s2);
    
   }
  }
? ----------------------?android开发、java培训、期待与您交流! ----------------------
发表评论
用户名: 匿名