您的位置:首页 > 职场人生

黑马程序员----JAVA基础----IO流_1

2015-07-21 10:21 246 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

一、IO流

IO流是用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,而这些操作流的对象都在IO包中。

流按数据操作可分为字节流和字符流(处理文本数据);

a,字节流:读取文字字节的数据

b,字符流:在字节流的基础上,不直接操作而是先查找指定编码表,获取对应的文字。简单说:字符流就是字节流+编码表。

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

a,输入流:从外部设备读数据到内存中。

b,输出流:将内存中的数据写到外部设备上。

二、IO流体系

IO流有四个顶层基类:

字节流抽象基类:InputStream、OutputStream

字符流抽象基类:Reader、Writer

对于IO流体系内的类的名称来说:子类都以父类名作为后缀,子类名的前缀表示该类的功能

三、IO流使用

1,创建一个可以向文件中写入数据的字符输出流对象及一些细节问题

import java.io.FileWriter;
import java.io.IOException;

public class IODemo {

private static final String LINE_SEPARATOR = System.getProperty("line.separator");

public static void main(String[] args) throws IOException{
/*
* 在创建字符流对象时,必须明确与其关联的文件
* 会抛出一个IO异常,原因:可能无法关联
*/
// 用字符输出流关联一个文本文件,文件存在,会覆盖其中的内容,如果该文件不存在,则创建一个文本文件
// 如果需要续写文件,则在构造函数中加入true
FileWriter fw = new FileWriter("demo.txt");
//		FileWriter fw = new FileWriter("demo.txt",true); //使用该流,就可以续写,而不会发生覆盖
// 调用FileWriter中的write()方法,写入数据,数据被写入临时数据缓冲区中
fw.write("abcdefg");
/*
* 换行:在windos系统中换行符:\r\n,在Linux系统中:\n
* 有两种方法,一是+\r\n;一种是用系统提供的方法System.getProperty("line.separator")
* 第二种方法不用考虑系统问题
*/
fw.write("hehe"+"\r\n"+"heihei");
fw.write("hehe"+LINE_SEPARATOR+"heihei");
// 运行flus()方法,将缓冲区的数据刷新到文本文件中
fw.flush();
// 关闭流,关闭资源,关闭前会调用flush刷新缓冲区的数据到文本文件中,因此flush可以省略
fw.close();
// 关闭流后再写入数据,就会引起IOException
//		fw.write("cde");
}

}
2,IO异常处理

import java.io.FileWriter;
import java.io.IOException;

public class IODemo2 {

private static final String LINE_SEPARATOR = System.getProperty("line.separator");

public static void main(String[] args) throws IOException {
// 先创建字符输出流对象
FileWriter fw = null;

try{
// 关联文件操作失败会引发IOException,因此将其放到try block中
fw = new FileWriter("demo.txt");
fw.write("abc"+LINE_SEPARATOR+"def");
}catch(IOException e){
// 处理异常
}finally{		// 表示一定要关闭资源
// 加上判断条件,当fw不为null时才可以关闭,否则会引发NullPointerException
if(fw!=null)
try{
fw.close();
}catch(IOException e){
System.out.println(e.toString());
}
}

}

}

3,读取一个文件,将文件的内容打印到控制台上。

<pre name="code" class="html">import java.io.FileReader;
import java.io.IOException;

public class IODemo3 {

public static void main(String[] args) throws IOException {
// 用读取流关联文件,文件不存在则会引发FileNotFoundException
FileReader fr = new FileReader("demo.txt");
// 读一次
//		show1(fr);
// 循环读取方式
//		show2(fr);
// 使用字符数组,将数据读取到数组中
show3(fr);
fr.close();
}
private static void show3(FileReader fr) throws IOException {
char[] buf = new char[1024];	//一般将数组的大小设为1024,如果数字是固定的,可以将其设置为常量
int len=0;
while((len=fr.read(buf))!=-1){
// 使用String构造函数,将字符数组转换成字符串
System.out.println(new String(buf,0,len));
}
}
private static void show2(FileReader fr) throws IOException {
int ch = 0;
while((ch=fr.read())!=-1){
System.out.print((char)ch);	//使用强制转换,将int转为char类型
}
}
private static void show1(FileReader fr) throws IOException {

int ch = fr.read();				// 用读取流的read()方法读取数据,返回读取到的字符数,读到结尾返回-1
System.out.print((char)ch);	//使用强制转换,将int转为char类型
}

}


4,字符流的缓冲区。缓冲区提高了数据的读写效率,对应类:BufferedReader、BufferedWriter。

缓冲区要结合流才可以使用,在流的基础上对流的功能进行增强。

缓冲区常用方法:readlLine()、newLine()

注意:使用缓冲区一定要使用flusn()方法!!!

