黑马程序员——java基础—IO流(二)

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

打印流概述:

字节流打印流   PrintStream

字符流打印流   PrintWriter

打印流的特点:

     A:只有写数据,没有读取数据。只能操作目的地,不能操作数据源。

B:可以操作任意类型的数据。

C:如果启动了自动刷新,能够自动刷新。

D:可以操作文件的流。

那些流对象是可以直接操作文本文件的呢?

FileInputStream

FileOutputStream

FileReader

FileWriter

printStream

printWriter

看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的。

流对象:

   基本流:就是能直接读写文件

   高级流:在基本流基础上提供了一些其他功能;

1.      可以操作任意类型的数据:

Print()

Pritln()

2.      启动自动刷新:

printWriter   pw = new PrintWriter(new FileWriter(“a.txt:” ,true)

还是调用println()的方法才可以;

这个时候不仅仅自动刷新了,还实现了数据的换行;

 Println() 等价于:

 Write();

 newLine();

 flush();

 

打印流复制文本文件;

  // 以前的版本
      // 封装数据源
      // BufferedReader br = new BufferedReader(newFileReader(
      // "DataStreamDemo.java"));
      // // 封装目的地
      // BufferedWriter bw = new BufferedWriter(newFileWriter("Copy.java"));
      //
      // String line = null;
      // while ((line = br.readLine()) != null) {
      // bw.write(line);
      // bw.newLine();
      // bw.flush();
      // }
      //
      // bw.close();
      // br.close();
 
      // 打印流的改进版
      // 封装数据源
      BufferedReader br = new BufferedReader(new FileReader(
            "DataStreamDemo.java"));
      // 封装目的地
      PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);
     
      String line = null;
      while((line=br.readLine())!=null){
         pw.println(line);
      }
     
      pw.close();
      br.close();
   }

IO流标准输入输出流概述和输出语句的本质:

System类中的两个成员变量:

  Public  static final  InputStream  in  “标准“输入流;

  Public  static final  PrintStream  out  “标准”输出流;

inputStream  is= System.in;

PrintStream ps= System.out;

System.in 标准输入流,是从键盘获取数据的

键盘录入数据:

      A:main方法的args接收参数;

      B:Scanner()

        Scanner  sc = newScanner(System.in);

        String  s = sc.nextLine();

        Int  x= sc.nextInt();

      C:通过字符缓冲流包装标准输入流实现;

 BuffereReader br = new BufferedReader(new InputStreamReader(system.in);

public static void main(String[] args) throwsIOException {
      // //获取标准输入流
      // InputStream is = System.in;
      // //我要一次获取一行行不行呢?
      // //行。
      // //怎么实现呢?
      // //要想实现,首先你得知道一次读取一行数据的方法是哪个呢?
      // //readLine()
      // //而这个方法在哪个类中呢?
      // //BufferedReader
      // //所以,你这次应该创建BufferedReader的对象,但是底层还是的使用标准输入流
      // // BufferedReader br = new BufferedReader(is);
      // //按照我们的推想,现在应该可以了,但是却报错了
      // //原因是:字符缓冲流只能针对字符流操作,而你现在是字节流,所以不能是用?
      // //那么,我还就想使用了,请大家给我一个解决方案?
      // //把字节流转换为字符流,然后在通过字符缓冲流操作
      // InputStreamReader isr = newInputStreamReader(is);
      // BufferedReader br= new BufferedReader(isr);
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 
      System.out.println("请输入一个字符串:");
      String line = br.readLine();
      System.out.println("你输入的字符串是:" + line);
 
      System.out.println("请输入一个整数:");
      // int i = Integer.parseInt(br.readLine());
      line = br.readLine();
      int i = Integer.parseInt(line);
      System.out.println("你输入的整数是:" + i);
   }

随机访问流:

RandomAccessFile类不属于流,是Object类的子类。

但它融合了InputStream和OutputStream的功能。

支持对随机访问文件的读取和写入;

 

 PublicRandAccessFile(String name,String mode)

 第一个参数是文件路径,

第二个参数是操作文件的模式;

private static void read() throws IOException {
      // 创建随机访问流对象
      RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
 
      int i = raf.readInt();
      System.out.println(i);
      // 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。
      System.out.println("当前文件的指针位置是:" + raf.getFilePointer());
 
      char ch = raf.readChar();
      System.out.println(ch);
      System.out.println("当前文件的指针位置是:" + raf.getFilePointer());
 
      String s = raf.readUTF();
      System.out.println(s);
      System.out.println("当前文件的指针位置是:" + raf.getFilePointer());
 
      // 我不想重头开始了,我就要读取a,怎么办呢?
      raf.seek(4);
      ch = raf.readChar();
      System.out.println(ch);
   }
 
   private static void write() throws IOException {
      // 创建随机访问流对象
      RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
 
      // 怎么玩呢?
      raf.writeInt(100);
      raf.writeChar('a');
      raf.writeUTF("中国");
 
      raf.close();
   }
}

