IO


1.处理设备之间的数据传输

2.JAVA对数据的操作通过流的方式

3. JAVA操作流的对象都在IO包中

4.按操作数据分为字节流和字符流(字节流是byte,用于传输数据,字符流是word,用于传输文本,字符流底层封装了字节流,并处理了字节数据,将之每两个用字符集进行一次处理)

5.按流向分为输入流和输出流

->以此为基础的四大IO流抽象基类(ctor属性为protected,不可直接创建对象,必须使用其具体子类创建对象):

Reader

Writer

InputStream

OutputStream

一、常用字符流类型

Writer

 

(一)Writer使用步骤(未处理IO异常)

import java.io.*;

 

FileWriter fout=new FileWriter(“test.txt”);

char[] cbuf=”abcde”.getBytes();

String str=”fghij”;

fout.write(97);

fout.write(‘a’);

fout.write(cbuf);

fout.write(cbuf,1,3);

fout.write(str);

fout.write(str,3,2);

fout.flush();

fout.close();

 

(二)处理IO异常

简单处理方法:抛出:invoker抛出,在函数上 throws IOException

具体处理步骤:

 

//创建对象(但不实例化)应当在try外进行

try{

/*需要处理的代码,通常是涉及底层操作的操作,包括

1.实例化IO对象

2.进行读写操作

3.刷新流

4.关闭流*/

}catch(IOExcepiton e){

 

}finally{

/*必须进行的操作,比如关闭资源

因为finally是一定会进行的操作,而对象实例化可能失败,

所以关闭资源前应当判断下对象是否不为null*/

}

 

(三)方法

1.ctor

a.IO流没有空参数的ctor,必须给流一个输入或者输出的对象。

b.默认是覆盖文件(即将原文件内容清空再写入)。可以通过设置modeltrue变为append在末尾添加

2.write()//write不可在close()之后,关闭流后不可以再读写。

单个字符

1)int ch

字符数组

2)char[] buf

3)char[] buf,int offset,int length

字符串

4)String str

5)String str,int offset,int length

3.flush()//刷新流对象的缓冲中的数据,将之传输到dst中

4.close()//关闭流对象,但是会刷新一次,关闭后不可再进行write操作

 

Reader

(一)使用步骤(未处理IO异常/简单处理: invoker在函数上throws IOException)

//import

FileReader fin=new FileReader(“test.txt”);

int ch;

char[]buf=new char[1024];

int cnt=0;

ch=fin.read();

cnt=fin.read(buf);

String tmp=new String(buf,0,cnt);

fin.close();

(二)方法

1.ctor必须有src

2.read()//不可在close()之后

无参数返回单个字符,若读到文件尾则返回-1

ch=fin.read()

字符数组做参数返回读取字符个数

cnt=fin.read(buf);

3.close()

//简单文本文件复制
import java.io.*;
public class test2 {
	public static void main(String[] args) throws IOException
	{
		FileReader fin=new FileReader("test2.txt");
		FileWriter fout=new FileWriter("test2_copy.txt");
		
		char[] cbuf=new char[1024];
		int cnt=0;
		
		while(-1!=(cnt=fin.read(cbuf)))
		{
			fout.write(cbuf, 0, cnt);
			fout.flush();
		}
		
		
		fin.close();
		fout.close();
	}
}

缓冲区输入输出流(装饰类)

BufferedReader/BufferedWriter/BufferedInputStream/BufferedOutputStream

(一)概述

1.缓冲区概念/缓冲区原理:内部封装了数组

2.BUF提高了对数据的读写效率

3.BUF要结合流才可以使用。

4.增强了流的功能

(二)方法

1.ctor必须带参数,参数为流对象

2.read/write()

3.flush()//使用缓冲区必须记得刷新

4.close()//直接对缓冲区流对象使用close()即可,不需要再另外对缓冲区目标的流对象进行关闭操作

5.newLine()//换行可以使用newLine()替代换行符,此方法可以跨平台

6.readLine()//读取一行,当读到换行符时结束本次读取。返回的内容不包含换行符,如果需要必须手动添加。读到文件尾则返回null。

LineNumberReader/LineNumberInputStream

跟踪行号的缓冲字符输入流

1.readLine()

2.getLineNumber()//获取当前行号

3.setLineNumber()//设置当前行号

 

InputStreamReader/OutputStreamWriter

字符与字节间的转换流

输入转换流InputStreamReader            System.in          in是public staticfinal InputStream in,若想接收成字符需要转换为InputStreamReader,即

new InputStreamReader(System.in)

输出转换流OutputStreamWriter           System.out       out是PrintStream out,若想输出字符需要转换为OutputStreamWriter,即

new OutputStreamWriter(System.out)

 

还可以再用缓冲区的字符流对转换流继续进行装饰newBufferedReader(new InputStreamReader(System.in))

转换流可以设置字符集比如:InputStreamReader(InputStreamin,String charSet)


二、流操作的基本规律

1.明确源和目的

src:输入流InputStream Reader

dst:输出流OutputStream Writer

2.操作的数据是否为文本 是-字符流 否-字节流

