IO

-------android培训 java培训  、期待与您交流-------

IO流
  • Java对数据的操作是通过流的方式
  • IO流用来处理设备之间的数据传输
  • Java用于操作流的对象都在IO包中
  • 流按操作数据分为两种:字节流与字符流。
  • 流按流向分为:输入流,输出流。
  • 字节流的抽象基类:
    • InputStream ,OutputStream
  • 字符流的抽象基类
    • ReaderWriter
字符流
Writer
Writer是写入字符流的顶层类。
Writer中定义的方法:
write(): 向流中写入数据,写入的数据可以是单个字符,字符串或字符串的某一部分,字符数组或字符数组的某一部分,
flush(): 刷新流中的数据,将数据写入到目的地。
close(): 关闭流资源,但是在关闭之前会先刷新流。
FileWriter 
FileWriter是Writer的间接子类,主要用于操作文本文件。

IO异常处理方式
代码示例:
FileWriter fw = null;
try {
	fw = new FileWriter("z://heima.java");
	fw.write("java");
	fw.flush();
} catch (IOException e) {
	System.out.println(e.toString());
} finally {
	try {
		// 如果指定的路径不存在,则FileWriter初始化失败,fw=null,不能调用close()方法。此处必须进行非空判断。
		// 如果有多个流资源的关闭动作,必须对每个流资源的关闭动作进行非空判断。
		if (fw != null) {
			fw.close();//关闭流资源的动作一定要被执行,所以放在finally块中
		}
	} catch (IOException e) {
		System.out.println(e.toString());
	}
}

文本文件的两种读取方式
方式一:一个字符一个字符的读,读取一个字符输出一个字符
int read():  读取单个字符。返回字符所对应的整数,如果读到流的末尾,则返回-1。
示例代码:
FileReader fr = new FileReader("FileWriterDemo.java");
int ch = 0;
while ((ch = fr.read()) != -1) {
	System.out.print((char) ch);
}
fr.close();
方式二:每读取一个字符就存入数组中,然后将数组中的字符输出。
int read(char[] cbuf): 将字符读入数组。返回读取的字符数,如果读到流的末尾,则返回-1。
代码示例:
FileReader fr = new FileReader("FileWriterDemo.java");
char[] buffer = new char[1024];
int num = 0;
while ((num = fr.read(buffer)) != -1) {
	System.out.print(new String(buffer, 0, num));
}
fr.close();

 

字符流的两种拷贝方式
拷贝方式一:读一个字符就写入一个字符到流中
示例代码:
FileWriter fw = new FileWriter("heima.java");
FileReader fr = new FileReader("FileReaderDemo1.java");
int ch = 0;
while ((ch = fr.read()) != -1) {
	fw.write(ch);
}
fw.close();
fr.close();
拷贝方式二:一直读并存入到缓冲区,再一并写入
示例代码:
FileWriter fw = new FileWriter("heima.java");
FileReader fr = new FileReader("CopyFileDemo.java");
char[] buffer = new char[1024];// 创建一个缓冲
int len = 0;
while ((len = fr.read(buffer)) != -1) {
	fw.write(buffer, 0, len);// 写入有效数据
}
fw.close();
fr.close();

拷贝文本文件图列

字符流的缓冲区
  • 缓冲区的出现提高了对数据的读写效率。
  • 对应类
    • BufferedWriter
      • void newLine(): 写入一个行分隔符。
    • BufferedReader
      • String readLine(): 读取一个文本行。返回包含该行内容的字符串,不包含任何行终止符。如果达到流的末尾则返回null。
  • 缓冲区要结合流才能使用。
  • 在流的基础上对流的功能进行了增强。
使用缓冲区的注意事项:
1    先有流对象,才有缓冲区。
2    使用缓冲区,必须调用flush()方法进行刷新。

字节流
字节流的拷贝方式
方式一:自定义一个缓冲区 byte数组 的方式读写数据
示例代码:
FileOutputStream fos = new FileOutputStream("d:\\2.jpg");
FileInputStream fis = new FileInputStream("d:\\1.jpg");
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
	fos.write(buf, 0, len);
}
fos.close();
fis.close(); 
方式二:通过Java提供的缓冲区对象读写数据
示例代码:
BufferedOutputStream bufos = new BufferedOutputStream(
		new FileOutputStream("d:\\3.jpg"));
