IO笔记总结

 

IO:输入就是input,输出是output,输入和输出就是某个方向流动的数据流。

Java对数据的操作是通过流的方式。输入和输出是相对于内存而言,将外设中的数据读取到内存中就是输入 ,将内存的数据写入到外设中就是输出。

流按操作数据分为两种:字节流和字符流。

流按流向分为:输入流和输出流。


字符流的由来:

其实就是:字节流读取指定文字字节数据后,不直接操作,而是先查指定的编码表。获取对应的文字。

再对文字进行操作。简单说:字节流+编码表。


字节流的抽象基类:

InputStream,OutPutStre+am。

字符流的抽象基类:

Reader,Writer。

由这四个类派生出来的子类名称都是以父类名作为后缀。

而且子类的前缀名就是该对象的功能。

例:InputStream的子类FileInputStream

Reder的子类FileReader


如果要操作文字数据,优先考虑字符流。

为了提高效率加入了缓冲区,缓冲区的设计使用了装饰设计模式。

字符流缓冲区:

BufferdeWriter:

newLine();

BufferddReader:

readLine();

缓冲区的实现原理:

自定义的读取缓冲区。其实就是模拟一个BufferedReader。

分析:缓冲区中就是封装了一个数组,

并对外提供了更多的方法对数组进行访问。

其实这些方法最终操作的都是数组的指针。

缓冲的原理:

其实就是从源中获取一起数据装进缓冲区中。

再从缓冲区中不断的取出一个一个数据。

在此次取完后,在从源中继续取一批数据放进缓冲区。

当源中的数据取光时,用-1作为结束标记。

-----------------------------------------------------------------

import java.io.FileReader;
import java.io.IOException;

/*
自定义的读取缓冲区。其实就是模拟一个BufferedReader。

分析:缓冲区中就是封装了一个数组,
并对外提供了更多的方法对数组进行访问。
其实这些方法最终操作的都是数组的指针。

缓冲的原理:
其实就是从源中获取一起数据装进缓冲区中。
再从缓冲区中不断的取出一个一个数据。

在此次取完后,在从源中继续取一批数据放进缓冲区。

当源中的数据取光时,用-1作为结束标记。


*/
public class MyBufferReader8 {
	private FileReader r;
//	定义一个数组作为缓冲区。
	private char[] buf = new char[1024];
//	定义一个指针用于操作这个数组中的元素,当操作完最后一个元素后,指针应该归零。
	private int pos = 0;
//	定义一个计数器用于记录缓冲区中的数据个数,当数据减到0,就从源中继续获取数据到缓冲区中。
	private int count = 0;
	
	public MyBufferReader8(FileReader r) {
		this.r = r;
	}
	
	public int myRead() throws IOException{
//		1.计数器为0的时候,从源中获取一批数据到缓冲区中.
		if(count == 0){
			count = r.read(buf);
//			每次获取数据到缓冲区后,角标归零。
			pos = 0;
		}
		if(count<0)
				return -1;

		char ch = buf[pos];
		pos++;
		count--;
		return ch;
	}
	public String myReadLine() throws IOException{
		StringBuilder sb = new StringBuilder();
		int ch = 0;
		while((ch=myRead())!=-1){
			if(ch=='\r')
				continue;
			if(ch=='\n')
				return sb.toString();
			if(sb.length()!=0)
				return sb.toString();
			
//			将从缓冲区中读到的字符,存储到缓存行数据的缓冲区。
			sb.append((char)ch);
		}
		return null;
	}
	public void myClose() throws IOException{
		r.close();
	}
}


-----------------------------------------------------------------

流操作的基本规律:

想要知道开发时用到哪些对象,通过四个明确即可确定。

明确一:明确目的和源

源:InputStream、Reader

目的:OutputStream、Writer

 明确二:明确数据是否是纯文本

源:是纯文本:Reader。不是:InputStream

目的:是纯文本Writer。不是:OutputStream

明确三:明确具体的设备

源设备:

硬盘:File

键盘:System.in

内存:数组

网络:Socket流

目的设备:

硬盘:File

键盘:System.out

内存:数组

网络:Socket流

明确四:是否需要其他功能。

是否需要高效:是,加上Buffer

是否需要对象序列化:ObjectInputStream

是否需要操作基本数据类型:DateInputStream,DateOutputStream

-----------------------------------------------------------------

LineNumberReader:

两个方法:可以读取行号和设置行号。

例:

