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

时间:2023-02-18 22:41:16

java之IO流(二)

 

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

 

流操作规律

1.源:键盘录入      目的:控制台  (上面的例子即是)

2.源:键盘录入      目的:文件(需求是将键盘录入的数据录入到一个文件中)

将代码

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

BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));

改为

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

BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("存放的指定路径")));

 

3.源:文件  目的:控制台(需求是将一个文件的数据打印到控制台上)

将代码

BufferedReader  bufr=new BufferedReader(new InputStreamReader(new FileInputStream("读取的文件路径")));

BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));

流操作的基本规律:我们经常遇到的问题是流很多,但是不清楚该用到哪一个

1.明确源和目的(源是输入流,InputStream Reader    目的是输出流,OutputStream Writer)

2.操作是数据是否是纯文本(是:字符流   否:字节流)

3.当体系明确后,还需要知道要使用哪个具体对象,通过设备来区分

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

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

 

改变标准输入输出设备

System.setIn(new FileInputStream("读取的文件路径"));

System.setOut(new PrintStream("复制到指定文件路径"));

异常的日志信息(将异常的日志信息打印到指定的文件中)

public static void main(String[] args) {
  try {
   int []arr=new int[2];
   System.out.println(arr[3]);
  } catch (Exception e) {
   try {
    Date d=new Date();
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
    String s=sdf.format(d);
    PrintStream ps=new PrintStream("打印到指定的文件路径");
    ps.println(ps);
   } catch (Exception e2) {
    throw new RuntiemException("日志文件创建失败");
       e2.printStackTrace(System.out);
   }
  }
 }

获取系统信息

Properties prop=System.getProperties();

prop.list(new PrintStream("打印到指定的文件路径"));

 

File类

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

作用:用来将文件或者文件夹封装成对象,方便对文件与文件的属性 夹进行操作。

格式:File   f1=new Fille("路径");

             File   f2=new Fille("父路径","子路径");

File.separator相当于//,用于解决跨平台时所产生的问题

 

File对象功能---创建和删除

1.创建:boolean mkdir():创建文件夹

                 boolean mkdirs():创建多级文件夹

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

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

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

                   System.Out.println(f1.createNewFile());

                第一次运行时的结果为true,再次运行时结果为false

2.删除:boolean delete();             //删除失败时返回false

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

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

                      System.Out.println(f1.delete());

                第一次运行时的结果为true,再次运行时结果为false

3.判断:boolean exists():文件是否存在

                isFile():是否是文件

                 isDirectory():是否是目录

                 isAbsolute():是否是绝对路径

                 (在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在,通过exists判断)

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

                      System.Out.println(f1.exists());

                 如果文件存在返回true,不存在返回false

4.获取信息:

                          4-1.getName():返回文件的名称

                          4-2.getPath():  返回文件的相对路径

 

                         4-3 getParent():返回文件的父目录(如果创建的时候没有指定则返回null)

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

                                          System.Out.println(f1.getParent());

                          该结果返回null

 

                          4-4getAbsolutePath():返回文件的绝对路径

                          4-5 lastModified():返回文件最后一次被修改的时间

                          4-6  length():返回文件的长度

                          4-7renameTo():覆盖原文件名

                            如:File f1=new File("c:\\a.txt");

                                     File f2=new File("c:\\b.txt");                                      System.Out.println(f1.renameTo(f2));
                            结果是f1的文件名变成了f2的,也可操作不同硬盘之间,文件的内容不会改变

文件列表

1.获取系统文件的有效盘符:listRoots()

File[]  files=File.listRoots();

for(File f:files){

         System.Out.println(f);

}

2.获取指定目录下的所有文件名称,包括隐藏文件的名称:list()

File f  =new File("c:\\");        //调用list方法的file对象必须是封装了一个目录,该目录还必须存在

String [] names=f.list();

for(String name:names){

System.Out.println(name);

}

list()和listFiles()的区别在于前者只能获取文件名称,后者还可以获取文件的长度,一般使用后者

3.文件名过滤

File dir=new File("指定需要过滤的文件夹");
  String []name =dir.list(new FilenameFilter(){
   public boolean accept(File dir,String name){
    return name.endsWith("需要过滤的文件的后缀名,比如说.txt");
   }
  });

4.列出目录下的所有内容--递归,即指定目录下的文件或文件夹,包含子目录中的内容

public static void main(String[] args){
  File dir=new File("指定的文件夹路径");
  showDir(dir);
 }
 public static void showDir(File dir){
  System.out.println(dir);
  File[] files=dir.listFiles();
  for (int i = 0; i < files.length; i++) {
   if(files[i].isDirectory())
    showDir(files[i]);
   else
    System.out.println(files[i]);
  }
 }