BufferedInputStream bufis = new BufferedInputStream(
		new FileInputStream("d:\\1.jpg"));
int b = 0;
while ((b = bufis.read()) != -1) {
	bufos.write(b);
}
bufos.close();
bufis.close();
读取键盘录入
System.in:  对应的是标准的输入设备,键盘。
System.out:  对应的是标准的输出设备,控制台。
示例代码:
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();
		System.out.println(s.toUpperCase());
		sb.delete(0, sb.length());
	} else {
		sb.append((char) ch);
	}
}
改变标准输入输出设备
System.setIn(InputStream in):             重新分配标准输入流。
System.setOut(OutputStream out):        重新分配标准输出流。

转换流

InputStreamReader:    是字节流通向字符流的桥梁
OutputStreamWriter : 是字符流通向字节流的桥梁


 
//获取键盘录入对象
InputStream in = System.in;
// 将字节流对象转成字符流对象,使用转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(in);
// 为了提高效率,将字符流进行缓冲区技术高效读取,使用BufferedReader
BufferedReader bufr = new BufferedReader(isr);
// 键盘录入最常见写法
BufferedReader bufr1 = new BufferedReader(new InputStreamReader(System.in));
OutputStream out = System.out;
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);
// 简写格式:
BufferedWriter bufw1 = 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();
流操作规律
通过三个明确来完成。
1,明确源和目的。
	源:输入流。InputStream  Reader
	目的:输出流。OutputStream  Writer。
2,操作的数据是否是纯文本。
	是:字符流。
	不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
	通过设备来进行区分:
	源设备:  内存ArrayStream  硬盘FileStream  键盘System.in
	目的设备:内存ArrayStream  硬盘FileStream  控制台System.out
4,如果要提高效率则使用缓冲区
5,如果要用指定编码存储数据则使用转换流	
 
 
 
异常的日志信息
示例代码:
try {
	int[] arr = new int[2];
	System.out.println(arr[3]);
} catch (Exception e) {
	try {
		Date d = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		String s = sdf.format(d);
		PrintStream ps = new PrintStream("exeception.log");
		ps.println(s);
		System.setOut(ps);
	} catch (IOException ex) {
		throw new RuntimeException("日志文件创建失败");
	}
	e.printStackTrace(System.out);
}
File类
File类继承自Object类,是文件和目录路径名的抽象表现形式。
用来将文件或文件夹封装成对象。
方便对文件和文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数。

File类的字段和构造函数:
String File.separator :                    与系统有关的目录分隔符,在windosXP系统中代表“\\”
File(File parent ,String child):      根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例
File(String pathname):                   通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例
File(String parent,String child):      根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

代码示例:
//将a.txt封装成File对象,可以将已有的和未出现的文件或文件夹封装成对象
Fiel f1 = new File("a.txt");
File f2 = new File("c:\\abc","b.txt");
File d = new File("c:\\abc");
File f3 = new File(d,"c.txt");
File类的常见方法:
1,创建
boolean createNewFile():
在指定位置创建文件,如果创建成功,返回true.如果该文件已经存在,则不创建,返回false.
和输出流不一样,输出流对象一建立就创建文件,而且文件已经存在,会覆盖原文件。
static File createTempFile(String prefix,String suffix):
在默认临时文件目录创建一个空文件,使用给定的前缀与后缀生成其名称。
static File createTempFile(String prefix,String suffix,File directory)
在指定目录创建一个空文件,使用给定的前缀与后缀生成其名称。
2,删除
boolean delete():              删除指定文件,删除成功返回true,删除失败返回false.
void deleteOnExit():         在程序推出时删除指定文件。即使程序中途出现异常导致程序停止,也会删除。

3,判断
boolean exists():              判断文件或目录是否存在。
boolean isFile():               判断是否是文件
boolean isDirectory():      判断是否是目录
boolean isHidden():         判断是否是隐藏文件或目录
boolean isAbsolute():      判断此抽象路径名是否为绝对路径名,无论此文件或文件夹已经被创建。

4,获取信息
String[] list():  
返回指定目录中的所有文件和目录的名称,包含隐藏的。调用list方法的file对象必须是封装了一个目录,并且该目录必须存在,否则将引发NullPointException
String[] list(FilenameFilter filter): 返回指定目录中的经过过滤的所有文件和目录的名称
示例代码:列出d盘下Java目录中(不包含子目录)的所有bmp文件
File dir = new File("d:\\Java");
String[] arr = dir.list(new FilenameFilter()
{
    public boolean accept(File dir,String name)

    return name.endsWith(".bmp");
});

