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;
                }
                
            });
        }
    }
  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5634798.html
Copyright © 2011-2022 走看看