IO概念
 可以将这种数据传输操作,看做一种数据的流动 , 按照流动的方向分为输入Input和输出Output
 Java中的IO操作主要指的是 java.io包下的一些常用类的使用. 通过这些常用类对数据进行读取(输入Input) 和 写出(输出Output)
IO分类
1.按流的方向来分:输入流和输出流
2.按流动的数据类型:字符流和字节流
注:一切皆字节:
      计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的.
      在数据传输时 也都是以二进制的形式存储的.
      后续学习的任何流 , 在传输时底层都是二进制.
字节:计量存储容量的一种计量单位
Class File
File概念:
文件和目录路径名的抽象表示。
创建文件
[File](#%3Cinit%3E(java.lang.String))([String](../lang/String.html) pathname) | 
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 | 
 | 
boolean | 
[createNewFile](#createNewFile())() | 
当且仅当具有此名称的文件尚不存在时,以原子方式创建由此抽象路径名命名的新空文件。 | 
 | 
ublic class Demo1 {    public static void main(String[] args) throws IOException {        File hh = new File("D://A.txt");         hh.createNewFile();//在D盘创建一个A.txt文件,如果指定的文件不存在且已成功创建返回ture; 如果指定的文件已存在返回false    }}
创建文件夹
boolean | 
[mkdir](#mkdir())() | 
创建此抽象路径名指定的目录。 | 
 | 
public class Demo1 {
    public static void main(String[] args) throws IOException {
        File hh = new File("D://A");
         hh.mkdir();//在d盘创建一个A文件夹
    }
}
创建文件夹时在文件夹中创建文件
| 构造器 | 
描述 | 
[File](#%3Cinit%3E(java.io.File,java.lang.String))([File](File.html) parent, [String](../lang/String.html) child) | 
从父抽象路径名和子路径名字符串创建新的 File实例。 | 
[File](#%3Cinit%3E(java.lang.String,java.lang.String))([String](../lang/String.html) parent, [String](../lang/String.html) child) | 
从父路径名字符串和子路径名字符串创建新的 File实例。 | 
public class Demo1 {
    public static void main(String[] args) throws IOException {
        File hh = new File("D:/A");
        File a = new File(hh,"a.txt" );//D盘创建一个文件夹A在文件夹里创建一个a.txt文件
        a.createNewFile();
        File b = new File("D:/A","B.txt");//D盘创建一个文件夹A在文件夹里创建一个B.txt文件
        b.createNewFile();
    }
}
字段汇总字段
| 变量和类型 | 
字段 | 
描述 | 
static [String](../lang/String.html) | 
[pathSeparator](#pathSeparator) | 
与系统相关的路径分隔符,为方便起见,表示为字符串。 | 
static char | 
[pathSeparatorChar](#pathSeparatorChar) | 
与系统相关的路径分隔符。 | 
static [String](../lang/String.html) | 
[separator](#separator) | 
系统相关的默认名称分隔符,为方便起见,表示为字符串。 | 
static char | 
[separatorChar](#separatorChar) | 
系统相关的默认名称分隔符。 | 
文件遍历
public class Demo2 {
    public static void main(String[] args) {
        File d = new File("D:\\");
        File[] files = e.listFiles();
        listFile(files);
    }
    public static void listFile(File[] files){
        if(files!=null&&files.length>0){
            for (File file:files) {
                if(file.isFile()){//判断是否是文件
                    if(file.getName().endsWith(".avi")){//判断是否是.avi的文件
                        if(file.length()>100*1024*1024)//大于100mb
                            System.out.println("找到了一个avi文件"+file.getAbsolutePath());
                    }
                }else {
                    File[] files2 = file.listFiles();
                    listFile(files2);
                }
            }
        }
    }
文件过滤器FileFilter
| 变量和类型 | 
方法 | 
描述 | 
boolean | 
[accept](#accept(java.io.File))([File](File.html) pathname) | 
测试指定的抽象路径名是否应包含在路径名列表中。 | 
相对路径和绝对路径
  相对路径:以盘符开始   例如c://a.txt
   绝对路径:java中是相对于项目目录路径    例如  a.txt
public class Demo2 {
    public static void main(String[] args) {
        //相对路径:以盘符开始   例如c://a.txt
        //绝对路径:java中是相对于项目目录路径    例如  a.txt
        File file1 = new File("c://a.txt");
        File file2 = new File("a.txt");
        System.out.println("File1的路径"+file1.getAbsolutePath());
        System.out.println("File2的路径"+file2.getAbsolutePath());
    }
}
字节的输出流OutputStream
概念:
- 此抽象类是表示输出字节流的所有类的超类。 输出流接受输出字节并将它们发送到某个接收器。 
需要定义OutputStream的子类的应用程序必须始终至少提供一个写入一个输出字节的方法。
方法摘要
| 变量和类型 | 方法 | 描述 |
| —- | —- | —- |
| void | [close](#close())() | 关闭此输出流并释放与此流关联的所有系统资源。  |
| void | [flush](#flush())() | 刷新此输出流并强制写出任何缓冲的输出字节。  |
| static [OutputStream](OutputStream.html) | [nullOutputStream](#nullOutputStream())() | 返回一个新的 OutputStream ,它丢弃所有字节。  |
| void | [write](#write(byte%5B%5D))(byte[] b) | 将 b.length字节从指定的字节数组写入此输出流。  |
| void | [write](#write(byte%5B%5D,int,int))(byte[] b, int off,  int len) | 将从偏移量 off开始的指定字节数组中的 len字节写入此输出流。  |
| abstract void | [write](#write(int))(int b) | 将指定的字节写入此输出流。  | 
FileOutputStream
概念:
文件输出流是用于将数据写入File或FileDescriptor的输出流。 文件是否可用或是否可以创建取决于底层平台。 特别是某些平台允许一次仅打开一个文件以供写入FileOutputStream (或其他文件写入对象)。 在这种情况下,如果涉及的文件已经打开,则此类中的构造函数将失败。
public class Demo3 {
  public static void main(String[] args) throws IOException {
      FileOutputStream fos = new FileOutputStream("d:/a.txt",true);//加true表示表示不会清空以前写的内容
//        fos.write(65);写出一个字节
      byte[] a = {35,66,67};
      fos.write(a);//写出一串数组
      fos.close();
      System.out.println("已经写出");
      //a,txt文件结果 :A#BC
  }
}
InputStream
概念:
此抽象类是表示输入字节流的所有类的超类。 
需要定义子类InputStream应用程序必须始终提供返回输入的下一个字节的方法。
方法摘要
| 变量和类型 | 
方法 | 
描述 | 
int | 
[available](#available())() | 
返回可以从此输入流中无阻塞地读取(或跳过)的字节数的估计值,可以是0,或者在检测到流结束时为0。 | 
void | 
[close](#close())() | 
关闭此输入流并释放与该流关联的所有系统资源。 | 
void | 
[mark](#mark(int))(int readlimit) | 
标记此输入流中的当前位置。 | 
boolean | 
[markSupported](#markSupported())() | 
测试此输入流是否支持 mark和 reset方法。 | 
static [InputStream](InputStream.html) | 
[nullInputStream](#nullInputStream())() | 
返回一个不读取任何字节的新 InputStream 。 | 
abstract int | 
[read](#read())() | 
从输入流中读取下一个数据字节。 | 
int | 
[read](#read(byte%5B%5D))(byte[] b) | 
从输入流中读取一些字节数并将它们存储到缓冲区数组 b 。 | 
int | 
[read](#read(byte%5B%5D,int,int))(byte[] b, int off,  int len) | 
从输入流 len最多 len字节的数据读入一个字节数组。 | 
byte[] | 
[readAllBytes](#readAllBytes())() | 
从输入流中读取所有剩余字节。 | 
int | 
[readNBytes](#readNBytes(byte%5B%5D,int,int))(byte[] b, int off,  int len) | 
从输入流中读取请求的字节数到给定的字节数组中。 | 
byte[] | 
[readNBytes](#readNBytes(int))(int len) | 
从输入流中读取指定的字节数。 | 
void | 
[reset](#reset())() | 
将此流重新定位到上次在此输入流上调用 mark方法时的位置。 | 
long | 
[skip](#skip(long))(long n) | 
跳过并丢弃此输入流中的 n字节数据。 | 
long | 
[transferTo](#transferTo(java.io.OutputStream))([OutputStream](OutputStream.html) out) | 
从该输入流中读取所有字节,并按读取顺序将字节写入给定的输出流。 | 
 
FileInputStream
概念:
构造方法
| 构造器 | 
描述 | 
[FileInputStream](#%3Cinit%3E(java.io.File))([File](File.html) file) | 
通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File对象 file命名。 | 
[FileInputStream](#%3Cinit%3E(java.io.FileDescriptor))([FileDescriptor](FileDescriptor.html) fdObj) | 
使用文件描述符 fdObj创建 FileInputStream  ,该文件描述符表示与文件系统中实际文件的现有连接。 | 
[FileInputStream](#%3Cinit%3E(java.lang.String))([String](../lang/String.html) name) | 
通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name命名。 | 
ublic class Demo4 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("d:/a.txt");
//        while(true){//通过循环读取所有字节
//            byte a = (byte) fis.read();
//            if(a == -1){//当a=-1时表示已经读完了因为read()方法没有读取由于到文件末尾而没有更多数据返回-1
//                break;
//            }
//            System.out.println(a);
//        }
        byte[] bytes = new byte[10];
        int len = fis.read(bytes);//防止读取的数据没有数组长而输出空格
        System.out.println(new String(bytes,0,len));
        len = fis.read(bytes);//防止读取的数据没有数组长而输出0
        System.out.println(len);//当要循环输出时可以通过lne==-1结束循环
        fis.close();
    }
}
加密解密文件代码
通过对一个文件反复异或来完成
public class Demo5 {
    public static void main(String[] args) throws  IOException {
        System.out.println("请输入文件的全路径");
        Scanner scanner = new Scanner(System.in);
        String filename = scanner.nextLine();
        //原文件
        File oldFile = new File(filename);
        //加密文件    加前缀mi-
        File newFile = new File(oldFile.getParent(),"mi-"+oldFile.getName());
        FileInputStream fis = new FileInputStream(oldFile);
        FileOutputStream fos = new FileOutputStream(newFile);
        while (true){
            int b = fis.read();
            if(b==-1){
                break;
            }
            //任何数据^10两次  结果还是其本身   加密解密过程
            fos.write(b^10);
        }
        System.out.println("加密或解密完成");
    }
}
字符码编码
UTF-8
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式。其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示)和 UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8 是 Unicode 的实现方式之一。
UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
字节流小结
当要对文字操作时选择字符流,为防止读半个文字
 
字符输出Writer
概念:
- 用于写入字符流的抽象类。 子类必须实现的唯一方法是write(char  [],int,int),flush()和close()。 但是,大多数子类将覆盖此处定义的一些方法,以提供更高的效率,附加功能或两者兼而有之。
| 变量和类型 | 字段 | 描述 |
| —- | —- | —- |
| protected [Object](../lang/Object.html) | [lock](#lock) | 用于同步此流上的操作的对象。  | 
构造方法
| 变量 | 
构造器 | 
描述 | 
protected | 
[Writer](#%3Cinit%3E())() | 
创建一个新的字符流编写器,其关键部分将在编写器本身上同步。 | 
protected | 
[Writer](#%3Cinit%3E(java.lang.Object))([Object](../lang/Object.html) lock) | 
创建一个新的字符流编写器,其关键部分将在给定对象上同步。 | 
 
 
方法摘要
 
| 变量和类型 | 
方法 | 
描述 | 
[Writer](Writer.html) | 
[append](#append(char))(char c) | 
将指定的字符追加到此writer。 | 
[Writer](Writer.html) | 
[append](#append(java.lang.CharSequence))([CharSequence](../lang/CharSequence.html) csq) | 
将指定的字符序列追加到此writer。 | 
[Writer](Writer.html) | 
[append](#append(java.lang.CharSequence,int,int))([CharSequence](../lang/CharSequence.html) csq, int start,  int end) | 
将指定字符序列的子序列追加到此writer。 | 
abstract void | 
[close](#close())() | 
关闭流,先冲洗它。 | 
abstract void | 
[flush](#flush())() | 
刷新流。 | 
static [Writer](Writer.html) | 
[nullWriter](#nullWriter())() | 
返回一个新的 Writer ,它丢弃所有字符。 | 
void | 
[write](#write(char%5B%5D))(char[] cbuf) | 
写一个字符数组。 | 
abstract void | 
[write](#write(char%5B%5D,int,int))(char[] cbuf, int off,  int len) | 
写一个字符数组的一部分。 | 
void | 
[write](#write(int))(int c) | 
写一个字符。 | 
void | 
[write](#write(java.lang.String))([String](../lang/String.html) str) | 
写一个字符串。 | 
void | 
[write](#write(java.lang.String,int,int))([String](../lang/String.html) str, int off,  int len) | 
写一个字符串的一部分。 | 
FileWriter
- 使用默认缓冲区大小将文本写入字符文件
构造方法
| 构造器 | 描述 |
| —- | —- |
| [FileWriter](#%3Cinit%3E(java.io.File))([File](File.html) file) | 给 File写一个 FileWriter ,使用平台的 default charset) |
| [FileWriter](#%3Cinit%3E(java.io.FileDescriptor))([FileDescriptor](FileDescriptor.html) fd) | 构造一个 FileWriter给出的文件描述符,使用该平台的 default charset) 。  |
| [FileWriter](#%3Cinit%3E(java.io.File,boolean))([File](File.html) file,  boolean append) | 在给出要写入的 FileWriter下构造 File ,并使用平台的 default  charset构造)一个布尔值,指示是否附加写入的数据。  |
| [FileWriter](#%3Cinit%3E(java.io.File,java.nio.charset.Charset))([File](File.html) file, [Charset](../nio/charset/Charset.html) charset) | 构造一个FileWriter给予File编写和charset  。 |
| [FileWriter](#%3Cinit%3E(java.io.File,java.nio.charset.Charset,boolean))([File](File.html) file, [Charset](../nio/charset/Charset.html) charset,  boolean append) | 构造FileWriter给出File写入, charset和一个布尔值,指示是否附加写入的数据。 |
| [FileWriter](#%3Cinit%3E(java.lang.String))([String](../lang/String.html) fileName) | 构造一个 FileWriter给出文件名,使用平台的 default charset) |
| [FileWriter](#%3Cinit%3E(java.lang.String,boolean))([String](../lang/String.html) fileName,  boolean append) | 使用平台的 default charset)构造一个 FileWriter给定一个文件名和一个布尔值,指示是否附加写入的数据。  |
| [FileWriter](#%3Cinit%3E(java.lang.String,java.nio.charset.Charset))([String](../lang/String.html) fileName, [Charset](../nio/charset/Charset.html) charset) | 构造一个FileWriter给出文件名和charset  。 |
| [FileWriter](#%3Cinit%3E(java.lang.String,java.nio.charset.Charset,boolean))([String](../lang/String.html) fileName, [Charset](../nio/charset/Charset.html) charset,  boolean append) | 构造一个FileWriter给定一个文件名, charset和一个布尔值,指示是否附加写入的数据。 | 
public class Demo6 {
    public static void main(String[] args) throws IOException {
        FileWriter fw = new FileWriter("b.txt",true);
        fw.write("有一个");
        fw.append("啥的").append(",").append("撒大大");//追加输出
        fw.close();
    }
}
字符读取Reader
- 用于读取字符流的抽象类。子类必须实现的唯一方法是read(char [],int,int)和close()。
 
构造方法
| 变量 | 
构造器 | 
描述 | 
protected | 
[Reader](#%3Cinit%3E())() | 
创建一个新的字符流阅读器,其关键部分将在阅读器本身上同步。 | 
protected | 
[Reader](#%3Cinit%3E(java.lang.Object))([Object](../lang/Object.html) lock) | 
创建一个新的字符流阅读器,其关键部分将在给定对象上同步。 | 
public class Demo7 {
    public static void main(String[] args) throws IOException {
          FileReader fr = new FileReader("b.txt");
//        while (true){//通过循环逐个输入字符
//            int c = fr.read();
//            if(c == -1){
//                break;
//            }
//            System.out.println((char) c);
//        }
//        fr.close();
        char[] a = new char[100];//通过数组输入
        int len = fr.read(a);//为防止读取的数据没有数组长而输出0
        String text = new String(a,0,len);
        System.out.println(text);
        System.out.println(len);
        //结果:有一个有一个有一个有一个有一个有一个有一个有一个有一个有一个啥的,撒大大
        //36
    }
刷新flush
当字符流输出多次时如在循环内输入时需要flush强制把缓存的字符存到文件中。close调用时也是刷新一次。
字节转换为字符流
public class Demo8 {
    public static void main(String[] args) throws IOException {//输出
        //字节流‘装饰’为字节流    :使用了装饰者模式
        FileInputStream fis = new FileInputStream("b.txt");
        InputStreamReader isr = new InputStreamReader(fis,"utf-8");
        while (true){
            int a = isr.read();
            if(a == -1){
                break;
            }
            System.out.println((char)a);
        }
        isr.close();
    }
}
public class Demo9 {
    public static void main(String[] args) throws IOException {//输入
        FileOutputStream fos = new FileOutputStream("b.txt",true);
        OutputStreamWriter osw = new OutputStreamWriter(fos);
        osw.write("撒大苏打");
        osw.flush();
        osw.close();
    }
}
 
打印流Print与BufferedReader
public class Demo10 {
    public static void main(String[] args) throws IOException {
        //字符输出(打印流)
//        PrintStream ps = new PrintStream("b.txt");
//        ps.println("就大厦跨境电商");
//        ps.println("就大厦跨境电商");
//        ps.close();
//        PrintWriter pw = new PrintWriter("b.txt");
//        pw.write("按时发放");
//        pw.write("按时发放");
//        pw.flush();
        //转换
//        FileOutputStream fos = new FileOutputStream("b.txt");
//        PrintWriter pw = new PrintWriter(fos);
//        pw.println("ask代码都是");
//        pw.println("ask代码都是");
//        pw.println("ask代码都是");
//        pw.flush();
//缓存读取流,将字符输入流转换为带有缓存的 可以一次读取一行的缓存读取流
        FileReader fileReader = new FileReader("b.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        String text = bufferedReader.readLine();//读到结尾返回null
        System.out.println(text);//读一行
        System.out.println(text); 
    }
收集异常日常
 public static void main(String[] args) throws FileNotFoundException {
        //收集异常信息
        try {
            String s = null;
            s.toString();
        }catch (Exception e){
            PrintWriter pw = new PrintWriter("c://bug.txt");
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            pw.print(format.format(new Date()));
            e.printStackTrace(pw);
            pw.close();
        }
    }
Properties
Properties类表示一组持久的属性。 Properties可以保存到流中或从流中加载。 属性列表中的每个键及其对应的值都是一个字符串。 
属性列表可以包含另一个属性列表作为其“默认值”; 如果在原始属性列表中找不到属性键,则搜索第二个属性列表。
构造方法
| 构造器 | 
描述 | 
[Properties](#%3Cinit%3E())() | 
创建一个没有默认值的空属性列表。 | 
[Properties](#%3Cinit%3E(int))(int initialCapacity) | 
创建一个没有默认值的空属性列表,并且初始大小容纳指定数量的元素,而无需动态调整大小。 | 
[Properties](#%3Cinit%3E(java.util.Properties))([Properties](Properties.html) defaults) | 
创建具有指定默认值的空属性列表。 | 
public class Demo11 {
    public static void main(String[] args) throws IOException {
//        Properties ppt = new Properties();//map集合的子类
//        ppt.put("name" ,"大号");
//        ppt.put("info","没小号好");
//        FileWriter fw = new FileWriter("a.properties");
//        ppt.store(fw,"存储的图书");
//        fw.close();
        Properties ppt = new Properties();
        Reader r = new FileReader("a.properties");
        ppt.load(r);
        System.out.println(ppt.get("name"));
        System.out.println(ppt.get("info"));
        r.close();
    }
}
序列化和反序列化
public class Demo13 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
//        //序列化
//        Book b = new Book("西游记","齐天大圣");
//        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c.txt"));
//        oos.writeObject(b);
//        oos.close();
        //反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c.txt"));
        Book book = (Book) ois.readObject();
        System.out.println(book.getInfo());
    }
    static  class  Book implements Serializable {
        private String name;
        private String info;
        public Book() {
        }
        public Book(String name, String info) {
            this.name = name;
            this.info = info;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getInfo() {
            return info;
        }
        public void setInfo(String info) {
            this.info = info;
        }
        @Override
        public String toString() {
            return "book{" +
                    "name='" + name + '\'' +
                    ", info='" + info + '\'' +
                    '}';
        }
    }
}
try-with-resources
try-with-resources语句也可以像普通的try语句一样,有catch和finally代码块。在try-with-resources语句中,任何的catch和finally代码块都在所有被声明的资源被关闭后执行。
   //jdk9
            FileReader fr = new FileReader("c://book.txt");
            PrintWriter pw = new PrintWriter("c://book.txt");
            try(fr;pw){
                int c = fr.read();
                System.out.println((char)c);
            }catch (IOException e) {
                e.printStackTrace();
            }