File[] listFiles():  返回当前目录下所有的文件和目录对象
示例代码:
File dir = new File("c:\\");
File[] files = dir.listFiles();
for(File f ,files)
{
    System.out.println(f.getName()+"::"+f.getLength());

}
static File[] listRoots():  返回系统根目录。
5,比较
int compareTo(): 按字母顺序比较两个抽象路径名。

 
打印流
该流提供了打印方法,可以将各种数据类型的数据都原样打印。
可以直接操作流和文件,并可指定是否自动刷新流中的数据。
PrintWriter
构造函数可以接收的参数类型:
  •   file对象          File
  •   字符串路径。String 
  •   字节输出流。OutputStream
  •   字符输出流。Writer
PrintStream
构造函数可以接收的参数类型:
  •   file对象          File
  •   字符串路径。String
  •   字节输出流。OutputStream
合并流
SequenceInputStream 对多个流进行合并
SequenceInputStream 表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。  
构造方法:
SequenceInputStream(Enumeration<? extends InputStream> e):
SequenceInputStream(InputStream s1,InputStream s2):
 
代码示例:
文件合并,将1.txt  2.txt  3.txt文件合并成4.txt文件
通过Vector存储流对象,效率低
Vector<InputStream> v = new Vector<InputStream>();
v.add(new FileInputStream("c:\\1.txt"));
v.add(new FileInputStream("c:\\2.txt"));
v.add(new FileInputStream("c:\\3.txt"));
Enumeration<InputStream> en = v.elements();
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
	fos.write(buf, 0, len);
}
fos.close();
sis.close();
通过ArrayList存储流对象
ArrayList<InputStream> al = new ArrayList<InputStream>();
al.add(new FileInputStream("c:\\1.txt"));
al.add(new FileInputStream("c:\\2.txt"));
al.add(new FileInputStream("c:\\3.txt"));
final Iterator<InputStream> it = al.iterator();
Enumeration<InputStream> en = new Enumeration<InputStream>() {
	public boolean hasMoreElements() {
		return it.hasNext();
	}
	public InputStream nextElement() {
		return it.next();
	}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
	fos.write(buf, 0, len);
}
fos.close();
sis.close();
序列流
被操作的对象需要实现Serialzzable(标记接口)

ObjectOutputStream
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。

ObjectInputStream
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时可以为应用程序提供对对象图形的持久存储。
ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。
 
序列化的作用:
将对象的信息从栈内存中移到硬盘中,实现了对象的持久化存储。
被序列化的对象通常在硬盘中的存储格式:对象名.Object

被transient关键字修饰的非静态成员不能被序列化
静态成员不能被序列化,因为静态成员在方法区,而对象在栈内存中。

当类中自定义了序列化标识:static final long serialVersionUID = 42L; 后
则新的类还能操作曾经被序列化的对象。

管道流
输入输出可以直接进行连接,通过结合线程使用。
  • PipedInputStream
    • 管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏 
  • PipedOutputSteam
    • 可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。
RandomAccessFile
  • RandomAccessFile类不是IO体系中的成员,而是直接继承自Object.但是它是IO包中的成员,因为它具备读和写功能。
  • 内部封装了一个大型数组,而且通过指针对数组的元素进行操作。
  • 可以通过getFilePointer获取指针的位置,同时可以通过seek改变指针的位置。
  • 随机访问文件,自身具备读写的方法。
  • 通过skipBytes(int x),seek(int x)来达到随机访问
  • 读写原理:内部封装了字节输入流和输出流
  • 局限性:RandomAccessFile类只能操作文件,且只有4种模式
  • r: 只读模式,不会创建文件,会读取一个已存在的文件,如果该文件不存在,则会出现异常。
  • rw:读写模式,操作的文件不存在,会自动创建,如果文件存在则不会覆盖。
其他流对象

操作基本数据类型
DataInputStream 与DataOutputStream

操作字节数组
ByteArrayInputStream 与ByteArrayOutputStream
代码示例:
ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEF".getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int by = 0;
while((by=bis.read())!=-1){
    bos.write(by);
}

操作字符数组
CharArrayReader与CharArrayWrite

操作字符串
StringReader 与StringWriter
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值