合并流:

SequencelnputStream概述:

SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也称为合并流;

SequenceInputStream的构造方法:

SenquenceInputStream(InputStream  s1 , InputStream  s2)

SequenceInputStream(Enumeration <? ExtendsInputStream>e)

1.txt + b.txt = c.txt;

 InputStream s1 = new FileInputStream("a.txt");
   InputStream s2 = new FileInputStream("b.txt");
   SequenceInputStream sins = new  SequenceInputStream(s1,s2);
   BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("c.txt"));
   //如何读写
   byte[]  buy = new byte[1024];
   int len = 0;
   while((len = sins.read(buy))!= -1 ){
       bos.write(buy,0 ,len);
   }
   bos.close();
   sins.close();  
}

合并流读取多个文件的内容复制到一个文件中;

SequenceInputStream (Enumeration  e)

通过简单的回顾我们知道了Enumeration是 Vector中的一个方法的返回值类型;

Enumeration<E>  elements()

Vector<InputStream>  v = new Vector<InputStream>();
  InputStream s1 = new FileInputStream("a.txt");
  InputStream s2 = new FileInputStream("b.txt");
  InputStream s3 = new FileInputStream("c.txt");
  v.add(s1);
  v.add(s2);
  v.add(s3);
  Enumeration<InputStream>          en =v.elements();
   SequenceInputStream sins = new SequenceInputStream(en);
   BufferedOutputStream bos= new BufferedOutputStream(new FileOutputStream("c.txt"));
   //读写文件件;
   byte[]  bys = new byte[1024];
   int len = 0;
   while((len= sins.read(bys)) != -1){
      bos.write(bys,0 ,len);
   }
 
   bos.close();
   sins.close();     
   }

序列化流:

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象——流数据(ObjectOutputStream)

反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据———(ObjectInputStream)

 

Public final void writeObject(Object  obj);

 

NotSerializableException没有序列化接口接口;

 

类通过实现java.io.Serializable 接口以启动其序列化功能,未实现此接口的类将无法使其任何状态序列化或反序列化;

该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口;

 

public static void main(String[] args) throws IOException,ClassNotFoundException {
   //由于我们要对对象进行序列化,所以我们先定义一个类
   //序列化数据其实就是把对象写到文本文件;
write();
read();
   }
   private static void read() throws IOException, ClassNotFoundException {
      // TODOAuto-generated method stub
   //创建反序列化对象
ObjectInputStreamois = new ObjectInputStream(new FileInputStream("oos.txt"));
   //还原对象;
   Object obj=ois.readObject();
   //释放资源
   ois.close();
   System.out.println(obj);
     
     
   }
   private static void write() throws IOException {
      // TODOAuto-generated method stub
   ObjectOutput oos =  new  ObjectOutputStream(new FileOutputStream("oos.txt"));
  
   //创建对象
   person p = new person("dephi",25);
   oos.writeObject(p);
   //释放资源;
   oos.close();
  
  
   }
 
 