3.要使用的具体对象 源设备内存 硬盘 键盘

 

修改默认输入输出设备

System.setIn()/System.setOut()

应用:

1.将错误信息保存到文本文件中:

catch(Exception e){

System.setOut(new PrintStream(“a.txt”));

e.printStackTrace(System.out);

}

2.打印系统信息Properties类

Properties prop=new Properties();

System.setOut(new PrintStream(“a.txt”));

prop.list(System.out);//prop.list(new PrintStream(“b.txt”));

 

 

三、装饰类设计模式

         当想对已有的对象进行功能增强时,可以定义一个类,将已有对象封装。基于已有功能,提供加强功能。

 

装饰类与继承:

装饰类是增强已有对象,具备的功能和已有相同,只是功能更强。

装饰类与被装饰类通常都属于一个体系。

降低了类与类之间的关系

 

继承:自定义,覆盖父类方法。类之间联系紧密

 

 

四、字节流

输入流InputStream/输出流OutputStream

字节流的写入方法write()因为不需要处理字节数据转换为字符不需要刷新,可以直接写入

字节流的读取方法read()使用同字符流相同。

available()//获取可获取的字节的个数,适用于较小的字节流,在构建缓冲区时直接读取。

byte[] buf=newbyte[in.available()];

 

字节流缓冲区BufferedInputStream/BufferedOutputStream

 

模拟字节输入流缓冲区时需要注意有一个强转的问题。

在InputStream的read方法中,一次读取1byte ,8个字节,而java没有unsigned类型,所以如果字节数据内容为1xxxxxxx时,则会表示成负数

为了避免这种情况发生,所以返回值为int,通过提升类型来扩展。得到返回值后将结果与0xff相与,则得到前24位为0后八位为所需的字节数据。避免了误认为负数的情况发生。

 

五、File类

(一)概述

1.描述文件/文件夹 将两者封装成对象。

2.方便对两者的属性信息进行操作

3.File对象可以作为参数传递给流的ctor

4.流只能操作数据,而操作数据所封装成的文件的信息,必须用File对象

5.File类是文件和目录路径名的抽象表示形式

(二)创建一个File对象

不论文件是否已存在都可以创建文件对象。

字段static String separator 目录分隔符:与系统有关的默认名称分隔符,被表示为一个字符串。”c:\\windows” 中“\\”就是分隔符。

 

0       Filef0=new File(“z.txt”);//使用相对路径直接在当前目录下创建文件对象

1       Filef1=new File(“c:\\abc\\a.txt”);//使用绝对路径创建文件对象

2       Filef2=new File(“c:\\abc”,”b.txt”);//两个参数,第一个是目录的路径,第二个是文件名

3       Filefdir=new File(“c:\\abc”);             Filef3=new File(fdir,”c.txt”);//和上一个相比较,第一个参数是将字符串形式的目录路径封装成File对象

4       Filef4=new File(“c:”+File.separator+”abc”+File.separator+”d.txt”);//使用目录分隔符字段来创建对象

 

创建对象时使用的是相对/绝对路径,使用print方法打印出来的就是什么类型的路径

(三)方法

创建:boolean createNewFile()//1.若文件不存在则建立并返回true,已存在则返回false  2.throws IOException

    static File createTempFile(Stringprefix,String suffix)//当前目录下用指定前后缀创建临时文件

    boolean mkdir()//创建对象所示路径的目录

    boolean mkdirs()//如果目录尚不存在则创建

删除:boolean delete()//删除File对象所代表的文件/目录,若是目录则必须目录下文件已清空,才可以删除

            deleteOnExit()//通知JVM退出时删除文件不需要抛出异常,通常用于临时文件

判断canExecute()//能否运行              canRead()//是否可读               canWrite()//是否可写

           isDirectory()//是否为目录          isHidden()//是否为隐藏          isFile()//是否是文件                  isAbsolute()//是否是绝对路径

           boolean exists()//判断文件对象是否已存在

   int compareTo(File pathName)// 按字母顺序比较两个抽象路径名。

查询:getName()            getPath()          getParent                  getAbsoluteFile        getAbsolutePath

    long lastModified()//返回最后修改时间             long length()//返回文件大小

重命名:boolean renameTo(Filedest)//若重命名已存在则false

文件列表

1       静态方法:File[] files=File.listRoots()//返回系统所有盘符

2       String[]list()//列出当前目录下的文件以及目录,包含隐藏文件

3       String[]list(FileFilter filter)//FileFilter是一个接口,有抽象方法accept,使用过滤器需要自己实现接口:

         f.list(newFileFilter(){

                   public booleanaccept(File dir,String name){

                            returnname.endWith(“.zip”);

}

});

4       File[] listFiles()//与2/3不同,返回的是File对象的数组

5       File[]listFiles(FileFilter filter)


六、打印输出流PrintStream/PrintWriter

有许多方便打印的功能:

1.println()方法,比起write方法不需要手动换行

2.boolean autoFlush 标志可以控制是否自动刷新

3.可以将各种数据类型按照原样打印

4.可以直接操作File对象

new PrintWriter(new File(“a.txt”));

