zoukankan      html  css  js  c++  java
  • Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)

      18天-06-IO流
      字节流和字符流

     
      字节流两个基类
    InputStream,FileInputStream,BufferedInputStream
    OutputStream,FileOutputStream,BufferedOutputStream
    PrintStream (打印字节流,带编码格式)
      字符流两个基类
    Reader,FileReader,BufferedReader,InputStreamReader(字节流转换为字符流读取,带编码格式)
    Writer,FileWriter,BufferedWriter,OutputStreamWriter(字节流转换为字符流写入,带编码格式)
    PrintWriter (打印字符流,带编码格式)
    流操作规律讲解
    源设备:   键盘 System.in;    硬盘 FileStream;      内存 ArrayStream;
    目的设备:  控制台 System.out;   硬盘 FileStream;     内存 ArrayStream;

    字符流:(只能用于文本文件)
    操作FileWriter写入文件
    1.创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。而且该文件会被创建到指定目录下。如果该目录下已经有同名文件,将被覆盖。其实该步骤就是在明确数据要存放的目的地。
    FileWriter fw=new FileWriter("filePath",true);  //ture代表不覆盖已有文件,并在已有文件末尾添加数据
    2.调用write()方法,将字符串写入到流中。
    3.刷新流对象中缓冲的数据到文件里。
    4.关闭流资源。在关闭流前,会刷新一次内部缓冲区的数据。

    操作FileReader读取文件
    1.创建一个文件读取流对象,和指定名称的文件。要保证该文件是已经存在,如果不存在,会发生FileNotFoundException异常。 FileReader fr=new FileReader(FilePath);
    2.调用读取流对象的read方法。read();一次读取一个字符,而且会自动往下读取。
    第二种通过字符数组进行读取。
    定义一个数组,用于存储读取到的字符,读取read(char[])返回的是读取到的字符个数。

    复制的原理:其实就是将一个地方的文件数据存储到另外一个指定的地方。

    字符流拷贝文件示例:

     1 /**
     2 * 拷贝文件
     3 *
     4 * @param sourceFile 源文件路径
     5 * @param targetFile 目标文件路径
     6 */
     7 public static void copyFile(String sourceFile, String targetFile)
     8 {
     9     FileReader fr = null;   //读文件
    10     FileWriter fw = null;   //写文件
    11     try
    12     {
    13         fr = new FileReader(sourceFile);
    14         fw = new FileWriter(targetFile);
    15 
    16         char[] temp = new char[1024];
    17         int length = 0;
    18         while ((length = fr.read(temp)) != -1)
    19         {
    20             //length是每次读取文件时返回已读取的字符数量,-1为文件读取完毕
    21             fw.write(temp, 0, length);
    22         }
    23     }
    24     catch (IOException e)
    25     {
    26         e.printStackTrace();
    27     }
    28     finally
    29     {
    30         try
    31         {
    32             if (fr != null)
    33             {
    34                 fr.close();
    35             }
    36         }
    37         catch (IOException e)
    38         {
    39             e.printStackTrace();
    40         }
    41         try
    42         {
    43             if (fw != null)
    44             {
    45                 fw.close();
    46             }
    47         }
    48         catch (IOException e)
    49         {
    50             e.printStackTrace();
    51         }
    52     }
    53 }
    字符流拷贝文件

      缓冲区 BufferedWriter,BufferedReader

      缓冲区的出现是为了提高流的操作效率。所以在创建缓冲区之前,必须要先有流对象。
    1.创建流对象(FileReader,FileWriter);
    2.将需要提高效率的流对象作为参数传递给缓冲区的构造函数即可;
    3.读写数据,并即时刷新缓冲区数据;
    4.关闭缓冲区,流对象,缓冲区关闭时会检测一下数据是否写完,所以要后关闭流对象。

    字符读取流缓冲区:该缓冲区提供了一个一次读一行的方法readLine(),当返回null时,表示读取到文件末尾
    readLine方法返回的时候只返回回车符之前的数据内容,并不返回包含回车符
    readLine原理:无论是读一行还是读取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是read()方法一次读一个。
    缓冲区提供了一个跨平台的换行符:newLine();

    缓冲区拷贝文件示例:

     1 /**
     2 * 缓冲区拷贝文件
     3 *
     4 * @param sourceFile 源文件路径
     5 * @param targetFile 目标文件路径
     6 */
     7 public static void copeFileByBuffer(String sourceFile, String targetFile)
     8 {
     9     BufferedReader bufr = null;
    10     BufferedWriter bufw = null;
    11     try
    12     {
    13         bufr = new BufferedReader(new FileReader(sourceFile));
    14         bufw = new BufferedWriter(new FileWriter(targetFile));
    15         String temp = null;
    16         while ((temp = bufr.readLine()) != null)
    17         {
    18             bufw.write(temp);
    19             bufw.newLine();
    20             bufw.flush();
    21         }
    22     }
    23     catch (FileNotFoundException e)
    24     {
    25         e.printStackTrace();
    26     }
    27     catch (IOException e)
    28     {
    29         e.printStackTrace();
    30     }
    31     finally
    32     {
    33         try
    34         {
    35             if (bufr != null)
    36             {
    37                 bufr.close();
    38             }
    39         }
    40         catch (IOException e)
    41         {
    42             e.printStackTrace();
    43         }
    44         try
    45         {
    46             if (bufw != null)
    47             {
    48                 bufw.close();
    49             }
    50         }
    51         catch (IOException e)
    52         {
    53             e.printStackTrace();
    54         }
    55     }
    56 }
    缓冲区拷贝文件

      装饰设计模式:当想要对已有的对象进行功能增强时,可以定义类将已有对象传入,基于已有的功能,并提供增强功能。那么自定义的该类称为装饰类。

    装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能
    装饰类因为增强了已有的对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常是都属于一个体系中的。
    装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类与类之间的关系

      字节流:
    int read():读取时返回int类型,会把byte字节提升为int类型,提升方式是byte&0xff,在写入时也做了反向操作强转为byte类型。防止类型提升导致原本不是 -1 的数据在类型提升后变成 -1。

    字节流复制文件示例:

     1 /**
     2 * 字节流方式拷贝文件
     3 *
     4 * @param sourceFile 源文件路径
     5 * @param targetFile 目标文件路径
     6 */
     7 public static void copyFileByByte(String sourceFile, String targetFile)
     8 {
     9     BufferedInputStream bfis = null;
    10     BufferedOutputStream bfos = null;
    11     try
    12     {
    13         bfis = new BufferedInputStream(new FileInputStream(sourceFile));
    14         bfos = new BufferedOutputStream(new FileOutputStream(targetFile));
    15         byte[] temp = new byte[1024*1024];
    16         int length;
    17         while ((length = bfis.read(temp)) != -1)
    18         {
    19             bfos.write(temp, 0, length);
    20         }
    21     }
    22     catch (FileNotFoundException e)
    23     {
    24         e.printStackTrace();
    25     }
    26     catch (IOException e)
    27     {
    28         e.printStackTrace();
    29     }
    30     finally
    31     {
    32         try
    33         {
    34             if (bfis != null)
    35             {
    36                 bfis.close();
    37             }
    38         }
    39         catch (IOException e)
    40         {
    41             e.printStackTrace();
    42         }
    43         try
    44         {
    45             if (bfos != null)
    46             {
    47                 bfos.close();
    48             }
    49         }
    50         catch (IOException e)
    51         {
    52             e.printStackTrace();
    53         }
    54     }
    55 }
    字节流方式拷贝文件

      19天-15-IO流读取键盘录入

    System.out:  对应的是标准输出设备,控制台。
    System.in:    对应的标准输入设备,键盘。

    流操作键盘录入示例:

     1 /**
     2  * 键盘录入,over表示结束
     3  */
     4 public static void keyboardEntry() throws IOException
     5 {
     6     BufferedReader br = null;
     7     BufferedWriter bw = null;
     8     try
     9     {
    10         br = new BufferedReader(new InputStreamReader(System.in));
    11         bw = new BufferedWriter(new OutputStreamWriter(System.out));
    12         String temp;
    13         while ((temp = br.readLine()) != null)
    14         {
    15             if ("over".equals(temp))
    16             {
    17                 break;
    18             }
    19             bw.write(temp);
    20             bw.newLine();
    21             bw.flush();
    22         }
    23     }
    24     finally
    25     {
    26         if (br != null)
    27         {
    28             br.close();
    29         }
    30         if (bw != null)
    31         {
    32             bw.close();
    33         }
    34     }
    35 }
    流操作键盘录入

      流操作的基本规律:

    通过三方面来确定:
    1.明确源和目的
    :输入流,InputStream,Reader
    目的:输出流,OutputStream,Writer
    2.操作的数据是否是纯文本
    是:字符流 否:字节流
    3.当体系明确后,再明确要使用哪个具体的对象
    通过设备来区分:源设备:内存,硬盘,键盘;目的设备:内存,硬盘,控制台

      注:转换流:主要用于字节流与字符流的转换和在涉及字符编码时指定编码。

      20天-01-IO流File类
    File类:用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作,File对象可以作为参数传递给流的构造函数。
    File类常用方法:
    1.创建 boolean createNewFile();//在指定位置创建文件,如果该文件已经存在,则不创建文件返回false
          boolean mkdir();//创建文件夹   boolean mkdirs();//创建多级文件夹
    2.删除 boolean delete();//删除失败返回false     void deleteOnExit();//在程序退出时删除指定文件
    3.判断 exists();//文件是否存在      isHidden();//判断是否是隐藏文件    canExecute();//判断文件是否可执行
        isFile();//是否是文件   isDirectory();//判断是否是目录       isAbsolute();//判断是否是绝对路径
      注:在判断文件对象是否是文件或者目录时,必须要先判断文件对象封装的内容是否存在,通过exists()判断
    4.获取 getName();//获取文件名     getPath();//获取文件封装路径    getParent();//获取文件封装父目录
        getAbsolutePath();//获取文件绝对路径   lastModified();//获取文件最后修改时间    length();//获取文件大小

    删除文件操作示例:

     1 /**
     2 * 递归遍历删除所有文件
     3 *
     4 * @param file 文件路径
     5 */
     6 public static void deleteFile(File file)
     7 {
     8     if (!file.exists())
     9     {
    10         return;
    11     }
    12     File[] fileList = file.listFiles();
    13     for (File f : fileList)
    14     {
    15         if (f.isDirectory())
    16         {
    17             deleteFile(f);
    18         }
    19         else
    20         {
    21             f.delete();
    22         }
    23     }
    24     file.delete();
    25 }
    递归遍历删除所有文件

      20天-11-IO流Properties类

      Properties是hashtable的子类,也就是说它具备map集合的特点,而且它里面存储的键值对都是字符串,是集合和IO技术相结合的集合容器。在加载数据时,需要数据有固定的格式:键=值

      打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印。
      字节流打印流:PrintStream 构造函数可以接收的参数类型:
    1.file对象,File;2.字符串路径,String;3.字节输出流,OutputStream

      字符打印流:PrintWriter 构造函数可以接收的参数类型:
    1.file对象,File;2.字符串路径,String;3.字节输出流,OutputStream;4.字符输出流,Writer

    序列流SequenceInputStream:将多个数据源的文件流合并到一起。
    文件合并流示例:

     1 /**
     2 * 把多个文件里面的数据合并到一个文件里面
     3 *
     4 * @param targetFile  合入文件
     5 * @param sourceFiles 多个原文件
     6 * @throws IOException
     7 */
     8 public static void combineTFiles(String targetFile, String... sourceFiles)
     9     throws IOException
    10 {
    11     ArrayList<FileInputStream> v = new ArrayList<FileInputStream>();
    12     for (String s : sourceFiles)
    13     {
    14         v.add(new FileInputStream(s));
    15     }
    16     Iterator<FileInputStream> it = v.iterator();
    17     Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
    18     {
    19         @Override
    20         public boolean hasMoreElements()
    21         {
    22             return it.hasNext();
    23         }
    24 
    25         @Override
    26         public FileInputStream nextElement()
    27         {
    28             return it.next();
    29         }
    30     };
    31     SequenceInputStream sis = new SequenceInputStream(en);
    32     FileOutputStream fos = new FileOutputStream(targetFile);
    33     byte[] bf = new byte[1024];
    34     int length = 0;
    35     while ((length = sis.read(bf)) != -1)
    36     {
    37         fos.write(bf, 0, length);
    38     }
    39     sis.close();
    40     fos.close();
    41 }
    文件合并

      对象流ObjectInputStream,ObjectOutputStream:被操作的对象需要实现Serializable(标记接口),对象中的transient和static修饰的成员变量不会被读取和写入

    实现Serializable接口的类,需要做一个标记方便后期修改 static final long serialVersionUID = 10L;

      管道流PipedInputStream,PipedOutputStream:输入输出可以直接进行连接,通过结合多线程使用,先把数据写入管道再从管道里面读取出来。
    管道流示例:

     1 class Demo
     2 {
     3     public static void main(String[] args)
     4     {
     5         //exit为退出管道示例命令
     6         PipedInputStream pis = new PipedInputStream();
     7         PipedOutputStream pos = new PipedOutputStream();
     8         //读取管道流连接写入管道流,当有数据写入管道时,读取管道线程自动读入数据
     9         pis.connect(pos);
    10         new Thread(new ReadPiped(pis)).start();
    11         new Thread(new WritePiped(pos, System.in)).start();
    12     }
    13 }
    14 class ReadPiped implements Runnable
    15 {
    16     private PipedInputStream in;
    17     public ReadPiped(PipedInputStream in)
    18     {
    19         this.in = in;
    20     }
    21     @Override
    22     public void run()
    23     {
    24         try
    25         {
    26             byte[] bt = new byte[1024];
    27             int len = 0;
    28             while (true)
    29             {
    30                 len = in.read(bt);
    31                 String str = new String(bt, 0, len);
    32                 if ("exit".equals(str))
    33                 {
    34                     break;
    35                 }
    36                 System.out.println(str);
    37             }
    38             in.close();
    39         }
    40         catch (IOException e)
    41         {
    42             e.printStackTrace();
    43         }
    44     }
    45 }
    46 class WritePiped implements Runnable
    47 {
    48     private PipedOutputStream out;
    49     private BufferedReader bf = null;
    50     public WritePiped(PipedOutputStream out, InputStream in)
    51     {
    52         this.out = out;
    53         bf = new BufferedReader(new InputStreamReader(in));
    54     }
    55     @Override
    56     public void run()
    57     {
    58         try
    59         {
    60             String temp;
    61             while (true)
    62             {
    63                 temp = bf.readLine();
    64                 out.write(temp.getBytes());
    65                 if ("exit".equals(temp))
    66                 {
    67                     break;
    68                 }
    69             }
    70             bf.close();
    71             out.close();
    72         }
    73         catch (IOException e)
    74         {
    75             e.printStackTrace();
    76         }
    77     }
    78 }
    键盘录入管道流

      随机访问文件RandomAccessFile:该类不算IO体系中的子类,而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能,内部封装了一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置,同时也可以通过seek修改指针的位置。其实内部完成读写的原理是内部封装了字节输入流和输出流。

      如果模式为只读 r,不会创建文件,会去读取一个已存在的文件,如果文件不存在,则会抛异常。
      如果模式为读写 rw,操作的文件不存在,会自动创建,如果文件存在则不会覆盖。
      特点:可以随机的读写文件里面的数据,用于多线程把数据分段存到一个文件里(多线程下载)
      void seek(long pos);  //设置指针位置,方便修改指定位置数据
      int skipBytes(int n);  //指针向前跳n个字节,不能向后跳

      基本数据类型流DataInputStream,DataOutputStream:可以用于操作基本数据类型的数据的流对象

      字节数组流
    ByteArrayInputStrean:在构造函数里,需要接收数据源,而且数据源是一个字节数组
    ByteArrayOutputStream:在构造函数里,不用定义数据目的,该对象内部已经封装了可变长度的字节数组,就是数据目的地。
    因为这两个流对象都操作的数组,并没有使用系统资源。所以不用进行close关闭。
    void writeTo(OutputStream out);  //把数组里面的数据写入流里面
      字符数组流   CharArrayReader,CharArrayWriter
      字符串流    StringReader,StringWriter

      21天-07-字符编码
    ASCII:美国标准信息交换码,用一个字节的7位可以表示
    ISO8859-1:拉丁码表,欧洲码表,用一个字节的8位表示
    GB2312:中国的中文编码表
    GBK:中国的中文编码表升级,融合了更多的中文文字字符,用两个字节的8位表示,每个字节前面第一位是标识
    Unicode:国际标准码,融合了多种文字,所有文字都用两个字节来表示,Java语言使用的就是Unicode
    UTF-8:最多用三个字节来表示一个字符

    编码:字符串变成字节数组
    String-->byte[];   str.getBytes(charsetName);
    解码:字节数组变成字符串
    byte[]-->String;   new String(byte[],charsetName);
    编码转换示例:

     1 import java.io.IOException;
     2 import java.io.UnsupportedEncodingException;
     3 class Demo
     4 {
     5     public static void main(String[] args)throws IOException
     6     {
     7         encodeShow("test", "gbk");
     8         encodeShow("test", "utf-8");
     9         encodeShow("test", "GB2312");
    10         encodeShow("test", "ascii");
    11         encodeShow("test", "unicode");
    12         encodeShow("test", "ISO8859-1");
    13     }
    14     public static void encodeShow(String param, String charset)
    15         throws UnsupportedEncodingException
    16     {
    17         String str = param;
    18         sop("source string: " + str + "     encode is: " + charset);
    19         byte[] bt = str.getBytes(charset);
    20         for (byte b : bt)
    21         {
    22             sop("encode binary: " + Integer.toBinaryString(b));
    23         }
    24         String t = new String(bt, charset);
    25         sop("encode string: " + t);
    26         sop("");
    27     }
    28     private static void sop(Object obj)
    29     {
    30         System.out.println(obj);
    31     }
    32 }
    编码转换

    换行符: Linux:    windows:    Mac:

  • 相关阅读:
    Android_bug之 task ':app:mergeDebugResources'. > Some file crunching failed, see logs f
    linux下vi命令大全[转]
    百度地图api 常用demo
    Mac之vim普通命令使用[转]
    java写文件
    java读取文件
    Android中对Log日志文件的分析[转]
    Android实用代码模块集锦
    java 位运算
    MyEclipse自带maven找不到或自己外置安装
  • 原文地址:https://www.cnblogs.com/zengming/p/7489892.html
Copyright © 2011-2022 走看看