Java基础知识_毕向东_Java基础视频教程笔记(19-21 IO流)

来源:互联网 发布:mysql下create index 编辑:程序博客网 时间:2024/06/05 10:28

  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     try12     {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     finally29     {30         try31         {32             if (fr != null)33             {34                 fr.close();35             }36         }37         catch (IOException e)38         {39             e.printStackTrace();40         }41         try42         {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     try12     {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     finally32     {33         try34         {35             if (bufr != null)36             {37                 bufr.close();38             }39         }40         catch (IOException e)41         {42             e.printStackTrace();43         }44         try45         {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     try12     {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     finally31     {32         try33         {34             if (bfis != null)35             {36                 bfis.close();37             }38         }39         catch (IOException e)40         {41             e.printStackTrace();42         }43         try44         {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     finally25     {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         else20         {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 IOException10 {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         @Override20         public boolean hasMoreElements()21         {22             return it.hasNext();23         }24 25         @Override26         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 Runnable15 {16     private PipedInputStream in;17     public ReadPiped(PipedInputStream in)18     {19         this.in = in;20     }21     @Override22     public void run()23     {24         try25         {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 Runnable47 {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     @Override56     public void run()57     {58         try59         {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 UnsupportedEncodingException16     {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:\n    windows:\r\n    Mac:\r

阅读全文
0 0
原创粉丝点击