zoukankan      html  css  js  c++  java
  • JavaSE复习_11 IO流复习

    △FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)
       FileWriter是使用默认码表写出文件, 如果需要使用指定码表写出, 那么可以使用OutputStreamWriter(字节流,编码表)  
    BufferedReader br =                                     //高效的用指定的编(解码)
                    new BufferedReader(new InputStreamReader(new FileInputStream("UTF-8.txt"), "UTF-8"));
            BufferedWriter bw =                                     //高效的用表写(编码)
                    new BufferedWriter(new OutputStreamWriter(new FileOutputStream("GBK.txt"), "GBK"));
            int ch;
            while((ch = br.read()) != -1) {
                bw.write(ch);
            }
    
            br.close();
            bw.close();
    △Java中一个字母占一个字节,char数据类型占两个字节,汉字根据编码不同,UTF-8两个字节,GBK是三个字节.
    △四个附加接口:Closeable,Flushable,Readable,Appendable.
     Closeable扩展了AutoCloseable接口,因此支持带资源的try语句.OutPutStream和Writer实现了Flushable接口,Readable接口只有一个方法:int read(CharBuffer cb),CharBuffer类拥有按顺序随机读写访问的方法.Appendable接口则有两个用于添加单个字符和字符序列的方法.
    Appendable append(char c)
    Appendable append(CharSequence s).
    其中CharSequence接口描述了char值序列的属性,String,CharBuffer,StringBuilder,StringBuffer都实现了它.
    append底层实际上是用write实现的.唯一的区别是append方法可以添加null.而write方法会报异常.一下是append的源码:
    public Writer append(CharSequence csq ) throws IOException {
            if (csq == null)
                write( "null" );
            else
                write( csq .toString());
            return this ;
        }
    △PushedbackInputStream支持可回推操作,例如,当它读取到一个字节的时候,可以将读取到的字节回推,这时候下一个读到的字节即是回推的字节.(支持多次读取,也可以回推字节数组等)
    PushbackInputStream(InputStream in):构建一个可以回推的输入流.
    void unread(int b):回推一个字节,它在下次调用read的时候被再次读取.
    △对于文本输出,可以使用Printriter.这个类拥有以文本格式打印字符串和数字的方法.它甚至还有一个将PrintWriter链接到FileWriter的方法.例如:
      PrintWriter out=new PrintWriter("employee.txt");
      等价于:
      PrintWriter out=new PrintWriter(new FileWriter("employee.txt"));
    可以在PrintWriter的构造器中指定是否自动刷新,如果设置为true,那么在每次调用println方法的时候,都会自动刷新缓冲区. 
    △Scanner hasnextInt()判断接下来的数是否是整数,判断后,在调用nextInt():获取输入的整数,.标准格式如下:
     if(i.hasnextInt()) {
         int x=i.nextInt();
    }
      当nextInt()和nextLine()作组合的时候,nextInt()在前面的时候,nextInt()获取整数后,不会再获取回车符,因此会被nextLine()所获取而得知该行已结束,因此不会再输出其他内容.
      解决方案1:创建两次Scanner对象2.都用nextLine()方法,随后在转换为整数.
    △CharSet:实现了统一的对字符集的转换.可以通过静态的forName方法来获得一个CharSet,只需向这个方法传递一个官方名字:
     Charset cset=Charset.forName("IOS-8859-1");
      利用Charset对象实现编码解码:
      编码:ByteBuffer encode(String str):将给定的字符串编码为字节序列.返回一个字节缓冲区,可以利用字节缓冲区的方法,array()返回这个缓冲区所管理的字节数组.即:
    //演示编码
    String str=...;
    ByteBuffer buffer=cset.encode(str);
    byte[] bytes=buffer.array();//等价于str.getBytes(cset);

    解码:Charset对象也需要通过字节缓冲区来实现解码功能,首先调用ByteBuffer的静态方法wrap将字节数组存入缓冲区,然后调用Charset对象的decode方法解码,返回一个字符缓冲区.再利用字符缓冲区的toString方法返回字符串.

    //演示解码
    byte[] bytes=...;
    ByteBuffer buffer=ByteBuffer.wrap(bytes,offset,length);
    CharBuffer chuf=cset.decode(buffer);
    String str=chuf.toString();
    //相当于new String(byte[] bytes, int offset, int length, Charset charset)
    △对象序列化:每个对象都是有一个序列号保存的.
    •   对于遇到的每一个对象引用都关联一个序列号
    • 对于每一个对象,当第一次遇到的时候,保存其对象数据到流中.
    • 如果某个对象之前已经保存过,只写出与之前保存的序列号为x的对象相同.
       读回对象的时候,整个对象是反过来的:
    • 对于流中的对象,在第一次遇到其序列号时候,构建它,并使用流中的数据初始化,然后记录这个顺序号与新对象之间的关联.
    • 当遇到"与之前保存过的序列号为x的对象相同"标记时获取与这个顺序号相同的对象引用
     对象序列化涉及到的单例问题,当对于一个通过单例产生的对象,调用序列化和反序列化操作的时候,将返回一个新的对象!即:即使构造器是私有的,序列化机制也能产生新的对象.
     为了解决这个问题,需要定义一个readResolve的特殊序列化方法,如果定义了readResolve方法,在对象序列化的时候就会调用它,它必须返回对象,该对象之后会成为readObject的返回值.方法签名为:protected Object readResolve().示例如下:
    import java.io.Serializable;
    
     class Person implements Serializable{
    
         /**
         *
         */
         private static final long serialVersionUID = 1L;
         private String name ;
         private int age ;
         public static Person p = new Person( "xyy",24);
         private Person(String name, int age ) {
              super ();
              this .name = name ;
              this .age = age ;
        }
         public static Person getPerson() {
              return p ;
        }
    
    }
    public class Demo {
         public static void main(String[] args) throws IOException, ClassNotFoundException {
             Person p=Person. p;
             ObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("C:/obj.dat" ));
              oos.writeObject( p);
              oos.close();
              ObjectInputStream ois= new ObjectInputStream( new FileInputStream("C:/obj.dat" ));
             Person p1=(Person) ois.readObject();
             System. out .println(p1 ==p );
              ois.close();
        }
    }

    此时输出为false.破坏了单例模式,解决问题应该在Person类中添加readResolve方法.在Person类添加如下代码,返回true.

    protected Object readResolve() {
              return p ;
        }

    △序列化机制提供了一种用法:提供了一种克隆对象的简便途径,只要对应的类是可序列化的即可,直接将对象序列化到输出流中,然后将其读回,这样产生的对象是原对象的一个深拷贝.可以用ByteArrayOutPutStream保存到字节数组.

    △Java7新特性之Path类和Files类.

     Java7新增了用于操作文件路径的Path类,它封装了文件的路径,并且提供了一系列有关于文件路径的方法,例如resolve(将两个路径组合起来),equals方法,getParent,getRoot,isAbsolute方法.将以前File类对于文件的操作封装至Files类中,Files类中提供了一系列诸如以前File类中操作文件的方法,例如delete,createFile,createDirectory方法.此外,一些获取文件属性的操作,封装到接口BasicFileAttribute接口中,例如creationTime方法,lastModifiedTime方法等.下面列出了一系列可能会很有用的方法:

    //Paths类.用于获取Path对象.
    static Path get(String first,String... more);
    /*获取路径对象.将按照默认文件系统分割符组合,然后解析连接起来的结果,如果不是合法路径,抛出异常*/
    //Path类.封装了一系列的路径操作
    /*
    如果other是绝对路径,返回绝对路径,否则返回this和other连接获得的路径
    */
    Path resolve(Path other);
    /*
    如果other是绝对路径返回other,否则返回连接this父路径和other获得的路径    
    */
    Path resolveSibling(Path other);
    /*
    返回父路径,或者在路径没有父路径的时候,返回null    
    */
    Path getParent();
    /*
    返回该路径的最后一个部件,没有任何部件,返回null
    */
    Path getFileName();
    /*
    从该路径中创建File对象
    */
    File toFile();
    //File对象提供了转化为path对象的方法
    Path toPath();
    //Files类封装了一系列对于文件的操作.包括输入输出流缓冲的读取.
    //把文件的内容转化为字节数组.
    byte[] bytes=Files.readAllBytes(path);
    //希望将文件当作行序列读取,那么可以调用:
    List<String> lines=Files.readAllLines(path,charset);
    //将字节数组写入文件
    Files.write(path,bytes);
    //将行的集合写入到文件中:
    Files.write(path,lines);
    //获取指定文件的输入流和输出流
    InputStream in=Files.newInputStream(path);
    OutputStream out=Files.newOutputStream(path);
    //获取指定编码的BufferedReader和指定解码的BufferedWriter
    Reader in=Files.newBufferedReader(path,charset);
    Writer out=Files.newBufferedWriter(path,charset);
    //将一个文件复制或移动(复制并删除)到给定位置.可以代替重命名操作.
    static Path copy(Path from,Path to,CopyOption... options);
    static Path move(Path from,Path to,CopyOption... options);
    //删除给定文件或空目录
    static void delete(Path path);
    static void deleteIfExits(Path path);
    //创建目录(与mkdir,mkdirs一样)
    static Path createFile(Path path,FileAttribute... attrs);
    static Path createDirectory(Path path,FileAttribute... attrs);
    static Path createDirectorys(Path path,FileAttribute... attrs);
    //获取文件信息(一部分信息封装在BasicAttributes接口)
    static boolean exits(Path path);    //是否存在
    static boolean isHidden(Path path);    //是否隐藏
    static boolean isRegularFile(Path path);    //是否是文件
    static boolean isDirevtory(Path path);     //是否是文件夹
    static long size(Path path);    //获取文件按字节度量的尺寸.
    //通过如下操作,获取文件属性对象
    PosixFileAttribute attributes=Files.readAttributes(path,BasicFileAttributes.class);
    //BasicFileAttributes接口提供一系列属性信息
    FileTime creationTime();   //创建时间
    FileTime lastModifiedTime();       //最迟修改的时间

    Files类提供了一个可以产生Iterable对象,代替list方法.下面代码说明如何使用:

    try(DirectoryStream<Path> entries=Files.newDirectoryStream(dir))
    {
           for(Path entry:entries)
               //Process entries    
    }

    可以在方法中指定模式来过滤文件:

    try(DirectoryStream<Path> entries=Files.newDirectoryStream(dir,"*.txt"))
      模式                           描述                                           示例
    * 匹配路径组成部分的0个或多个字符 *.java匹配当前目录所有Java文件
    ** 匹配跨目录边界的0个或多个字符 **.java 匹配在所有子目录中的Java文件
    ? 匹配一个字符 ????.java匹配所有四个字符的Java文件
    {...} 匹配由逗号隔开的多个可选项之一 *.{java,class}匹配所有的Java文件和类class文件
    转义上述任意模式的字符 *,转义*

    Files提供了一种我认为非常便捷的访问子孙成员的方法,walkFileTree方法,省去了原先需要进行的遍历操作.向其传递一个FileVistor对象.(一般传入便捷类SimpleFileVistor对象,但是其除FileVisited方法之外所有的操作都不做任何处理继续访问,而visitFileFailed方法会抛出异常终止访问,因此一般需要覆盖visitFileFailed方法,防止遇到无法打开的文件暂停访问,其余方法是否覆盖根据需求.下面是遍历一个路径下的所有子孙文件的操作,大大增加了遍历文件的简洁性:

    import java.io.IOException;
    import java.nio.file.FileVisitResult;
    import java.nio.file.FileVisitor;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.SimpleFileVisitor;
    import java.nio.file.attribute.BasicFileAttributes;
    
    public class Demo {
        public static void main(String[] args) throws IOException  {
            Path path=Paths.get("C:\","pictures");
            printFile(path);
        }
        public static void printFile(Path path) throws IOException {
            Files.walkFileTree(path,new SimpleFileVisitor<Path>() {
                //在一个目录被处理前执行的操作
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    System.out.println(dir+"目录将被处理");
                    return FileVisitResult.CONTINUE;
                }
                //遇见一个文件的时候执行的操作
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    System.out.println("访问"+file+"文件");
                    return FileVisitResult.CONTINUE;
                }
                //访问文件失败的时候执行的操作
                public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                    return FileVisitResult.CONTINUE;
                }
                //一个目录被处理后执行的操作
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    System.out.println(dir+"被处理");
                    return FileVisitResult.CONTINUE;
                }
                
            });
        }
    }
  • 相关阅读:
    剑指offer4:重建二叉树(后序遍历)
    剑指offer3:从尾到头打印链表每个节点的值
    剑指offer2:C++实现的替换空格(字符中的空格替换为“%20”)
    tp5系统变量输出(可以用来传递搜索的参数)
    Ajax实现文件上传的临时垃圾文件回收策略
    php获取当天的开始时间和结束时间
    Think PHP递归获取所有的子分类的ID (删除当前及子分类)
    tp查找某字段,排除某字段,不用一次写那么多
    git-查看历史版本及回滚版本
    dedecms目录结构,非常全
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5634798.html
Copyright © 2011-2022 走看看