黑马程序员——Java高新技术——IO流(上)

点击打开链接 点击打开链接 点击打开链接 android培训、<a">点击打开链接 点击打开链接 java培训、期待与您交流!">点击打开链接 点击打开链接

IO(Input  Output)流

l IO流用来处理设备之间的数据传输

l Java对数据的操作是通过流的方式

l Java用于操作流的对象都在IO包中

l 流按操作数据分为两种:字节流与字符流

l 流按流向分为输入流、输出流

 

IO流常用基类

l 字节流的抽象基类

     InputStream    OutputStream

l 字符流的抽象基类

     Reader     Writer

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

 

Writer:写入字符流的抽象类

Writer的重要方法:

Writer  append(char c):将指定字符添加到此Writer

Writer  append(CharSequence csq):将指定字符序列添加到此Writer。注:CharSequence所有已知实现类:CharBufferSegmentStringStringBuffereStringBuilder

Writer  append(CharSequence ,int start,int end):将指定字符的子序列添加到此Writer

abstract void  close():关闭此流,但要先刷新它

abstract void  flush():刷新该流的缓冲

void         writer(char[] cbuf):写入字符数组

abstract void  writer(char[] cbuf,int off,int len):写入字符数组的某一部分

void         writer(int c):写入单个字符

void         writer(String str):写入字符串

void         writer(String str,int off,int len):写入字符串的某一部分。

 

    Writer是抽象类不能创建对象,只能创建他的子类对象,通过API查找,找到一个子类OutputStream的子类FileWriterFileWriter是写入字符文件的便捷类,专门用于操作文件。

   创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。其构造方法的参数有(File file)(String fileName,boolean append)(String fileName)(String fileName,boolean append)

特有方法:

String  getEncoding():返回此流使用的字符编码名称,如果流已经关闭,则返回null.

Writer练习

import java.io.*;
class Test28  //Writer练习 
{
	public static void main(String[] args) throws Exception
	{
		//创建一个FileWriter对象,该对象一初始化必须要明确被操作的文件
		//而且该文件会被创建到指定目录下,如果该目录下已有同名文件,将会被覆盖。
		//其实该步就是在明确数据要存放的目的地。
		FileWriter fw=new FileWriter("Demo.txt");
		//调用write方法,将字符串写入到流中。
		fw.write("abcdr");
		//刷新流对象中的缓冲中的数据
		//将数据刷到目的地中
		fw.flush();
		//关闭流资源,但是关闭之前会刷新一次缓冲中的数据,将数据刷到目的地中
		//和flush的区别是:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
		fw.close();
	}
}

文件的续写

   当已有文件?.txt,再把它传入FileWriter里面进行操作时,会覆盖原有的文件,如果我们的本意是要在源文件的末尾添加数据,这时就需要:

FileWriter fw=new FileWriter(“??.txt”,true);

传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据的续写

注:/r/n:在记事本中表示换行,记事本不能识别/n.

 

Reader:用于读取字符流的抽象类。

Reader重要方法:

abstract void  close():关闭该流并释放与之关联的所有资源

void         mark(int readAheadLimit):标记流中的当前位置

boolean       markSupported():判断此流是否支持mark()操作

int           read():读取单个字

int           read(char[] cbuf):将字符读入数组,返回读入字符数。

abstract int    read(char[] cbuf,int off,int len):将字符读入数组的某一部分

int           read(CharBuffer target):试图将字符读入指定的字符缓冲区

boolean      ready():判断是否准备读取此流。

Void         reset():重置该流。

long        skip(long n):跳过字符

 

子类InputStream的子类FileReader

特有方法:

String  getEncoding():返回此流使用的字符编码名称

 

构造方法可传入的参数(File file)(String filename)

FileRead fr=new FileRead(“demo.txt”);

  创建一个文件读取流对象,和指定名称的文件相关联。要保证该文件是已经存在的,如果不存在会发生异常:FileNofoundExceptiom

 

文件读取的两种方法

int/read():一次读取一个字符,会自动往下读,如果已达到文件的末尾会返回-1.

while((ch=fr.read())!-1)

{

   System.out.print(“ch=”+ch);

}

int / read(char[] c):换回文件读取的字符数

char[] buf=new char[1024];

while((num=fr.read(buf))!=-1)

{

   System.out.println(new String(buf,0,num));

}

IO异常的处理  

import java.io.*;
class Test29 
{
	public static void main(String[] args) 
	{
		FileReader fr=null;
		try
		{
			fr=new FileReader("Test30.java");
		    char[] buf=new char[1024];
		    int num;
		    while((num=fr.read(buf))!=-1)
		    {
			   System.out.println(new String(buf,0,num));
		    }
		}
		catch (IOException e)
		{ 
			System.out.print(e);
		}
		finally
		{
			try
			{ 
                if(fr!=null)
				fr.close();
			}
			catch (IOException e)
		    { 
			   System.out.print(e);
		    }
		}

	}
}


 

 

字符流的缓冲区:缓冲区的出现提高了对数据的读写效率

对应类

l BufferedWrtter

l BufferedReader

 

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

 

BufferedWrtter

新方法:newLine():换行。跨平台的换行符

BufferedReader

新方法:String / readLine():读取一个文本行。读到末尾则返回空——null,不会返回回车符,也就是不会换行。

 

装饰设计模式

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类成为装饰类。

装饰类:通常会通过构造方法接收被装饰对象,并基于被装饰对象的功能,提供更强的功能。

装饰模式比继承要灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常是属于一个体系的。

 

BufferedReader的子类LineNumberReader中有2个特有的方法:

方法:getLineNumber():获取当前行号

      setLineNumber():设置当前行号

T

//制作一个自己个LineNumberReader类
import java.io.*;
class Test31 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr=new FileReader("Test29.java");
		MyLineNumberReader ml=new MyLineNumberReader(fr);
       // String str=null;
		//while((str=ml.myReadLine())!=null)
		//{
		//	System.out.println(ml.mygetLineNumber()+":"+str);
		//}
		ml.mysetLineNumber(100);
		for(String str1=ml.myReadLine();str1!=null;str1=ml.myReadLine())
		{
			System.out.println(ml.mygetLineNumber()+":"+str1);
		}
		ml.close();
	}
}

//自己的LineNumberReader类
class MyLineNumberReader extends BufferedReader
{
   //设置一个行号变量
	private int lineNumber=0;
	//构造函数要传入其他流
	MyLineNumberReader(Reader in)
	{
		//父类中已经完成此事,只要调用父类构造函数
		super(in);
	}

    //写特有的myReadLine方法是为了每调用一次,行号+1.
	public String myReadLine() throws IOException
	{
		lineNumber++;
		return super.readLine();
	}

    public void mysetLineNumber(int lineNumber) 
	{
        this.lineNumber=lineNumber;
	}

	public int mygetLineNumber() 
	{
        return this.lineNumber;
	}

}

 

字节流:

 OutputStream:输出流

重要方法

Void  close():关闭此输出流并释放与此流有关的所有系统资源

Void  flush():刷新此输出流并强制写出所有缓冲的输出字节

Void  write(byte b):

Void  write(byte[] b,int off,int len)

Abstract void write(int b):

 

子类FileOutputStream:用于写入诸如图像数据之类的原始字节的流

构造方法与FileWriter相同。

 

特有方法:

protected void / finalize():清理到文件的连接,并确保在不再引用此文件输出流时调用此流的close方法。

FileChannel  /  getChannel():返回与此文件输出流有关的唯一FileChannel对象

FileDescriptor / getFD():放回与此流有关的文件描述

 

InputStream:输入流

重要方法:

void      /    close():关闭该流并释放与之关联的所有资源

void      /    mark(int readlimit):标记流中的当前位置

boolean    /   markSupported():判断此流是否支持markreset方法

abstract int  /  read():读取单个字节

int        /   read(byte[] b):将字节读入数组

int        /   read(byte b,int off,int len):将字节读入数组的某一部分

boolean   /   ready():判断是否准备读取此流。

long      /  skip(long n):跳过n个字节

void     /   reset():将此流重新定位到最后一次对此输入流调用mark方法时的位置

int      /    available():返回此输入流下一个方法调用可以不受阻塞地从此输入流(或跳过)的估计字节数。

 

子类FileInputStream用于读取诸如图像数据之类的原始字节流

其构造方法与FileReader相同。

 

特有方法:

protected void/ finalize():确保在不再引用此文件输入流时调用此流的close方法。

FileChannel  /  getChannel():返回与此文件输入流有关的唯一FileChannel对象

FileDescriptor / getFD():放回与此流有关的文件描述

 

缓冲区的字节流:是FilterInputStreamFilterOutputStream的子类

BufferedOutputStream:该类实现缓冲的输出流。

两个构造函数:BufferedOutputStream(OutputStream  Out)BufferedOutputStream(OutputStream out,int size):创建具有指定缓冲区大小的BufferedOutputStream.

 

BufferedInputStream:该类实现缓冲的输入流

两个构造函数:BufferedInputStream(InputStream in),BufferedInputStream(Input Stream in,int size):创建具有指定缓冲区大小的BufferedInputStream.

 

自定义字节流缓冲区

 

读取键盘录入:

System.out:对应的是标准输出设备,控制台。

System.in:对应的是标准输入设备,键盘

 

转换流:在字符流中

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

OutputStreaWriter:是字符通向字节的桥梁。

通常的用法:键盘录入打印在控制台上

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));

System里的静态方法:setIn(InputStream in):重新分配标准输入流

                    setOut(printStream out):重新分配标准输出流

 

流操作的基本规律:

1.明确源和目的

源:输入流:InputStream Reader

目的:输出流:OutputStreamWriter

 

2.操作的数据是否是纯文本

是:字符流

不是:字节流

 

3.当体系明确后,再明确使用哪个具体的对象

 源设备:内存,硬盘,键盘

 目的设备:内存,硬盘,控制台

 

示例:

1.将一个文本文件中数据存储到另一个文件中,复制文件

  源是文本文件,用Reader,设备是:硬盘上的一个文件,用FileReader

  目的是纯文本文件,用Writer,设备:硬盘,一个文件。用FileWriter

 是否需要提高效率,是,加入Reader体系中缓冲区 BufferedReader\BufferedWriter

 

2.将一个图片文件中数据存储到另一个图片文件中,复制图片

  源是图片文件,非纯文本,用InputStream,设备是:硬盘上的一个文件,用FileInputStream

  目的是图片文件,用OutputStream,设备:硬盘,一个文件。用FileOutputStream

是否需要提高效率,是,加入缓冲区 BufferedInputStream\BufferedOutputStream

 

3.需求:将键盘录入的数据保存到一个文件中

  源是纯文本:Reader,设备:键盘,对应对象System.in,System.in对应的是字节流,为了操作键盘的文本数据方便,转成字符流按照字符串操作是最方便的,用InputStreamReader。需要提高效率吗,需要:BufferedReader

目的:硬盘的纯文本文件,FileWriter。需要提高效率吗,需要:BufferedWriter

 

扩展:把录入数据按照指定编码表(utf-8),将数据存到文件中。

目的是硬盘上的一个文件,用FileWriter

但是存储时,需要加入指定编码表utf-8,指定编码表只有转换流可以指定,使用OutPutStreamWriter。而该转换流对象要接收一个字节输出流,而且还可以操作文件的字节输出流。fileOutputStream

 

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“d.txt”)”UTF-8”)

通常涉及到字符编码转换时需要用到转换流。

 

异常的日志信息保存在文件中,printStackTrace(printStream s)

printStream类:OutputStream的子类FilterOutputStream的子类,为其他输出流添加了功能,使他们能够方便地打印各种数据值表现形式。

构造方法传入的参数有(File file)(OutputStream out)(String FileName)

 

重要方法:

打印

void /  print():可以传入各种基本类型包括对象

Void / pritln():打印各种数据类型,并换行

Void / writer(byte[] buf,int,off,int len):

Void / writer(int b):

 

Properties:可以与流相结合的集合

Properties prop=System.getProperties()

Prop.list(System.out);

 

 

File

l 用来将文件或者文件夹封装成对象

l 方便对文件与文件夹的属性信息进行操作

l File对象可以作为参数传递给流的构造函数

 

创建对象

File f1=new File(“1.txt”);1.txt封装成对象,可以将已有的和未出现的文件或者文件夹封装成对象。

File f2=new File(“c:\\abc”,“1.txt”):父目录,文件名

File d=new File(“c:\\sgh”);

File f3=new File(d,“1.txt”):

Sop(f1):打印的是文件路径,传入的是什么路径就打印什么路径。

separator字段:跨平台的分隔符.用的时候File.separator.

 

方法:

1.创建

boolean   /  createNewFile():在指定位置创建文件,如果该文件已存在则不创建,返回false。和输出流不一样,输出流对象一建立就创建文件,而且文件已经存在,会覆盖。

static File / createTempFile(String prefix,Stirng suffix):在默认临时文件中创建一个空文件,使用给定前缀和后缀生成其名。

static File / createTempFile(String prefix,Stirng suffixFile directory):在默认临时文件中创建一个空文件,使用给定前缀和后缀字符串生成其名。

boolean / mkdir():创建此抽象路径指定的目录

boolean / mkdirs():创建此抽象路径指定的目录,包括所有必须但不存在的父目录

 

2.删除

  boolean / delete():删除失败返回false

  void   / deleteOnExit():退出时删除指定文件

 

3.判断

 boolean / canExecute():文件是否能执行

 boolean / canRead():文件是否能读

 boolean / canWrite():文件是否能写

 int   / comparaTo(File pathname):按字母顺序比较两个抽象路径

 boolean  / exists():文件是否存在

boolean   / isDirectory():在判断文件是否是文件或目录时,必须要先判断文件是否存在。

boolean /  isFile():是否是文件

boolean /  isHidden():是否是隐藏文件

Boolean /  isAbsolute():是否是绝对路径

 

4.获取信息

 String  /     getName():获取文件名字

 String  /    getPath():获取文件路径

 String  /   getParent():该方返回的是绝对路径中的父目录,如果获取的是相对路径则返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。

 String  /   getAbsolutePath():获取绝对路径

 long  /  lastModified():返回文件最后一次被修改的时间

 long  /  length():返回文件长度

 Boolean / renameTo(File dest):重命名

Static File[]  listRoots():列出可用的文件系统根

String[]  list():指定目录下文件或文件夹的名称,包含隐藏文件。调用list方法的file对象必须是封装了一个目录,该目录必须存在。

String[]  list(FilenameFilter filter):FilenameFilter是一个接口,里面只有一个方法boolean  /  boolean accept(File dir,String neme)

File[]   /  listFiles():获取目录下的所有文件和目录

File[]  /   listFiles(FilenameFilter filte):获取目录下符合条件的目录

 

/*  题目:列出目录下所有文件的内容
    思路:1.首先要创建一个File对象把目录当做参数传递给构造函数
	      2.File对象的listFiles可以用于列出目录下的所有文件和目录
		  3.判断一下如果列到目录,则列出目录中的内容
   
*/
import java.io.*;
class  ListFileDemo
{
	public static void main(String[] args) 
	{
		File file=new File("G:\\java");
		myList(file,0);
	}
	//把题目要求封装成函数
	public static void myList(File file,int count)
	{
		System.out.println(kongge(count)+file.getName());
		count++;
		//把目录下的文件和文件放到文件数组中。
		File[] files=file.listFiles();
		for(int i=0;i<files.length;i++)
		{
			if(files[i].isDirectory())
				myList(files[i],count);  //利用递归的思想,如果文件是目录,将再次运行本函数本函数
			else
			System.out.println(kongge(count)+files[i]。getName());//目录下的几级文件就会打印几个空格。
		}
	}

	//传入个数返回多少空格。
	public static String kongge(int count)
	{
		String str="";
		for(int i=0;i<count;i++)
		{
			str=str+" ";
		}
		return str;
	}
}


 

 

递归:函数自身调用自身的表现形式或编程手法

1.限定条件

2.要注意递归的次数,避免内存溢出。

 

练习:删除一个带内容的目录

 

//删除带内容的文件夹
import java.io.*;
class DelDirDemo
{
	public static void main(String[] args) 
	{
		File f=new File("G:\\迷茫");
		delDir(f);
	}
	public static void delDir(File dir)
	{
		File[] files=dir.listFiles();
		for(int i=0;i<files.length;i++)
		{
			if(files[i].isDirectory())
			   delDir(files[i]);
			else
               files[i].delete();
		}
		dir.delete();//最后不能忘了把目录删掉
	}
}


Propertieshashtable的子类。也就是说它是map集合的特点。而且它里面存储的键值对都是字符串。是集合与IO技术相结合的容器。

该对象的特点:可以用于键值对形式的配置文件。

那么在加载数据时,需要数据有固定形式,k=v.

 

重要方法:

设置和获取元素。

Object / setProperty(String key,String value):设置键值对,返回指定键的旧值,没有则返回null

String / getProperty(String key):根据键获取键值对

Set<String> / StringPropertyName():返回此属性列表的键集

void / list(PrintStream out):将属性列表输出到指定的输出流

void / list(PrintWriter out):将属性列表输出到指定的输出流

void / load(InputStream in):从输入流中读取属性列表

void / load(Reader reader):按简单的面向行的格式从输入字符流中读取属性列表。

void / store(OutputStream out,String Comments):将列表值写入到输出流

void / store(Writer writer,String comments):将列表写入到输出字符。

 

练习:想要将文件中数据存到集合中进行操作

1.用一个流和文件相关联

2.读取一行数据,将该行数据用=进行切割

3.等号左边为键,右边为值,存入到Properties集合

import java.io.*;
import java.util.*;
class PropertiesDemo  //Properties类的练习
{
	public static void main(String[] args) throws IOException
	{
		//proToFile();
         fileToProp();
	}
	public static void proToFile() throws IOException
	{
		
		Properties prop=new Properties();
		prop.setProperty("lisi","85");
		prop.setProperty("zhangsan","52");

		FileWriter fw=new FileWriter("properties.txt");
		prop.store(fw,"=");
		fw.close();
	}
	public static void fileToProp() throws IOException
	{
		BufferedReader br=new BufferedReader(new FileReader("p1.txt"));
        Properties pr=new Properties();
		for(String str=br.readLine();str!=null;str=br.readLine())
		{
			String[] strs=str.split("=");
			pr.setProperty(strs[0],strs[1]);
		}
		System.out.println(pr);
		br.close();
	}
}


 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值