FileReader fr = new FileReader("c:\\IO.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
lnr.setLineNumber(10);
while((line=lnr.readLine())!=null){
	System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();

-----------------------------------------------------------------

转换流:

InputStreamWriter:字节流通向字符流的桥梁。

OutputStreamWriter:字符转成字节的桥梁。

-----------------------------------------------------------------

File类:用来将文件或者文件夹封装成对象。

方便对文件或文件夹的属性进行操作。

构造函数:File.separator

File对象常见方法:

1.获取:

1.1获取文件名称。

String getName();

1.2获取文件路径.

StringgetPath();

StringgetAbsolutePath();

1.3获取文件大小.

long length();

1.4获取文件修改时间。(判断修改时间,来加载修改后的新文件。)

longlastModified();

2.创建和删除。

booleancreateNewFile();文件不存在就创建,文件存在不创建。

booleandelete();

deleteOnExit();在退出时删除。

File dir = new File("abc\\d\\e");//注意:File对象封装的是e文件夹。

boolean b = dir.mkdir();

boolean b = dir.mkdir();//创建多级目录

boolean b1 = dir.delete();//必须要由内向外删,目录里有内容删除不掉。

3.判断。

文件是否存在。

booleanexists();

booleanisDirectory();//应该先判断是否存在,不存在返回flase

boolean isFile();

4.重命名。

File f1 = new File("c:\\0.txt");

File f1 = new File("d:\\9.txt");

f1.renamenTo(f2);//剪切文件到d盘,并改名为9.txt

5.获取系统根目录和容量

获取所有盘符:

File[] files = File.listRoots();

for(File file : files){

System.out.println(file);

}

getFreeSpace();

getTotalSpace();

6.获取目录内容。

File file = new File("c:\\");

String[] names = file.list();

for(String name : names){

System.out.println(name);

}

打印的是c盘当前目录下所有文件以及文件夹的名称,包括隐藏文件。

调用list方法的File对象中封装的必须是目录,否则会发生空指针异常。

如果目录存在但是没有内容会返回一个数组,但是长度为0.

7.过滤器。

File dir = new File("c:\\");

String[] names = dir.list(new FilterByJava());

for(String name: names){

System.out.println(name);

}

递归:

函数自身直接或者间接的调用到了自身。

一个功能在被重复使用个,并每次使用时参与运算的结果和上一次调用有关。

这时就可以用递归来解决问题。

注意:递归一定要明确条件,否则容易栈内存溢出。

注意递归的次数。次数太多会栈溢出。

小练习:

删除一个带内容的目录。

需要从里往外删,先进行深度遍历。

import java.io.File;
public class DeleteDirTest3 {
	public static void main(String[] args){
		File dir = new File("d:\\dir");
		deleteDir(dir);
	}
	private static void deleteDir(File dir) {
		File[] files = dir.listFiles();
		for(File file : files){
			if(file.isFile()){
				file.delete();
			}else{
				deleteDir(file);
			}
		}
	dir.delete();
}


-----------------------------------------------------------------

Map集合子类Propertiesio流结合。

Map:

|--HashTable

|--Properties(没有泛型)

Properties集合特点:

1.集合中的键和值都是字符串对象。

2.集合中的数据可保存在流中,或从流中获取数据。

通常该集合用于操作以键值对形式存在的配置文件。

Properties集合和流结合使用:

store方法:(持久化)

prop.store(FileOutputStream fos, "name+age");//不能传中文信息。

Load方法:

prop.load(FileInputStream fis);

-----------------------------------------------------------------

序列流:对多个流进行合并。字节流。

构造函数接收枚举类型。

SequenceInputStream(Enumeration en)

使用方法:

将流添加进ArrayList集合,后使用Collections的静态方法。


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

for (int i = 1; i < 4; i++) {

al.add(new FileInputStream(i+".txt"));

}

Enumeration<FileInputStream> e =Collections.enumeration(al);

-----------------------------------------------------------------

PrintStream:

1.提供了打印方法,可以对多中数据类型值进行打印。并保持数据的表现形式。

2.不抛出IOException

构造函数,接收三种类型的值:

1.字符串路径。

2.File对象。

3.字节输出流。

PrintWriter:字符打印流。

构造函数,接收四种类型的值:

1.字符串路径。

2.File对象。

3.字节输出流。

4.字符输出流。

注意:输出流能自动刷新。

PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);

-----------------------------------------------------------------

能操作对象的字节流:

ObjectInputStream:

ObjectOutputStream:

要序列化的对象要实现Serializable接口,启用序列化功能。

对象的默认序列化机制写入的内容是,对象的类,类签名,及非瞬态和非静态字段的值。

数据加transient(短暂的)修饰后不会写入,变为瞬态数据。

静态和瞬态都不会写入。

Serializable:用于给被序列化的类加入ID号。

用于判断类和对象是否是同一版本。

建议所有课序列化类都显示声明serialVersionUID值。

定义方式:

private static final long serialVersionUID = 12345L;

-----------------------------------------------------------------

RandomAccessFile:

不是io体系中的子类。

特点:

1.该对象既能读又能写。

2.内部维护了一个大型 的byte可变长度数组,并通过指针可以操作数组中的元素。

3.可以通过getFilePointer方法获取指针位置,通过seek方法设置指针位置。

4.其实该对象就是将字节输入流和输出流进行了封装。

5.该对象的源或者目的只能是文件,通过构造函数就可以看出。

通常在多线程写入的时候使用

-----------------------------------------------------------------

操作基本数据类型:

DateInputStream,DateOutputStream:

readUTF()和writeUTF()方法,使用指定的utf-8修改版编码表

操作字节数组:

ByteArrayInputStream:

包含一个内部缓冲区。

ByteArrayInputStream(byte[] buf)

ByteArrayOutputStream:

实现了一个输出流,其中的数据被写入一个byte数组,缓冲区会随着数据的不断写入而自动增长。

可使用toByteArray()和toString()获取数据。关闭此流无效(对象没有调用资源,在内存中读写)。

writeTo(OutputStream out):将此byte数组输出流的全部内容写入到指定的输出流参数中,

和使用out.write(buf,o,len)调用该输出流的write方法效果一样。

ByteArrayInputStream bis = new ByteArrayInputStream("abcd".getBytes());

ByteArrayOutputStream bos = new ByteArrayOutputStream();

int ch = 0;

while((ch=bis.read())!=-1){

bos.write(ch);

}

System.out.println(bos.toString());

操作字符数组:

CharArrayReader(源是字符数组)与CharAraryWrite

操作字符串:

SrringReader(源是字符串)与StringWriter

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值