---------------------- android培训、java培训、期待与您交流! ----------------------
1. 创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件,而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
fw.write("abcde");调用write方法,将字符串写入到流中。还未写入到硬盘
fw.flush();刷新流对象中的缓冲中的数据,将数据刷到目的地中。
fw.close();关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据,将数据刷到目的地中。和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
2. 标准IO异常的处理方式:
import java.io.*;
class FileWriterDemo2{
public static void main(String[] args) {
FileWriter fw = null;
try{
fw = new FileWriter("demo.txt");
fw.write("abcdefg"); }
catch (IOException e) {
System.out.println("catch:"+e.toString());}
finally{
try{
if(fw!=null) //fw对象可能创建不成功
fw.close(); }
catch (IOException e){
System.out.println(e.toString());}} }}
3. FileWriter fw = new FileWriter("demo.txt",true);
传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
4. windows中,写入文件换行符:\r\n linux中换行符:\n
5.字符操作应用操作系统默认编码。
6.BufferedWriter特有方法:newLine()
BufferedReader特有方法:readLine()达到流末尾时,返回null。返回的数据不包括换行符。
7. 装饰设计模式:当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。如:缓冲流BufferedWriter、BufferedWriter的扩充方法。
自定义示例:
class Person{
public void chifan(){
System.out.println("吃饭"); }}
class SuperPerson {
private Person p ;
SuperPerson(Person p) {
this.p = p; }
public void superChifan(){
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
System.out.println("来一根"); }}
class PersonDemo{
public static void main(String[] args) {
Person p = new Person();
//p.chifan();
SuperPerson sp = new SuperPerson(p);
sp.superChifan(); }}
装饰模式比继承要灵活。避免了继承体系臃肿,而且降低了类于类之间的关系。
装饰类增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。
如:BufferedReader(Reader in)可以接受所有实现Reader接口的类,并调用增强功能。如果使用继承,则要分别对实现Reader接口的类实现其缓冲子类,并重写read方法。
8. LineNumberReader类继承了BufferedReader类,它定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。 默认情况下,行编号从 0 开始。该行号随数据读取在每个行结束符处递增,并且可以通过调用 setLineNumber(int) 更改行号。但要注意的是,setLineNumber(int) 不会实际更改流中的当前位置;它只更改将由 getLineNumber() 返回的值。
LineNumberReader实现原理:定义一个int类型的行计数器,并通过方法 setLineNumber(int) 和 getLineNumber()设置和取得。每当用readLine()方法读取一行时,行计数器自增一。
9.字节流读取相对于字符流特有的方法:
public static void readFile_3()throws IOException{
FileInputStream fis = new FileInputStream("fos.txt");
// int num = fis.available();返回文件二进制数据位数
byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用在循环了。
fis.read(buf);
System.out.println(new String(buf));
fis.close();}
此方法要慎用。注意不能操作太大的文件,如视频文件。
10.用二进制流方法读取键盘输入:
import java.io.*;
class ReadIn{
public static void main(String[] args) throws IOException{
InputStream in = System.in;
StringBuilder sb = new StringBuilder();
while(true){
int ch = in.read();
if(ch=='\r') continue;
if(ch=='\n'){
String s = sb.toString();
if("over".equals(s))
break;
System.out.println(s.toUpperCase());
sb.delete(0,sb.length()); }
else
sb.append((char)ch);
} }}
11.利用转换流,获取键盘录入的字符流,并转换成大写字母输出到控制台:
import java.io.*;
class TransStreamDemo{
public static void main(String[] args) throws IOException {
//键盘的最常见写法。 InputStream in
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
// System.out为二进制流,将它转换成字符流
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line=bufr.readLine())!=null) {
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush(); }
bufr.close(); }}
注:转换流可以指定编码输出字符。
Windows系统默认编码为GBK。如果向文件写入字符时是以UTF-8,则读取其中的数据时要用转换流转换成系统默认字符(不能用FileReader)。
12.重定向练习:
1)将键盘录入的数据保存到一个文件中(利用转换流,高效方式)。
BufferedReader isr=new BufferedReader(
new InputStreamReader(System.in));
System.setOut(new PrintStream("test.txt"));
while(true){
String str=isr.readLine();
if(str.equalsIgnoreCase("over"))
break;
System.out.println(str.toUpperCase());}
注意:关闭流。
2)将一个文本数据打印在控制台上(利用转换流,高效方式)。
字节流法:
System.setIn(new FileInputStream("Demo.java"));
BufferedInputStream isr = new BufferedInputStream(System.in);
BufferedOutputStream bw = new BufferedOutputStream(System.out);
byte[] b = new byte[32]; int len = 0;
while ((len = isr.read(b)) != -1) {
bw.write(b, 0, len);
bw.flush(); }
转换流的应用,字符流法:
System.setIn(new FileInputStream("Demo.java"));
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
String str;
while(( str=br.readLine())!=null){
bw.write(str);
bw.newLine();
bw.flush(); }
注意:关闭流。
练习:有五个学生,每个学生有3门课的成绩,从键盘输入以上数据(包括姓名,三门课成绩),输入的格式:如:zhagnsan,30,40,60计算出总成绩,并把学生的信息和计算出的总分数高低顺序存放在磁盘文件"stud.txt"中。
13 .打印流:PrintStream的构造参数可以传递File对象,字符串,OutputStream对象,字符编码。它还提供了打印各种基本数据类型的方法以及打印对象的方法。具体详见API。
14. 流合并类SequenceInputStream:
构造方法:
SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时
类型为 InputStream 对象的 Enumeration 型参数。
SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
方法:
int available()
返回不受阻塞地从当前底层输入流读取(或跳过)的字节数的估计值,方法是通过下一次调用当前底层输入流的方法。
void close() 关闭此输入流并释放与此流关联的所有系统资源。
int read() 从此输入流中读取下一个数据字节。
int read(byte[] b, int off, int len) 将最多 len 个数据字节从此输入流读入 byte 数组。
此类只有这些方法及构造器。
15.文件剪切示例:
public static void splitFile()throws IOException{
FileInputStream fis = new FileInputStream("c:\\1.bmp");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int count = 1;
while((len=fis.read(buf))!=-1){
fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
16.序列化流:ObjectInputStream和ObjectOutPutStream。类中包括常用的读取和写入各种
数据类型的方法以及一些其他方法。
如果一个可序列化的类有多个父类,则所有父类要么是可序列化的,要么有无参构造器。否则,在反序列化时,会抛出InvalidClassException(原因疯狂讲义P723)。
如果某个类的属性是另一个类的引用,那么这个类必须是可序列化的。否则,拥有该属性的类不可序列化。
静态修饰成员不会被序列化。
序列化原理:序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化
类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因是计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修饰符显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于直接声明类 -- serialVersionUID 字段作为继承成员没有用处。
特殊方法:void write(int val) 写入一个字节,即整形的最后一个字节。
---------------------- android培训、java培训、期待与您交流! ----------------------