因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可

在列出过程中出现的还是目录的话,还可以再次调用本功能,也就是函数自身调用自身

像这种表现形式或者编程手法称之为递归。

递归要注意的事项:限定条件;注意递归的次数,尽量避免内存溢出。

5.删除一个带内容的目录

删除原理:在window中,删除目录是从里往外删的,这就需要递归

public static void main(String[] args){
  File dir=new File("删除指定的目录路径");
  removeDir(dir);
 }
 public static void removeDir(File dir){
  File[] files=dir.listFiles();
  for (int i = 0; i < files.length; i++) {
   //判断是否是隐藏文件和是否是目录,系统隐藏文件一般是不能删除的
   if(!files[i].isHidden()&&files[i].isDirectory()){
    removeDir(files[i]);
   }else{
    System.out.println(files[i].toString()+"--------"+files[i].delete());
   }
   System.out.println(dir+"-------"+dir.delete());
  }
 }

6.创建java的文件列表

需求:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中

           建立一个java 文件列表

思路:

6-1.对指定的目录进行递归

6-2.获取递归过程索引的java文件路径

6-3.将这些路径存储到集合中

6-4.将集合中的数据写入到一个文件中

/*
  * 测试代码
  */
 public static void main(String[] args)throws IOException{
  File dir=new File("指定目录下的文件夹的路径");
  List<File> list=new ArrayList<File>();
  fileToList(dir,list);
  //dir是父级目录,javalist.txt为目的文件夹名称
  File file=new File(dir,"javalist.txt");
  writeToList(list,file.toString());
 }
 /*
  * 提取.java为后缀名的文件的方法
  */
 public static void fileToList(File dir,List<File>list){
  File[] files=dir.listFiles();
  for(File file:files){
   if(file.isDirectory()){
    fileToList(file,list);
   }else{
    if(file.getName().endsWith(".java"))
     list.add(file);
   }
  }
 }
 /*
  * 将集合中的文件对象以字符串的形式存储指定的路径中
  */
 public static void writeToList(List<File>list,String javaListFile)throws IOException{
  BufferedWriter bufw=null;
  try {
   bufw=new BufferedWriter(new FileWriter(javaListFile));
   for (File f:list) {
    String path=f.getAbsolutePath();
    bufw.write(path);
    bufw.newLine();
    bufw.flush();
   }
  } catch (IOException e) {
   throw e;
  }
  finally{
   try {
    if(bufw!=null)
     bufw.close();
   } catch (IOException e) {
    throw e;
   }
  }
 }

 

Properties简述

Properties是hashtable的子类,也就是说它具有map集合的特点,而且里面存储的键值都是字符串

是集合中和IO技术相结合的集合容器,该对象的特点是可以用于键值对形式的配置文件

那么在加载数据时,需要数据具有固定的格式:键=值

Properties设置和存取元素 public static void setAndGet(){
  Properties prop=new Properties();
  //设置元素
  prop.setProperty("zhangsan", "30");
  prop.setProperty("lisi", "20");
  //获取lisi的值
  String value=prop.getProperty("lisi");
   System.Out.println(value);    //重新设置lisi的值
   prop.setProperty("lisi", 89+“”);
  //获取所有的键值
  Set<String> names=prop.stringPropertyNames();
  for (String s:names) {
   System.out.println(s+"----"+prop.getProperty(s));
  }
 }

Properties存储配置文件
  需求:如何将流中的数据存储到集合中,例如想要info.txt中键值存到集合中进行操作 思路: 1.用一个流和info.txt文件关联 2.读取一行数据,将该行数据用”=“进行切割 3.等号左边作为键,右边作为值,存入到Properties集合中即可   /*
  * 第一种形式,自定义,相当于load()方法
  */
 public static void method()throws IOException{
  BufferedReader bufr=new BufferedReader(new FileReader("info.txt"));
  String line=null;
  Properties prop=new Properties();
  while((line=bufr.readLine())!=null){
   String[]arr=line.split("=");
   System.out.println(arr[0]+"----"+arr[1]);
   prop.setProperty(arr[0], arr[1]);
  }
  bufr.close();
  System.out.println(prop);
 }
 /*
  * 第二种形式:使用load()方法
  */
 public static void loadTest()throws IOException{
  Properties prop=new Properties();
  FileInputStream fis=new FileInputStream("info.txt");
  prop.load(fis);
  System.out.println(prop);
  //另一种输出的形式:
  //System.out.println(System.out);
   fis.Colse(); }