使用缓冲区与流结合高效读写数据,并加上异常处理:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedDemo {

public static void main(String[] args) {
// TODO Auto-generated method stub
// 创建缓冲区对象
BufferedReader bufr = null;
BufferedWriter bufw = null;
try{
// 与流相关联
bufr = new BufferedReader(new FileReader("demo.txt"));
bufw = new BufferedWriter(new FileWriter("copydemo.txt"));
String line = null;
// readLine()是读取一行
while((line=bufr.readLine())!=null){
bufw.write(line);
bufw.newLine();			// 换行
bufw.flush();			// 使用缓冲区一定要刷新
}
}catch(IOException e){
System.out.println(e.toString());
}finally{
// 当bufr和bufw不为空时,才可以关闭流
if(bufr!=null)
try{
bufr.close();
}catch(IOException e){

}
if(bufw!=null)
try{
bufw.close();
}catch(IOException e){

}
}
}

}

5,装潢设计模式:对一组对象的功能进行增强时,就可以使用该模式进行问题的解决

装潢和继承都能进行功能的扩展增强,那么二者的区别是什么呢?用继承来进行功能的扩展,

会导致继承体系越来越臃肿,不够灵活。装饰比继承更为灵活

注意:装饰类和被装饰类必须所属同一个接口或者父类!!!

装饰类:BufferedReader、BufferedWriter、LineNumberReader等。

其中LineNumberReader的特有方法:setLineNumber(int index)、getLineNumber()(返回行号)

6,字节流两个常用子类FileInputStream、FileOutputStream,该类的read()方法一次读取一个字节,available()方法可以

返回与其关联文件的字节数

字符流只可以处理文本文件,而字节流既可以处理文本文件,又可以处理非文本文件。

注意在使用BufferedOutputStream时不用使用flush()方法,原因:

字符流底层使用的还是字节流,因为字符流融合了编码表,所以可以读写字符。

字符流写入文本数据时,需要先将文本数据写入字符流中,对照编码表转换成字节数据,然后flush进目的地。

字节流中是字节数据不需要转换,所以可以直接写入目的地。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyMediaDemo {

public static void main(String[] args) throws IOException {
// 方法1
//		show1();
// 方法2
show2();
}

private static void show2() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("Desert.jpg");
FileOutputStream fos = new FileOutputStream("Desert_copy.jpg");
byte[] buf = new byte[1024];
int len = 0;
len=fis.read(buf);
System.out.println(len);
// 如果read()方法里不加数组buf,那么len就是读到的字节的值
// 加上buf后,len表示读进buf的字节数量
//		while((len=fis.read())!=-1){
//			fos.write(buf,0,len);
//		}

while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
}

