------- android培训、java培训、期待与您交流! ----------
一、IO流
IO流用来处理设备之间的数据传输。Java对数据的操作是通过流的方式。
Java用于操作流的对象都在IO包中。
输入流和输出流相对于内存设备而言。
流按操作数据分为两种:字节流与字符流。
字节流的抽象基类:InputStream,OutputStream。
字符流的抽象基类:Reader,Writer。
字符流只能操作文本数据,字节流还可以操作媒体数据
二、字符流
2.1字符流用来处理文本数据(读写)
通过下列代码了解字符流使用流程
2.1.1需求:需求:在硬盘创建一个文件并写入一些文字数据 (FileWriter对象,写)
-
- import java.io.*;
- class FileWriterDemo
- {
- public static void main(String[] args) throws IOException
- {
-
-
- FileWriter fw = new FileWriter("demo.txt");
-
-
-
- fw.write("abcd");
-
-
- fw.flush();
-
-
- fw.close();
-
- }
- }
注意:
1、已有文件的数据续写:在构造函数传递一个boolean参数,true则不覆盖(如果已存在的话),在已有文件的末尾处进行文件续写
FileWriter fw = new FileWriter("demo.txt",true);
2、由于在创建对象时,需要指定创建文件位置,如果指定的位置不存在,就会发生IOException异常,所以在整个步骤中,需要对IO异常进行try处理。以下为标准处理格式。
- import java.io.*;
- class FileWriterDemo2
- {
- public static void main(String[] args)
- {
- FileWriter fw = null;
- try
- {
- fw = new FileWriter("demo.txt");
- fw.write("abcd");
-
- }
- catch (IOException e)
- {
- System.out.println(e.toString());
- }
- finally
- {
- try
- {
- if(fw!=null)
- fw.close();
- }
- catch(IOException e)
- {
- System.out.println(e.toString());
- }
- }
- }
- }
2.1.2 文本文件读取方式(FileReader对象,读)
读取方式:
int read() 读取单个字符
int read(char[] cbuf) 通过数组读取,返回字符个数
- import java.io.*;
- class FileReaderDemo
- {
- public static void main(String[] args)
- {
-
-
- FileReader fr = null;
- try
- {
- fr = new FileReader("demo.txt");
-
-
-
- int ch = 0;
- while((ch=fr.read())!=-1)
- {
- System.out.println("ch="+(char)ch);
- }
- }
- catch (IOException e)
- {
- System.out.println(e.toString());
- }
- finally
- {
- try
- {
- if(fr!=null)
- fr.close();
- }
- catch (IOException e)
- {
- System.out.println(e.toString());
- }
- }
- }
- }
2.2字符流的缓冲区:BufferedWriter、BufferedReader
是为了提高流的操作效率而出现的,在创建缓冲区之前,必须要先有流对象,在构造缓冲区对象时将流对象赋给缓冲区对象。
BufferedWriter
- FileWriter fw = new FileWriter("buf.txt");
-
- BufferedWriter bufw = new BufferedWriter(fw);
- bufw.write("abcdef");
- bufw.newLine();
- bufw.write("abcdef");
- bufw.flush();
- bufw.close();
BufferedReader
- FileReader fr = new FileReader ("buf.txt");
- BufferedReader bufr = new BufferedReader(fr);
- String st = null;
- while((st=bufr.readLine())!=null)
- {
- "white-space:pre"> System.out.println(st);
- }
- bufr.close();
写入换行使用BufferedWriter类中的newLine()方法。
读取一行数据使用BufferedReader类中的readLine()方法。
练习:通过缓冲区复制一个.java文件
- mport java.io.*;
- class BufferedCopy
- {
- public static void main(String[] args)
- {
- BufferedReader bufr = null;
- BufferedWriter bufw = null;
-
- try
- {
- bufr = new BufferedReader(new FileReader("BufferedWriterDemo.java"));
- bufw = new BufferedWriter(new FileWriter("e:\\BufferedWriterDemo.txt"));
- String buf = null;
- while((buf=bufr.readLine())!=null)
- {
- bufw.write(buf);
- bufw.newLine();
- bufw.flush();
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("读写异常");
- }
- finally
- {
- if(bufw!=null)
- {
- try
- {
- bufw.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException("写入关闭异常");
- }
- }
- if(bufr!=null)
- {
- try
- {
- bufr.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException("读取关闭异常");
- }
- }
- }
- }
- }
2.3 LineNumberReader
BufferedReader的子类。跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
- import java.io.*;
- class LineNumberReaderDemo
- {
- public static void main(String[] args)
- {
- FileReader fr = null;
- LineNumberReader lnr = null;
- try
- {
- fr = new FileReader("CopyTest.java");
- lnr = new LineNumberReader(fr);
-
- String line = null;
- lnr.setLineNumber(10);
- while((line=lnr.readLine())!=null)
- {
- System.out.println(lnr.getLineNumber()+": "+line);
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("读写异常");
- }
- finally
- {
- try
- {
- if(lnr!=null)
- lnr.close();
- try
- {
- if(fr!=null)
- fr.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException("关闭读取异常");
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException("关闭读取异常");
- }
- }
- }
- }
2.4 装饰设计模式
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类称为装饰类
1、装饰类通常会通过构造方法接受被装饰的对象
2、装饰类比继承要灵活,避免了继承体系的臃肿而且降低了类与类之间的关系
3、装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能
所以装饰类和被装饰类通常是属于一个体系中的
- class SuperPerson
- {
- public static void main(String[] args)
- {
- Person p = new Person();
- PersonUp pu = new PersonUp(p);
- pu.chifanUp();
- }
- }
- class Person
- {
- public void chifan()
- {
- System.out.println("吃米饭");
- }
- }
- class PersonUp
- {
- private Person p;
- PersonUp(Person p)
- {
- this.p = p;
- }
- public void chifanUp()
- {
- System.out.println("吃开胃菜");
- p.chifan();
- System.out.println("饭后甜点");
- }
- }
三、字节流
基本操作与字符流类相同。但它不仅可以操作字符,还可以操作其他媒体文件。
字节流操作最小的数据单位,不需要刷新。
基类:InputStream(输入) OutputStream(输出)
练习:复制一张图片
- import java.io.*;
- class CopyPicture
- {
- public static void main(String[] args)
- FileOutputStream fos = null;
-
- FileInputStream fis = null;
- try
- {
- fos = new FileOutputStream("Copy.png");
- fis = new FileInputStream("copy1.png");
- byte[] buf = new byte[1024*1024];
- int len = 0;
- while((len=fis.read(buf))!=-1)
- {
- fos.write(buf,0,len);
- }
- }
- catch (IOException e)
- {
- throw new RuntimeException ("读写失败");
- }
- finally
- {
- try
- {
- if(fos!=null)
- fos.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException ("写入关闭失败");
- }
- try
- {
- if(fis!=null)
- fis.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException ("读取关闭失败");
- }
- }
- }
- }
3.1 字节流缓冲区
字节流的缓冲区:同样是提高了字节流的读写效率。
读写特点:
read():会将字节byte型值提升为int型值
write():会将int型强转为byte型,即保留二进制数的最后八位。
练习:自定义字节流缓冲区
- import java.io.*;
- class myBufferedInputStream
- {
- private InputStream in;
- private byte[] buf = new byte[1024];
- private int pos = 0,count = 0;
- myBufferedInputStream(InputStream in)
- {
- this.in = in;
- }
-
- public int myread() throws IOException
- {
- if(count==0)
- {
-
-
- count = in.read(buf);
- if(count<0)
- return -1;
- pos = 0;
- byte b = buf[pos];
- count--;
- pos++;
- return b&255;
- }
- else if(count>0)
- {
- byte b = buf[pos];
- count--;
- pos++;
- return b&0xff;
- }
- return -1;
- }
-
- public void myclose() throws IOException
- {
- in.close();
- }
- }
四、 流的操作规律
4.1键盘录入
键盘本身就是一个标准的输入设备。对于java而言,对于这种输入设备都有对应的对象。
标准输入输出流
System.in:对应的标准输入设备,键盘。
System.out:对应的是标准的输出设备,控制台。
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream的子类。
4.2 转换流
能不能直接用readLine方法来完成键盘录入一行数据的读取呢
readLine是字符流BufferedReader类中的方法
而键盘录入的read方法是字节流InputStream类中的方法
能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢
InputStreamReader 是字节流通向字符流的桥梁,解码
OutputStreamWriter 是字符流通向字节流的桥梁,编码
字节流处理的是文本数据,可以转换成字符流,操作更方便。
练习:获取用户键盘录入的数据并将数据变成大写显示在控制台上,如果用户输入的是over,结束键盘录入。
- import java.io.*;
- class ReadIn
- {
- public static void main(String[] args) throws IOException
- {
-
-
-
-
-
-
-
-
-
-
- BufferedReader br =
- new BufferedReader(new InputStreamReader(System.in));
-
-
-
-
-
-
- BufferedWriter buw = new BufferedWriter(
- new OutputStreamWriter(System.out));
-
- String line = null;
- while((line=br.readLine())!=null)
- {
- if("over".equals(line))
- break;
- buw.write(line.toUpperCase());
- buw.newLine();
- buw.flush();
- }
- br.close();
- }
- }
4.3 IO流操作规律
流的对象很多,不知道该用哪一个,通过3个明确来完成
1.明确源和目的
源:输入流 InputStream Reader
目的: 输出流 OutputStream Writer
2.操作的数据是否是纯文本
是:字符流
不是:字节流
3.当体系明确后,再明确要使用哪个具体的对象。通过设备来进行区分:
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
示例:将键盘录入的数据保存到一个文件中。
源:InputStream和Reader
是不是纯文本?是,Reader
设备:键盘。对应的对象是System.in。为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。所以既然明确了Reader,那么就将System.in转换成Reader。用Reader体系中转换流,InputStreamReader
InputStreamReaderisr = new InputStreamReader(System.in);
需要提高效率吗?需要,BufferedReader
BufferedReaderbufr = new BufferedReader(isr);
4.4 字符编码
字符流的出现方便了操作字符,更重要的是加入了编码转换
通过子类转换流来完成
InputStreamReader
OutputStreamWriter
在两个对象构造时可以加入字符集
- import java.io.*;
- class EncodeStream
- {
- public static void main(String[] args) throws IOException
- {
- readText();
- }
-
- public static void readText() throws IOException
- {
- InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"GBK");
- char[] buf = new char[10];
- int len = 0;
- len = isr.read(buf);
- String str = new String(buf,0,len);
- System.out.println(str);
- isr.close();
- }
- public static void writeText() throws IOException
- {
- OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
- osw.write("你好");
- osw.close();
- }
- }
原因分析:由于utf.txt文件中是UTF-8编码的“你好”,6个字节。
使用FileReader类是用GBK编码进行读取,6个字节代表3个字符,并且按照GBK进行解码,因此才出现如上结果。
五、File类
File类用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。流只能操作数据,不能操作文件。
File对象创建
方式一: File f =new File("a.txt");
将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。
方式二: File f2=newFile("c:\\abc","b.txt");
将文件所在目录路径和文件一起传入,指定文件路径。
方式三: File d=new File("c:\\abc");
File f3=new File(d,"c.txt");
将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。
小知识:
File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。
File类常见方法
1.创建
boolean createNewFile() 指定位置创建文件,存在则返回flase
boolean mkdir() 创建此抽象路径名指定的目录。
boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。
2.删除
boolean delete() 删除此抽象路径名表示的文件或目录
void deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。
3.判断
boolean exists() 测试此抽象路径名表示的文件或目录是否存在。
boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。
boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。
isHidden()
isAbsolute()
4.获取信息
String getName()
String getPath()
String getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名
没有指定父目录,则返回 null。
File getParentFile() 返回此抽象路径名父目录的抽象路径名;
如果此路径名没有指定父目录,则返回 null
File getAbsoluteFile() 返回此抽象路径名的绝对路径名形式。
String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。
long lastModified()
long length()
5、列出文件及文件过滤
static File[] listRoots(); //列出可用的文件系统根目录,即系统盘符
String[] list(); //列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
String[]list(FilenameFilter filter); //返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。
File[] listFiles();//返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹
File[] ListFiles(FilenameFilterfilter);//返回抽象路径名数组,获取目录中满足指定过滤器的文件或目录。
练习:常用方法操作
- import java.io.*;
- class FileDemo2
- {
- public static void main(String[] args) throws IOException
- {
- method_5();
- }
-
- public static void method_1() throws IOException
- {
-
- File f = new File("e:\\file.txt");
- File dir = new File("e:\\zz");
- sop("mkdir:"+dir.mkdir());
- sop("creat:"+f.createNewFile());
-
- sop("delete:"+f.delete());
- sop("exists:"+dir.exists());
- }
- public static void method_2()
- {
- File f = new File("e:\\file.txt");
- sop("execute:"+f.canExecute());
- }
- public static void method_3()
- {
-
-
- File f = new File("file.txt");
- f.mkdir();
- sop("Directory:"+f.isDirectory());
- sop("File:"+f.isFile());
- }
- public static void method_4()
- {
- File f = new File("file.txt");
- sop("path:"+f.getPath());
- sop("Abspath:"+f.getAbsolutePath());
- sop("parent:"+f.getParent());
- sop(f.length());
- sop(f.lastModified());
-
- }
- public static void method_5() throws IOException
- {
- File f1 = new File("e:\\file.txt");
- File f2 = new File("e:\\file22.txt");
- f1.createNewFile();
- sop(f1.renameTo(f2));
-
- }
- public static void sop(Object obj)
- {
- System.out.println(obj);
- }
- }
练习:获取一个目录下所有的.java文件
- import java.io.*;
- class FileDemo3
- {
- public static void main(String[] args)
- {
- listDemo_1();
- }
- public static void listDemo_1()
- {
- File f = new File("C:\\Users\\JXH\\Desktop\\java\\day13");
- String[] st = f.list(new FilenameFilter()
- {
- public boolean accept(File dir, String name)
- {
- return name.endsWith(".java");
- }
- });
- for(String s:st)
- {
- System.out.println(s);
- }
- }
- }
六、打印流
PrintWriter与PrintStream:可以直接操作输入流和文件。
PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
与其他输出流不同,PrintStream永远不会抛出IOException。
PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。
在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类。
PrintStream:字节打印流
1. 提供了打印方法可以对多种数据类型值进行打印,并保持数据的表示形式
2. 它不抛IOException
构造函数,接收三种类型的值:
1. 字符串路径
2. File对象
3. 字节输出流
PrintWriter:字符打印流
构造函数参数:
1. 字符串路径
2. File对象
3. 字节输出流
4. 字符输出流
- import java.io.*;
- import java.util.*;
- class PrintWriterDemo
- {
- public static void main(String[] args) throws IOException
- {
- BufferedReader bufr =
- new BufferedReader(new InputStreamReader(System.in));
-
- PrintWriter out = new PrintWriter(System.out,true);
-
- String line = null;
-
- while((line=bufr.readLine())!=null)
- {
- if("over".equals(line))
- break;
-
- out.println(line.toUpperCase());
-
- }
-
- out.close();
- bufr.close();
-
- }
- }
七、序列流
SequenceInputStream:对多个流进行合并。
常用构造函数 SequenceInputStream(Enumeration e)
- import java.io.*;
- import java.util.*;
- class SequenceDemo
- {
- public static void main(String[] args) throws IOException
- {
- Vector v = new Vector();
-
- v.add(new FileInputStream("1.txt"));
- v.add(new FileInputStream("2.txt"));
- v.add(new FileInputStream("3.txt"));
-
- Enumeration en = v.elements();
- SequenceInputStream sis = new SequenceInputStream(en);
- FileOutputStream fos = new FileOutputStream("4.txt");
-
- byte[] buf = new byte[1024];
- int len = 0;
- while((len=sis.read(buf))!=-1)
- {
- fos.write(buf,0,len);
- }
-
- fos.close();
- sis.close();
- }
- }