当我们需要重新设置数据时,需要加上一些代码,相当于刷新一样,否则只在内存中修改。
prop.setProperty("lisi","25"); FileOutputStream fos=new FileOutputStream("info.txt"); prop.store(fos,”注释信息,都是带#号的”); fos.Close();   IO流中的其他类   打印流PrintWriter与PrintStream,可以直接操作输入流和文件   序列流SequenceInputStream,对多个流进行合并   操作对象ObjectInputStream与ObjectOutputStream,被操作的对象需要实现Serializable(标记接口)   PintStream(字节打印流) 构造函数可以接收的参数类型 1.file对象,File 2.字符串路径,Stirng 3.字节输出流,OutputStream   PintWriter(字符输出流)构造函数可以接收的参数类型1.file对象,File2.字符串路径,Stirng 3.字节输出流,OutputStream4.字符输出流,Writer   public static void main(String[] args) throws IOException {
  BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
  PrintWriter out=new PrintWriter(new FileWriter("a.txt"),true);
  String line=null;
  while((line=bufr.readLine())!=null){
   if("over".equals(line))
    break;
   out.write(line.toUpperCase());
  }
  out.close();
  bufr.close();
  管道流(PipedInputStream和PipedOutputStream)

/* java 管道流的读写操作 用于两个线程之间  
 PipedOutputStream    PipedInputStream  连接起来就是一个管道   
 管道输出流可以向管道写入数据   管道输入流可以从管道读取数据   
 这种Decorator 装饰 的设计模式 大大增强了java流的功能
 可以在构造流的时候连接 管道输入输出流 也可以通过connect函数连接

*/
import java.io.*  ;
class  PipeTest
{
 public  static   void main(String []args)  throws Exception
 {
     PipedInputStream pis=new PipedInputStream() ;   //构造管道输入流
     PipedOutputStream pos=new  PipedOutputStream(pis); //构造输出流并且连接输入流形成管道
     new Procedure(pos).start() ;  //线程启动
     new Consumer(pis).start();  //线程启动
   
 }
}

class  Procedure  extends Thread   //线程1管道 输出流
{
   private  PipedOutputStream  pos ;
   Procedure(PipedOutputStream  pos)
   {
         this.pos=pos ;
   }
    public  void run()
   {
         try
         {
            pos.write("hello! welcome you!".getBytes());  //向管道写入 数据
         }
         catch(Exception e)
         {         
           e.printStackTrace();
         }
   }
 
 
}

class  Consumer  extends  Thread
{
 private  PipedInputStream pis ;
 Consumer(PipedInputStream pis)
 {
      this.pis=pis ;
 }
 public   void  run()
 {
       try
       { 
          
           byte []buf=new byte[100] ;
           int len=pis.read(buf,0,100);            //从管道读取数据
           System.out.println(new String(buf,0,len)); 
        }
       catch(Exception e)
       {
           e.printStackTrace() ;
       }
    
 
 }

Java操作基本数据类型的流对象DataStream

子类:DataInputStream和DataOutputStream

class DataStreamDemo {  

  

    public static void main(String[] args) throws IOException {  

        // writeData();  

        // readData();  

        // writeUTFDemo();  

        readUTFDemo();  

    }  

  

    public static void readUTFDemo() throws IOException {  

        DataInputStream dis = new DataInputStream(new FileInputStream("utfdate.txt"));  

        String s = dis.readUTF();  

        System.out.println(s);  

        dis.close();  

    }  

  

    public static void writeUTFDemo() throws IOException {  

        DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));  

        dos.writeUTF("你好"); // UTF-8修改版  

        dos.close();  

    }  

  

    public static void readData() throws IOException {  

        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));  

        int num = dis.readInt();  

        boolean b = dis.readBoolean();  

        double d = dis.readDouble();  

        System.out.println("num=" + num);  

        System.out.println("b=" + b);  

        System.out.println("d=" + d);  

        dis.close();  

    }  

  

    public static void writeData() throws IOException {  

        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));  

        dos.writeInt(234);  

        dos.writeBoolean(true);  

       dos.writeDouble(9887.543);  

        dos.close();  

    }  

}  

用于操作字节数组的流对象

ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组

ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组

这就是数据目的地。

由于以上两个流对象都是操作的是数组,并没有使用系统资源,所以不用进行Close()关闭。

例如:

ByteArrayInputStream   bis=new ByteArrayInputStream("ABCDEFD".getByte());

ByteArrayOutputStream  bos=new ByteArrayOutputStream();

int by=0;

while((by=bis.read())!=-1){

bos.write(by);

}

System.Out.println(bos.size());

System.Out.println(bos.toString());

 

 

 

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