概述
一、IO流,即Input Output流
1.IO流用来处理设备之间的数据传输
2.Java对数据的操作是通过流的形式
3.Java用于操作流的对象都存放于IO包中
4.流按操作数据分为两种:字节流和字符流
5.按流向分为:输入流和输出流
6.字符流对象中融合了编码表
(GB2312--->GBK 中文相对于二进制的映射表,ASCII 英文相对于二进制的映射表,unicode--->UTF-8 国际通用编码表)
二、IO流常用基类
1、字符流的抽象基类
Reader Writer
2、字节流的抽象基类
InputStream OutputStream
由以上四个类派生出来的子类的名称都是以其父类名作为子类名的后
FileWriter类
一、功能定义
FileWriter
用于写入字符流。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。专门用于操作文件的Writer子类对象。
二、方法
1.构造方法(根据给定的文件名构造一个 FileWriter 对象。)
FileWriter(String fileName)
创建一个FileWriter对象,该对象一被初始化就要指定文件名,而且该文件会被创建到指定目录下,如果指定目录下存在同名文件,那么将会覆盖已存在的文件,该步目的是要明确数据要存放的目的地。
2.写入字符串
3.刷新流对象中缓冲的数据,将数据刷到目的地中。
void
flush()
FileWriter f=new FileWriter("demo.txt");
f.write("abdcd");
f.flush();
4.关闭此流,但要先刷新它。
void
close()
IO异常处理方式
一、IO异常处理程序
import java.io.*;
class FileWriterDemo2
{
public static void main(String[] args)
{
FileWriter f=null;//为了将f作用于整个函数,在外面建立引用,在try内初始化
try
{
f=new FileWriter("demo.txt");
f.write("abcd");
}
catch (IOException e)
{
System.out.println(e.toString());
}
finally
{
try
{
if(f!=null)//为了防止创建文件失败,而导致f为空,在关闭文件前先做判断
f.close();//文件出现异常后,一定要关闭,所以要放在finally中
}
catch (IOException e)
{
System.out.println(e.toString());
}
}
}
}
文件的续写
一、FileWriter构造方法:
根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
FileWriter(String fileName, boolean append)
import java.io.*;
class FileWriterDemo3
{
public static void main(String[] args) throws IOException
{
FileWriter f=new FileWriter("demo.txt",true);
f.write("wqz\r\nwwb");//\n记事本不识别,\r\n记事本可以识别为换行
f.close
}
}
文本文件读取方式
一、FileReader类
FileReader
用于读取字符流。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。
二、方法
1.构造方法(
在给定从中读取数据的文件名的情况下创建一个新
FileReader
。)
FileReader(String fileName)
如果文件不存在,会发生FileNotFoundException异常
2. 读取单个字符。
int
read()
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("demo.txt");//demo.txt中存放着abc
int ch1=fr.read();
int ch2=fr.read();
int ch3=fr.read();
int ch4=fr.read();
System.out.println("ch1:"+(char)ch1);
System.out.println("ch2:"+(char)ch2);
System.out.println("ch3:"+(char)ch3);
System.out.println("ch4:"+(char)ch4);//如果已读取到末尾,会返回-1
fr.close();
/*代码简化如下
int ch=0;
while((ch=fr.read())!=-1)
{
System.out.println((char)ch);
}
*/
}
}
3.将字符读入数组。
int
read(char[] cbuf)
import java.io.*;
class FileReaderDemo2
{
public static void main(String[] args) throws IOException
{
<span style="white-space:pre"> </span>/*代码简化如下
FileReader fr=new FileReader("demo.txt");
int num=0;
char[] ch=new char[3];//一般定义1024的整数倍
while((num=fr.read(ch))!=-1)
{
System.out.println(new String(ch,0,num));
}
*/
char[] ch=new char[3];
int num1=fr.read(ch);
System.out.println("num1="+num1+"...ch="+new String(ch));//输出3,abc
int num2=fr.read(ch);
System.out.println("num2="+num2+"...ch="+new String(ch));//输出3,def
int num3=fr.read(ch);
System.out.println("num3="+num3+"...ch="+new String(ch));//输出1,gef
int num4=fr.read(ch);
System.out.println("num4="+num4+"...ch="+new String(ch));//输出-1,gef
fr.close();
}
}
单独取最后一个g,可以使用
String(char[] value, int offset, int count)构造方法,即分配一个新的 String
,它包含取自字符数组参数一个子数组的字符。
三、文本文件读取练习(读取一个.java文件,并打印在控制台上)
拷贝文本文件
一、将C盘下的一个文本文件复制到D盘中
1.在D盘创建一个文件
2.定义读取流和C盘文件完成关联
3.通过不断的读写完成对数据的存储
4.关闭资源
第一种方式:(不建议)
import java.io.*;
class CopyText
{
public static void main(String[] args) throws IOException
{
FileWriter fw=new FileWriter("demo_destination.txt");//创建一个文件
FileReader fr=new FileReader("FileReaderDemo.java");//读取流与要读取的文件建立关系
int ch=0;
while((ch=fr.read())!=-1)//完成对数据的读写
{
fw.write(ch);
}
fw.close();//关闭资源
fr.close();
}
}
第二种方式:将数据批量读取到内存中,一次性完成数据转移
import java.io.*;
class CopyText2
{
public static void main(String[] args)
{
FileWriter fw=null;
FileReader fr=null;
try
{
fw=new FileWriter("demo1_destination.txt");
fr=new FileReader("FileReaderDemo.java");
int num=0;
char[] ch=new char[1024];
while((num=fr.read(ch))!=-1)
{
fw.write(ch,0,num);
}
}
catch (IOException e)
{
throw new RuntimeException("数据读写出现错误");
}
finally
{
if(fr!=null)
try
{
fr.close();
}
catch (IOException e)
{
}
if(fw!=null)
try
{
fw.close();
}
catch (IOException e)
{
}
}
}
}
二、拷贝文本图例
BufferedWriter
***字符流缓冲区***
1.缓冲区的出现提高了对数据的读写效率
2.对应的类有
BufferedWriter BufferedReader
3.缓冲区要结合流才可以使用
4.在流的基础上对流的功能进行了加强
一、功能定义
1.将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
2.可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
二、方法
1.构造方法(创建一个使用默认大小输出缓冲区的缓冲字符输出流。)
BufferedWriter(Writer out)
2.写入一个行分隔符。
void
newLine()
跟平台无关,无论什么平台都是换行。
import java.io.*;
class BufferedWriterDemo
{
public static void main(String[] args) throws IOException
{
FileWriter fw=new FileWriter("demo2.txt");
BufferedWriter bw=new BufferedWriter(fw);
/*
bf.write("abcde");
bf.flush();//只要用到缓冲区就要记得刷新
bf.close();
*/
for(int i=1;i<=5;i++)
{
bw.write("abcde"+i);
bw.newLine();
bw.flush();
}
//fw.close();无需此操作,因为在关闭缓冲区的时候就是在关闭数据流
}
}
BufferedReader
一、功能定义
1.从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
2.可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
二、方法
1.构造方法(创建一个使用默认大小输入缓冲区的缓冲字符输入流。)
BufferedReader(Reader in)
2.读取一个文本行。
import java.io.*;
class BufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("demo2.txt");
BufferedReader br=new BufferedReader(fr);
String line=null;
while((line=br.readLine())!=null)
{
System.out.println(line);
}
}
}
MyBufferedReader
一、概述
自定义一个类,这个类包含一个功能和readLine()一样的方法,来模拟一下BufferedReader类
二、代码
import java.io.*;
class MyBufferedReader
{
private FileReader fr=null;
MyBufferedReader(FileReader fr)
{
this.fr=fr;
}
public String myReadLine() throws IOException//定义一个一下可以读一行数据的方法。抛出异常,谁调用,谁处理
{
//定义一个临时容器,原BufferedReader封装的是字符数组
//为了演示方便,在这里使用StringBuilder容器来代替,因为最终要把数据编程字符串
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=fr.read())!=-1)
{
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void myClose() throws IOException
{
fr.close();
}
}
class MyBufferedReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("demo2.txt");
MyBufferedReader mbr=new MyBufferedReader(fr);
String s=null;
while((s=mbr.myReadLine())!=null)
{
System.out.println(s);
}
mbr.myClose();
}
}
装饰设计模式
一、概述
当想要对已有的对象进行功能增强时——可以自定义一个类,将已有对象传入,基于已有对象的功能,并提供加强功能,那么自定义的该类就被成为装饰类。比如上节中自定义的MyBufferedReader类。
二、代码
class Person
{
public void eat()
{
System.out.println("吃饭");
}
}
class SuperPerson
{
private Person p=null;
SuperPerson(Person p)
{
this.p=p;
}
public void superEat()
{
System.out.println("开胃菜");
System.out.println("开胃酒");
p.eat();
System.out.println("饭后甜点");
}
}
class DecorationDemo
{
public static void main(String[] args)
{
Person p=new Person();
SuperPerson sp=new SuperPerson(p);
sp.superEat();
}
}
三、装饰与集成的区别参见视频19-07
LineNumberReader和MyLineNumberReader
一、功能定义
LineNumberReader是BufferedReader的子类,提供了getLineNumber()和setLineNumber()方法来获取设置行号
二、方法
1.获得当前行号。
int
getLineNumber()
2.设置当前行号。
void setLineNumber(int lineNumber)
import java.io.*;
class LineNumberReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("demo2.txt");
LineNumberReader lnr=new LineNumberReader(fr);
String line=null;
lnr.setLineNumber(100);
while((line=lnr.readLine())!=null)
{
System.out.println(lnr.getLineNumber()+" "+line);
}
}
}
三、自定义MyLineNumberReader
参见视频19-10
IO练习
一、概述
有五个学生,每个学生有3门课的成绩,
从键盘输入以上数据,包括姓名,三门课的成绩。
输入的格式:如 zhangsan,30,40,50
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中
二、思想:
1.通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2.因为学生很多,那么久需要存储,使用到集合。
3.因为要对学生的总分排序,所以使用到TreeSet集合。
4.将集合的信息写入到一个文件中。
从键盘输入以上数据,包括姓名,三门课的成绩。
输入的格式:如 zhangsan,30,40,50
并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中
二、思想:
1.通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。
2.因为学生很多,那么久需要存储,使用到集合。
3.因为要对学生的总分排序,所以使用到TreeSet集合。
4.将集合的信息写入到一个文件中。
三、代码
import java.util.*;
import java.io.*;
class Student implements Comparable<Student>
{
private String name;
private int en,cn,ma;
private int sum;
Student(String name,int en,int cn,int ma)
{
this.name=name;
this.en=en;
this.cn=cn;
this.ma=ma;
sum=en+cn+ma;
}
public String getSum()
{
return this.name;
}
public int compareTo(Student stu)
{
if(this.sum==stu.sum)//为什么可以stu.sum而不报错?sum不是私有变量吗?why?
return this.name.compareTo(stu.name);
return this.sum-stu.sum;
}
public int hashCode()
{
return name.hashCode()+sum*36;
}
public boolean equals(Object obj)
{
if(obj instanceof Student)
return false;
Student s=(Student)obj;
return s.name.equals(this.name) && s.sum==this.sum;
}
public String toString()
{
return "student"+"["+name+","+ma+","+en+","+cn+","+sum+"]";
}
}
class StudentTool
{
public static Set<Student> getStudents() throws IOException
{
Set<Student> set=new TreeSet<Student>(Collections.reverseOrder());
BufferedReader bufr=
new BufferedReader(new InputStreamReader(System.in));
String line=null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
String[] info=line.split(",");
Student s=new Student(info[0],Integer.parseInt(info[1]),Integer.parseInt(info[2]),Integer.parseInt(info[3]));
set.add(s);
}
bufr.close();
return set;
}
public static void write2File(Set<Student> stu) throws IOException
{
BufferedWriter bw=new BufferedWriter(new FileWriter("student.txt"));
for(Student s : stu)
{
bw.write(s.toString()+"\t");
bw.write(s.getSum());
bw.newLine();
bw.flush();
}
bw.close();
}
}
class StudentsIOTest
{
public static void main(String[] args) throws IOException
{
Set<Student> ts=StudentTool.getStudents();
StudentTool.write2File(ts);
}
}
/*
zhangsan,66,22,33
lisi,33,88,99
wangwu,76,85,96
*/