黑马程序员——第六章 JavaIO操作
2015-05-13 13:08
309 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
异常
定义:程序的运行时候出现的不正常现象。异常的继承体系
Throwable类是所有异常和错误的父类。
Error错误:程序出现了严重的问题,不修改代码,根本不能运行。
Exception异常:程序出现了比较轻的问题,处理掉之后,继续运行。
Exception类是所有异常的父类。
Throwable中的方法:
StringtoString()重写Object类的方法,异常信息的详细描述。
StringgetMessage() 返回异常信息的简短描述。
voidprintStackTrace() 异常信息输出到控制台。
编译异常和运行异常
编译时期异常:当你调用一个方法,这个方法抛出异常,调用者必须处理,否则编译失败,处理方式:可以try或者抛。
运行时期异常:RuntimeException类和他的所有子类,都称为运行时期异常,方法中如果抛出的异常是运行时期异常,处理方式:方法中try catch throw,不需要throws。
try catch处理异常。
运行时期异常的设计初衷:运行时起异常不能出现的,一旦发生,不要处理异常。程序必须停下,修改源代码。
常见运行时期异常
IndexOutOfBoundsException越界异常
NullPointerException空指针异常
ClassCastException 类型转换异常
NoSuchElementException没有元素被取出异常
IllegalArgumentException 无效参数异常
异常的处理方式
1,try catch处理
格式:
try{
检测的代码
有可能发生异常的代码
}catch(异常类 变量){
异常的处理方式(循环,判断,调方法)
有catch,就可以称为异常被处理了
}
2,throws throw抛出异常给调用者
throw:写在方法中,手动抛出异常,后面接 new 异常对象。
throws:写在方法的声明上,方法声明抛出异常,后面接异常类。
finally代码块
finally代码块中的程序,必须要运行,有释放资源意义。
finally跟随try出现,不能进行异常处理,必须抛出。
finally也可以跟随try...catch出现。
自定义异常
步骤:
定义类,后缀名Exception 继承Exception类,或者继承RuntimeException,自定义的异常类的构造方法中,把异常信息使用super传递到父类。
注意:
1,只有异常类,才具备可抛性,throw new 异常体系的类。
2,如果一个方法中,抛出多个异常,必须要throws声明多个异常(运行时期除外)
调用者,使用多个catch进行异常的捕获,多个catch中,最大(继承关系)的父类,必须写在最后面,否则编译失败。
3,RuntimeException以及其子类如果在函数中被throw抛出,可以不用在函数上声明。
4,父类的方法抛异常,子类重写方法后,可抛可不抛,如果子类抛,不能抛出比父类还大的异常。
5,父类的方法不抛异常,子类重写方法后,子类不能抛出异常,只能try...catch处理异常。
IO流
IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,Java用于操作流的类都在java.io包中。IO流的划分:
按流向分为两种:
输入流:程序读取文件。
输出流:程序写入文件。
按操作类型分为两种:
字节流 : 开始于JDK1.0,字节流可以操作任何数据,每次操作1个字节8个二进制,不查询编码表。
字符流 : 开始JDK1.1,字符流专门用于操作文本文件,方便Java程序操作纯文本,每次操作1个字符16个二进制,会查询本机默认的编码表。
文本文件:.txt .java .html .xml .css文件等
IO流的书写
使用前,导入IO包中的类。
使用时,进行IO异常处理。
使用后,释放资源。
字符流
字符流的抽象父类:Reader和Writer字符输出流
Writer类,抽象的,找子类 FileWriter 写入字符文件的便捷类。写入顺序:
1,创建子类FileWriter对象,使用子类的构造器,传递String文件名。
2,子类对象调用父类方法write( )写文件。
3,flush( )刷新该流的缓冲。
4,close( )关闭流对象。
一旦流对象关闭,不能再次使用。
写入方式
1,写入字符串,write(String str)
2,写入单个的字符,write(int i)
3,写入字符数组,write(char[] c)
4,写入字符数组一部分,write(char[] c,int start,int length)
字符输入流
Reader类,抽象类,找子类FileReader读取字符文件的便捷类。读取顺序:
1,创建子类FileReader对象,使用子类构造器,传递String文件名。
2,在调用父类方法read( )读取文件
3,close( )关闭流对象。
一旦流对象关闭,不能再次使用。
读取方式
1,读取单个字符,read()
2,读取字符数组,read(char[] c)
3,读取字符数组一部分,read(char[] c,int off, int len)
读取到文件末尾,返回-1
文件的复制效果--带异常处理
BufferedWriter类
字符输出流缓冲区BufferedWriter,提高字符流的输出效率。BufferedWriter,也是Writer的子类,Writer类的方法都可以用,必须有一个输出流对象配合使用,newBfferedWriter(new FileWriter( ))
特有方法
void newLine()文本中,写换行,具有跨平台性。
Windows中换行,newLine( )写的是\r\n
Linux中换行,newLine( )写的是\n
BufferedReader类
字符输入流的缓冲区BufferedReader,提高字符流的输入效率。BufferedReader也是Reader的子类,Reader的方法,都可以用,也需要一个输入流对象配合使用,newBufferedReader(new FileReader( ))
特有方法
String readLine()读取文本一行,返回字符串。
读取到文件末尾,返回null
字节流
字节流的抽象父类:InputStream和OutputStream字节输出流
OutputStream类,抽象的,找子类 FileOutputStream写入任意文件的便捷类。写入顺序:
1,创建子类FileOutputStream对象,使用子类的构造器,传递String文件名。
2,子类对象调用方法write( )写文件。
3,close( )关闭流对象。
一旦流对象关闭,不能再次使用。
写入方式
1,写入单个的字节,write(int i)
2,写入字节数组,write(b
4000
yte[] c)
3,写入字符数组一部分,write(byte[] c,int start,int length)
字节输入流
InputStream类,抽象类,找子类FileInputStream读取任意文件的便捷类。读取顺序:
1,创建子类FileInputStream对象,使用子类构造器,传递String文件名。
2,在调用方法read( )读取文件
3,close( )关闭流对象。
一旦流对象关闭,不能再次使用。
读取方式
1,读取单个字节,read()
2,读取字节数组,read(char[] c)
3,读取字节数组一部分,read(char[] c,int off, int len)
读取到文件末尾,返回-1
BufferedOutputStream
字节输出流缓冲区BufferedOutputStream,提高字节流的输出效率。BufferedOutputStream,也是OutputStream的子类,OutputStream类的方法都可以用,必须有一个输出流对象配合使用。
new BufferedOutputStream (newFileOutputStream ( ))
BufferedInputStream
字节输入流的缓冲区BufferedInputStream,提高字节的输入效率。BufferedReader也是InputStream的子类,InputStream的方法,都可以用,也需要一个输入流对象配合使用。
new BufferedInputStream (newFileInputStream ( ))
标准输入输出流
它们各代表了系统标准的输入和输出设备,默认输入设备是键盘,输出设备是显示器。System.in:类型是InputStream,标准输入流, 默认可以从键盘输入读取字节数据。
System.out:类型是PrintStream,标准输出流,是OutputStream的子类FilterOutputStream 的子类。
转换流
字节转成字符InputStreamReader,本身是一个字符流,继承Reader,字节流向字符的桥梁。
转换顺序:
1, InputStreamReader构造方法中,传递字节输入流。
2, BufferedReader(Reader r) 可以缓冲这个转换流,进行行读取。
字符转成字节
OutputStreamWriter, 继承Writer,也是一个字符流,字符流向字节的桥梁。
转换顺序:
1, BufferedWriter(Writer w)写入字符流
2, OutputStreamWriter构造方法中,传递字节输出流。
转换流的好处,在于数据源和数据目的,可以随时改变,但是转换流是字符流,只能处理文本数据。
转换流编码效果
流对象,没有指定查询哪一个码表,默认走操作系统的中GBK
转换流OutputStreamWriter构造方法中,写一个字节输出流,写编码表的名字(String)不区分大小写,转换流会将文本数据,以指定的编码形式写入文件。
转换流InputStreamReader构造方法中,写一个字节输入流,写编码表的名字(String)不区分大小写,转换流会将文本数据,以指定的编码形式读取文件。
字符的编码和解码
编码:字符串à字节数组解码:字节数组à字符串
编码表:
ASCII:美国标准信息交换码,用一个字节的7位可以表示。
ISO8859-1:拉丁码表,欧洲码表,java网络服务器Tomcat,用一个字节的8位表示。
GB2312:中国的中文编码表,2个字节 对应1个汉字,4000左右汉字。
GBK:中国的中文编码表升级,2个字节对应1个汉字,20000个汉字。
Unicode:国际标准码,融合了多种文字,所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:3个字节对应1个汉字。
编码方法:String类方法getBytes(编码表名)
解码方法:String类的构造方法(字节数组,编码表名)
File类
将文件或文件夹路径封装成File对象,File类提供方法来操作这些对象。File类,不属于流对象,不能读写文件。
File类的对象,可以作为参数,传递给流对象的构造方法.
File类方法,熟练掌握,用方法操作路径和文件夹,必须能够配合流对象实现更多功能。
绝对路径: 从盘符开始, 是一个固定的路径
相对路径: 不从盘符开始, 相对于某个位置。在Eclipse中的Java工程相对于工程根目录. cmd则相对应于当前目录。
File类的静态常量
目录分隔符,Windows中为“\” Linux中为“/”
public static String separator,返回String
public static char separatorChar,返回char
路径分隔符,Windows中“ ; ” Linux中为“:”
public static String pathSeparator,返回String
public static char pathSeparatorChar,返回char
File类构造方法
File(String pathname)传递字符串的路径。
File(String parent,String child)传递字符串的父路径,字符串的子路径。
File(File parent,String child)传递File父路径,字符串的子路径。
File类创建方法
boolean createNewFile() 创建文件,创建的是File构造方法中封装的路径,创建成功返回真,失败返回假。如果文件有,不在创建。只能创建文件。
boolean mkdir()创建文件夹,创建的是File构造方法中封装的路径,创建成功返回真,失败返回假。如果存在就不在创建。只能创建文件夹,能创建一级目录。
boolean mkdirs()可以创建多级目录,用法和mkdir完全一致,推荐使用。
File类的删除方法
boolean delete()删除构造方法中指定的路径,删除成功返回真,失败返回假。删除的时候,不走回收站,直接永久删除。删除一个文件夹时,只能删空文件夹。
void delectOnExit()删除构造方法中指定的路径,延迟删除,等JVM退出之前再删除。
File类的判断方法
boolean exists()判断File构造方法中封装的路径是不是存在,如果存储在返回真,不存在返回假。
boolean isAbsolute()判断File构造方法中封装的路径是不是绝对路径,如果是返回真,不是返回假。
boolean isDirectory()判断File构造方法中封装的路径是不是一个文件夹,如果是文件夹返回真,不是返回假。
boolean isFile()判断File构造方法中封装的路径是不是文件,如果是文件返回真,不是文件返回假
boolean isHidden()判断File构造方法封装的路径是不是隐藏属性,是隐藏属性返回真,不是返回假
File类的获取方法
String getName()获取到File构造方法中封装的路径的最后部分的名字。
String getParent()返回File构造方法中封装的路径的父路径,返回字符串,如果没有父路径返回null。
File getParentFile()返回File构造方法中封装的路径的父路径,返回的是一个File对象,如果没有父路径返回null。
String getAbsolutePath()返回File构造方法中封装的路径的绝对路径,返回的是一个String类对象。
File getAbsoluteFile()返回File构造方法中封装的路径的绝对路径,返回值是一个File对象。
File类的其他方法
boolean renameTo(File f)重命名,File封装一个路径,这个对象调用renameTo(修改后的路径的File对象),修改成功返回真,失败返回假。修改名字后路径不同,方法renameTo带有剪切效果。
long lastModified()返回File封装的路径中文件的最后修改时间的毫秒值。
static File[] listRoots()返回系统根,封装成File对象,存储数组。
String[] list()返回File构造方法封装的路径下的所有文件和文件夹。返回String
File[] listFiles()返回File构造方法封装的路径下的所有文件和文件夹,返回的Filed对象,带全路径。
list开头方法的文件过滤器
根据自己的需要,遍历目录的时候,只获取想要的文件,其他文件全部过滤。
过滤器FileFilter是一个接口,需要定义类实现FileFilter接口,重写方法accept,把实现类的对象,传递给listFiles()方法。
例:File file = new File("f:\\");
File[] files = file.listFiles(new MyFileFilter());
或者:
File[] files = file.listFiles(new FileFilter( ) {
publicboolean accept(File pathname) {
returnpathname.getName().endsWith(".hetml");
}
});
递归
递归:编程技巧,方法自身调用自己。适用情况:当某一功能要重复使用时,方法的运算主体不变,每次运行的参数在变化。
递归的好处和弊端:
好处:可以不知道循环次数(方法调用次数)。
弊端:有可能会栈内存溢出。
递归的注意事项:
1, 递归一定要有条件限制,否则就死循环。
2, 递归,方法进栈的次数不能太大。
3, 构造函数不能使用递归,因为若可以,将不断创建对象,永不停止。
4, 递归调用可以有返回值也可以没有。
打印流
该流可以很方便的将对象的toString()结果输出, 并且自动加上换行, 而且可以使用自动刷新的模式。打印流不抛异常,因为只操作数据目的,不操作数据源。
第一个打印流是字节输出流PrintStream ,System.out 返回值结果是PrintStream
第二个打印流是字符输出流PrintWriter,实现类PrintStream中的所有打印方法。
PrintStream类和PrintWrtier类的关系
共性:负责打印数据,不抛异常,不操作数据源,都有很多打印方法。
区别:一个是字节流,一个是字符流,两个流的构造方法。
PrintStream构造方法,传递的都是数据目的,接收File对象,字节输出流,字符串的文件名,三种类型参数。
PrintWrtier构造方法,传递的都是数据目的,接收File对象,字符输出流,字符串的文件名,字符输出流,四种类型参数。
若构造方法中的参数是流对象,在流对象的构造方法的参数中加上true,就可以开启打印流的自动刷新功能。
如果启用自动刷新,则必须调用三个方法之一:println、printf、format
对象操作流
对象的序列化将对象的数据写到文件中。
写对象数据的流 ObjectOutputStream,构造方法中,传递字节输出流 OutputStream子类FileOutputStream,写的方法void writeObject(Object obj)将对象中的数据,写入到字节输出流包装的文件。
例:ObjectOutputStreamoos =
new ObjectOutputStream(newFileOutputStream("f:\\Person.txt"));
Person p = new Person("张三", 18);
oos.writeObject(p);
oos.close();
关键字transient,修饰符,只能用在成员变量的修饰上,阻止变量序列化。
对象的反序列化
将文件中保存的对象的数据读取出来。
读取对象数据的流ObjectInputStream,构造方法中,传递字节输入流InputStream子类FileInputStream,读取对象的方法 Object readObject() 读取文件中的对象,返回Object。
抛出类找不到异常. 必须有class文件,否则不能实现
例:ObjectInputStream ois =
new ObjectInputStream(newFileInputStream("f:\\Person.txt"));
Object o = ois.readObject();
ois.close();
对象的类必须实现Serializable接口,如果不实现这个接口,无法序列化和反序列化。
序列化中的序列号问题
序列号冲突:编译Person.java生成class,class文件中就保存了这个类的序列号,此时对类进行了序列化操作,生成序列化文件person.txt,保存了一个序列号,这个号和class文件中的序列号是一致的。修改了Person.java源文件,将private修改成了public,从新编译class,序列号发生变化了,从新读取了序列化文件,此时的文件中保存的序列号和class文件中的序列号不一致,因此发生异常。
修改源代码后,不让JVM重新计算序列号,就要自定义序列号。
例:static finallong serialVersionUID = 7865432134587654321L;
集合IO的结合使用
集合使用的是Hashtable的子类Properties。存储键值对的集合,不能存储null,并且是一个线程安全的集合。两个自己的方法setProperty ,getProperty。Properties类的方法load(字节或者字符输入流),文件中的键值对就会自动被存储到集合中。
配置文件中,存储键值对的文件,不想要这个键值对,使用#注释
Properties类的
aa8d
方法store(字节或字符输出流,字符串)将集合中的键值对自动保存回原来的文件中。
集合IO综合练习题
题目要求: 已知一个文本,保存的是学生的姓名,考试成绩
对成绩进行排序,成绩相同,按照姓名排,排序后的结果存储到新的文件中,文件的名字有要求,如果原始文件名字 score.txt 新生成排序后的文件 sortScore.txt
例:
/*
* 需求:
* 1,已知一个文本,保存的是学生的姓名,考试成绩,要求对成绩进行排序。
* 2,成绩相同的,按照姓名排,排序后的结果存储到新的文件中。
* 3,如果原始文件名字 score.txt,新生成排序后的文件 sortScore.txt
*/
import java.io.*;
import java.util.*;
public class ScoreSort {
public static voidmain(String[] args) throws Exception {
// 原始文件,封装到File对象
File source = new File("c:\\score.txt");
// IO流读取文件,按行读取
BufferedReader bfr = new BufferedReader(newFileReader(source));
// 创建集合对象
List<Student> list = new ArrayList<Student>();
// 读取后,切割字符,存到集合
String line = null;
while ((line = bfr.readLine()) != null) {
String[] str =line.split(" +");
list.add(newStudent(str[0], Integer.parseInt(str[1])));
}
// 关闭流
bfr.close();
bfr = null;
// 对List集合进行排序
Collections.sort(list, Collections.reverseOrder());
// 迭代集合,将集合中数据,写到新的文件中
// 获取源文件名
String filename = source.getName();
StringBuilder sb = new StringBuilder(filename);
// 把s变为S
char ch = (char) (sb.charAt(0) - 32);
sb.setCharAt(0, ch);
sb.insert(0, "sort");
// 获取数据源目录的父路径
String parent = source.getParent();
// 父路径和文件名组成新的File对象
File sort = new File(parent, sb.toString());
// 创建打印流对象,包装File sort对象,开启自动刷新
PrintWriter pw = new PrintWriter(new FileWriter(sort), true);
// 遍历集合
for (Student s : list) {
pw.println(s.getName()+ " " + s.getScore());
}
pw.close();
}
}
基本数据操作流
DataOutputStream写基本数据类型继承OutputStream,字节输出流
构造方法中,传递字节输出流 FileOutputStream
写基本数据类型的方法writeInt(int),将4个字节的int值写入输出流。
DataInputStream读取基本数据类型
继承InputStream,字节输入流
构造方法中,传递字节输入流FileInputStream
读取基本数据类型的方法 int readInt(),4个字节读取。
读取到文件末尾抛出EOFException,利用异常进行循环读取。
字节数组操作流
ByteArrayInputStream,读取内存中的字节数组,不占用操作系统底层资源,无需关闭。构造方法中传递字节数组。ByteArrayOutputStream,往内存中写字节数组,不占用操作系统的资源,无需关闭,空参数构造方法。
byte[] toByteArray,流中的数组返回来。
String toString,将流中的字节数组,变成字符串,默认编码表GBK
String toString(String字符集名字)将流中的字节数组,变成字符串,指定编码表。
例:
FileInputStreamfis = new FileInputStream("a.txt");//创建字节输入流,关联a.txt
ByteArrayOutputStreambaos = new ByteArrayOutputStream();//创建内存输出流
byte[] arr = newbyte[5]; //创建字节数组,大小为5
int len;
while((len =fis.read(arr)) != -1) {//将文件上的数据读到字节数组中
baos.write(arr, 0, len); //将字节数组的数据写到内存缓冲区中
}
System.out.println(baos);//将内存缓冲区的内容转换为字符串打印
fis.close();
随机读写流RandomAccessFile
非常特殊的流对象,拥有读和写的能力,这个类中封装了一个大型字节数组,数组的下标,看成是这个文件的指针seek(long l)方法对指针定位。
随机读写:可以中文件中的任意位置进行读和写。
构造方法,String filename , String mode 读取模式
。
相关文章推荐
- 黑马程序员——java的IO之流操作的基本规律,Properties类,打印流,序列流
- 黑马程序员——JAVA笔记——IO操作(2)
- Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律 (黑马程序员)
- 黑马程序员 java 基础 毕向东 面向对象 IO操作 File Properties PrintWriter PrintStream 应用
- 『黑马程序员』---java--IO--分段读写-操作基本类型-内存为源
- 黑马程序员学习笔记之七(Java IO操作)
- 黑马程序员 java IO PrintWriter BufferedReader 读取键盘 写操作
- 黑马程序员------java -io操作
- 黑马程序员——Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律
- 黑马程序员——Java基础----IO(字节流、操作规律等)(2)
- 黑马程序员——Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律
- 黑马程序员——JAVA笔记——IO操作
- 黑马程序员——Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律
- 黑马程序员——Java基础视频笔记(七):IO操作
- 黑马程序员——javaIO中File的操作与应用
- 黑马程序员 Java IO操作
- 黑马程序员——Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律
- 黑马程序员——java 之 IO读取文件排序后存入另一文件操作
- 黑马程序员——Java基础---IO(二)---IO字节流、流操作规律
- 黑马程序员 java基础IO操作原则随笔