创建PrintWriter的ctor可以使用四种参数

1.直接操作File对象

2.String path

3.OutputStream

4.Writer

 

PrintWriter pout=new PrintWriter(newBufferedReader(new FileWriter(“b.txt”)),true);

===============================

150527 add:

PrintWriter和PrintStream不会抛出IO异常

PrintStream也可以直接用文件对象和文件路径字符串创建对象。


七、Properties类

Properties类-HashTable类的子类。

1有Map集合的特点,键值都是String

2是集合中和IO技术相结合的集合容器

3特点:可用于键值对形式的配置文件(java的配置文件的类型就是properties)

方法:

1       setProperty(<key>,<value>);//写入一个键值对

2       getProperty(<key>);//通过键名读取值

3       set<String>stringPropertyName()返回键名集合

4       voidload(Reader/InputStreamin)//从输入流读取所有键值对配置

5       voidstore(Writer/OutputStreamout,String comment)//向输出流输出所有键值对配置,使用完后需要flush()/close()

File f=new File(“config.ini”);
if(!f.exists()){f.createNewFile();}

Properties prop=new Properties();
prop.load(new FileInputStream(f));
int cnt=0;

String times=prop.getProperty(“times”);
if(null!=times){
<span style="white-space:pre">	</span>if(times>max){throw new RuntimeException(“max use times!”);}
	cnt=Integer.praseInt(times);
}

prop.setProperty(“times”,++cnt);
prop.store(new FileOutputStream(f),null);


八、合并流

SequenceInputStream

使用步骤:

1.创建各个输入流

2.创建集合(Vector)按顺序存入各个输入流

3.转换成枚举类型

4.以枚举类型的对象为参数创建SequenceInputStream

5.创建输出流

6.将SequenceInputStream和输出流作为IO的输入输出进行使用

 

创建枚举类型的方法:

1.Vector

Vector<FileInputStream> v=newVector<FileInputStream>();

 

v.add(new FileInputStream(“a.txt”));

v.add(new FileInputStream(“b.txt”));

v.add(new FileInputStream(“c.txt”));

 

Enumeration<FileInputStream> e=v.elements(); 

SequenceInputStream sis=new SequenceInputStream(e)

2.匿名内部类

ArrayList<FileInputStream> al=newArrayList<FileInputStream>();

//al.add(…);

Iterator<FileInputStream>itor=al.iterator();

SequenceInputStream sis=newSequenceInputStream(new Enumeration<FileInputStream>(){

         publicboolean hasMoreElements(){ return itor.hasNext();}

         publicFileInputStream nextElement(){return itor.next();}

});

 

切割文件:使用缓冲区数组的大小作为切割的依据。


九、对象流

直接操作对象的流ObjectInputStream/ObjectOutputStream//将堆中的对象保存到硬盘

被操作的对象须要实现标记接口Serialize

方法:

1       ctor           ObjectInputStream(InputStream in)//须要传入一个输入流作为参数

2       写入方法         write(…)//写入的是8bit的字节数据

                                     writeInt(…)//写入的是一个32位的int

                                     writeObject()//写入一个对象

3       读取方法         read(…)//读取8bit的字节数据

                                     readInt()//读取一个32位的int值

                                     readObject()//读取一个对象//须处理一个ClassNotFoundException的异常

在使用writeObject时:

1.不修改类,只修改对象的属性值,则使用writeObject方法后将覆盖原对象

2.修改类后,使用writeObject会新写入一个对象,而不是覆盖原有对象

判断类是否被修改的依据:类的uid      -        类的所有对象的序列号

如果想将修改后的类强制固定为原来的类。则可以通过自定义UID来实现:

任意修饰符 static finallongserialVersionUID=42L;

注意静态成员不会被序列化,若不想让某个非静态成员被序列化,则使用修饰符transient

 

若想从流中循环读取对象,不会正常结尾,须要通过捕获EOPException来结束循环


十、管道流

PipedInputStream/PipedOutputStream

注意连接的顺序,应当是输出作为参数传递给输入

new PipedInputStream(PipedOutputStreampout)

通常通过多线程使用。数据由某个线程从PipedInputStream读取,并由其他线程写入到相应的PipedOutputStream中,

管道输入流包含一个buf,可以在buf的范围内将rw操作分开。

 

PipedInputStream提供输出的线程不再存在,则认为管道损坏

 

线程启动的先后顺序不重要,因为read是阻塞式方法


十一、基本数据和数组的流

操作基本数据类型的流DataInputStream/DataOutputStream

操作数组的流(内存)ByteArrayInputStream…

这类流的特点:

1不涉及底层操作

2不会抛出IO异常

3关闭无效

4关闭后仍可以使用

 

操作数组的流:

输入流需要一个字节数组作为输入的ctorByteArrayInputStream(byte[] buf)

输出流不需要,内部封装了一个可变长度的数组,其缓冲区会随着写入内容的增加而增大。

若想获取输出流缓冲区的内容不是使用flush()

而是使用toByteArray()/toString()来获取。

 

类似的流:CharArrayReader/CharArrayWriter

                     StringReader/StringWriter



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值