类的序列化:
NotSerializableException:未序列化异常
 *
 * 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
 * 该接口居然没有任何方法,类似于这种没有方法的接口被称为标记接口。
 *
 * java.io.InvalidClassException:
 * cn.itcast_07.Person; local classincompatible:
 * stream classdesc serialVersionUID =-2071565876962058344,
 * local class serialVersionUID = -8345153069362641443
 *
 * 为什么会有问题呢?
 *    Person类实现了序列化接口,那么它本身也应该有一个标记值。
 *    这个标记值假设是100。
 *    开始的时候:
 *    Person.class-- id=100
 *    wirte数据: oos.txt -- id=100
 *    read数据: oos.txt -- id=100
 *
 *    现在:
 *    Person.class-- id=200
 *    wirte数据: oos.txt -- id=100
 *    read数据: oos.txt -- id=100
 * 我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。怎么办呢?
 * 回想一下原因是因为它们的id值不匹配。
 * 每次修改java文件的内容的时候,class文件的id值都会发生改变。
 * 而读取文件的时候,会和class文件中的id值进行匹配。所以,就会出问题。
 * 但是呢,如果我有办法,让这个id值在java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗?
 * 不会。现在的关键是我如何能够知道这个id值如何表示的呢?
 * 不用担心,你不用记住,也没关系,点击鼠标即可。
 * 你难道没有看到黄色警告线吗?
 *
 * 我们要知道的是:
 *    看到类实现了序列化接口的时候,要想解决黄色警告线问题,就可以自动产生一个序列化id值。
 *    而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。
 *
 * 注意:
 *    我一个类中可能有很多的成员变量,有些我不想进行序列化。请问该怎么办呢?
 *    使用transient关键字声明不需要序列化的成员变量
 */
public class Person implements Serializable {
   private static final long serialVersionUID = -2071565876962058344L;
 
   private String name;
 
   // private int age;
 
   private transient int age;
 
   // int age;
 
   public Person() {
      super();
   }
 
   public Person(String name, int age) {
      super();
      this.name = name;
      this.age = age;
   }
 
   public String getName() {
      return name;
   }
 
   public void setName(String name) {
      this.name = name;
   }
 
   public int getAge() {
      return age;
   }
 
   public void setAge(int age) {
      this.age = age;
   }
 
   @Override
   public String toString() {
      return "Person [name=" + name + ",age=" + age + "]";
   }
}

Properties集合

Properties概述:

Properties属性集合类,是一个可以和IO流相结合的使用的集合类。

Properties可以保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串;

是Hashtable子类,说明是一个Map集合;

Propertiesprop = new Properties();
   //添加元素;
  
   prop.put("001" , "hello"); 
   prop.put("002", "world");  
    prop.put("003", "java");
    //遍历集合
    Set<Object> set = prop.keySet();
    for(Object key : set){
       Objectvalue = prop.get(key);
       System.out.println(key + "----"+ value);
    }   
   }
}

Properties的特殊功能使用:

特殊功能:

publicObject setProperty(String key,String value):添加元素

publicString getProperty(String key):获取元素

publicSet<String> stringPropertyNames():获取所有的键的集合

 

   

   // 创建集合对象
      Properties prop = new Properties();
 
      // 添加元素
      prop.setProperty("张三", "30");
      prop.setProperty("李四", "40");
      prop.setProperty("王五", "50");
 
      // public Set<String> stringPropertyNames():获取所有的键的集合
      Set<String> set =prop.stringPropertyNames();
      for (String key : set) {
         String value = prop.getProperty(key);
         System.out.println(key + "---" + value);
      }
   }
 

Properties和IO流的结合使用:

这里的集合必须是Properties集合;

Public void  load(Reader reader):把文件中的数据读取到集合中

Public void  store(Writer writer,  String comments) ;把集合中的数据存储到文件

 

  

 private static void myStore() throws IOException {
      //创建集合对象
   Properties prop = new Properties();
   prop.setProperty("刘洋", "23");
   prop.setProperty("刘明宇", "20");
   prop.setProperty("江代欣", "22");
  
   Writer w = new FileWriter("me.txt");
   prop.store(w, "hellworld");
   w.close();  
   }

 private static void myload() throws IOException {
      // TODOAuto-generated method stub
      Properties prop = new Properties();
      Reader r = new FileReader("oos.txt");
      prop.load(r);
      r.close();
      System.out.println("prop"+ prop);
        
   }

案例:判断文件中是否有指定的键如果有就修改值得案列:

 Properties prop = new Properties();
   Reader r = new FileReader("me.txt");
 
   prop.load(r);
   r.close();
   //遍历集合
//Set<String>set = prop.stringPropertyNames();  拿到所有的键
     Set<Object>  st= prop.keySet();
     for(Object obj : st){
        String s = (String) obj;
        if("刘明宇".equals(s)){
           prop.setProperty(s, "2525");
           break;
        }
     } 
     //把集合中的数据重新存储到文件中
     Writer w= new FileWriter("me.txt");
     prop.store(w, "九月");  
     w.close();
}

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值