/**
*
*/
private static void show1() {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 将缓冲区与流相关联
bis = new BufferedInputStream(new FileInputStream("Desert.jpg"));
bos = new BufferedOutputStream(new FileOutputStream("Desert_copy.jpg")
bc76
);
int ch=0;
while((ch=bis.read())!=-1){
/*
* 字符流底层使用的还是字节流,因为字符流融合了编码表,所以可以读写字符。
* 字符流写入文本数据时,需要先将文本数据写入字符流中,对照编码表转换成字节数据,
* 然后flush进目的地。字节流中是字节数据不需要转换,所以可以直接写入目的地
*/
bos.write(ch);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
// 关闭流,释放资源,记着判断流是否为空
if(bos!=null)
try {
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
if(bis!=null)
try {
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

}

7,读取键盘录入的数据并打印在控制台上

InputStreamReader 和 OutputStreamWriter是字节流与字符流之间的桥梁

InputStreamReader:字节到字符的桥梁,解码。

OutputStreamWriter:字符到字节的桥梁,编码。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class KeyDemo {

public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
// 创建字节流接
InputStream in = System.in;
// 读取一次
//		show1(in);
// 无限读取,直到遇到特定标记停止
//		show2(in);
// 通过字节字符桥梁来完成键盘录入及打印操作
show3(in);
// 流关闭后再创建新流会产生异常IOException
//		InputStream in1 = System.in;
//		int ch1 = in.read();
//		System.out.println(ch1);
}

private static void show3(InputStream in) throws IOException {
// InputStreamReader和OutPutStreamWriter是字节流与字符流的桥梁
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String str = null;
while((str=bufr.readLine())!=null){
if("over".equals(str))
break;
bufw.write(str);
bufw.newLine();
bufw.flush();
}
}

private static void show2(InputStream in) throws IOException {
// 创建一个StringBuilder用于接收数据
StringBuilder sb = new StringBuilder();
int ch=0;
while((ch=in.read())!=-1){
// 当回车时,输出键盘录入的内容
if(ch=='\r')
continue;
if(ch=='\n'){
String temp = sb.toString();
// 当输入内容为over时就结束
if("over".equals(temp))
break;
// 将键盘录入数据转成大写输出
System.out.println(temp.toUpperCase());
// 输出数据后清空sb
sb.delete(0, sb.length());
}else
sb.append((char)ch);	// 将ch转换成字符存入sb中
}
}

private static void show1(InputStream in) throws IOException {
int ch = in.read();		// 阻塞式
System.out.println(ch);
in.close();
}

}


8,流的操作规律

a,明确源和目的源:InputStream
Reader目的: OutputStream
Writer

b,明确数据是否是纯文本数据源:是纯文本用Reader,否InputStream
目的:是纯文本用Writer,否OutputStream

c,明确具体的设备源:硬盘(File)、键盘(System.in)、内存(数组)、网络(Socket流)
目的设备与源相同。

d,是否需要额外功能是否需要高效?是,加Buffer

四、File类

用来将文件或文件夹封装成对象,方便对文件和文件夹的属性进行操作,File对象可作为参数传递给流的构造函数。

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;

public class FileDemo {

public static void main(String[] args) throws IOException {
// 可以建一个存在的和不存在的文件或者目录封装成对象
// 构造函数的集中不同形式
File f1 = new File("demo.txt");
File f2 = new File("D:\\JAVA\\Blog\\","demo.txt");
File f3 = new File("D:\\JAVA\\Blog\\");
File f4 = new File(f3,"demo.txt");
// 字段	File.separator 对于不同的操作系统都可以应用
File f5 = new File("D:"+File.separator+"JAVA"+File.separator+"Blog"+File.separator+"demo.txt");
/*
* File类常见方法
* 1,获取:文件名称、大小、路径、修改时间等
* 2,创建与删除
* 3,判断:
*/
// 获取
System.out.println("getName():"+f1.getName());
System.out.println("length():"+f1.length());
System.out.println("path:"+f1.getPath());
System.out.println("absolutePath:"+f1.getAbsolutePath());	//获取绝对路径
System.out.println("lastModified:"+f1.lastModified());
// 创建与删除
File file = new File("aaa.txt");
// 和输出流不一样,如果文件不存在则创建,如果存在就不创建。输出流是在与不在都会创建,在就覆盖
boolean b = file.createNewFile();
boolean b1 = file.delete();	// 删除文件
// 创建目录
File file1 = new File("abc");
boolean b2 = file1.mkdir();
boolean b3 = file1.delete();// 注意:如果要删除的文件内部有其他文件,则无法删除
// 创建多级目录
File file2 = new File("abc\\def\\mnk\\ss");
boolean b4 = file2.mkdirs();
boolean b5 = file2.delete();// 删除的ss文件夹,不会都删除
// 判断
File file3 = new File("demo.txt");
System.out.println(file3.exists());	//是否存在,当文件是未知时,应该先判断是否存在
System.out.println(file3.isDirectory());//是不是目录
System.out.println(file3.isFile());// 是不是文件
// renameTo()
File file4 = new File("demo.txt");
File file5 = new File("DEMO.txt");
File file6 = new File("d:\\demo_copy.txt");
//		file4.renameTo(file5);	//同目录下重命名,
//		file4.renameTo(file6);	//非同文件下,移动并重命名
// listRoots	获取根目录列表
File[] file7 = File.listRoots();
for(File files:file7){
System.out.println(files);
}
//
File file8 = new File("d:\\");
System.out.println(file8.getFreeSpace());	// 盘符的可用空间
System.out.println(file8.getUsableSpace());	// 盘符的可用空间
System.out.println(file8.getTotalSpace());	// 盘符的大小
// list	获取当前目录下的文件及文件夹名称,包含隐藏文件
// 注意:调用list方法的File类对象中封装的必须是目录,否则会发生NullPointerException
// 如果访问系统级目录也会发生NullPointerException
// 如果目录存在但没有内容,会返回一个长度为0的数组
String[] names = file8.list();
for(String name:names){
System.out.println(name);
}
// FilenameFilter 获取指定类型的文件
File file9 = new File("E:\\数据\\BLS900");
String[] strs = file9.list(new FilterByMnd());
for(String str:strs){
System.out.println(str);
}
File[] files = file9.listFiles(new FilterByHidden());
for(File f:files){
System.out.println(f);
}
}

}

class FilterByMnd implements FilenameFilter{
//创建构造函数,可以方便过滤某后缀的文件
//	private String suffix;
//
//	public FilterByMnd(String suffix) {
//		super();
//		this.suffix = suffix;
//	}
//	@Override
//	public boolean accept(File dir, String name) {
//		// TODO Auto-generated method stub
//		return name.endsWith(suffix);
//	}

@Override
public boolean accept(File dir, String name) {
// TODO Auto-generated method stub
return name.endsWith(".mnd");
}

}
class FilterByHidden implements FileFilter{

@Override
public boolean accept(File pathname) {
// TODO Auto-generated method stub
return !pathname.isHidden();
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: