【黑马程序员】java 中的--------------其他流对象

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------




一、IO包中的打印流

1、PrintWriter类继承于Writer基类,,字符打印流

2、构造函数可以接受的参数类型:

a、File对象

b、字符串路径:String类型

c、字节输出流:OutputStream

d、字符输出流:Writer

1、字节打印流:PrintStream类继承于OutputStream

2、构造函数可以接受的参数类型

a、File对象

b、字符串路径:String类型

c、字节输出流:OutputStream

/*							打印流:
字节打印:PrintStream类(构造函数可以接受的对象):
File.   String  .OutputStream out      

字符打印流:PrintWriter类(构造函数可以接受的对象)
File  ,   String  , OutputStream  out   ,Writer

*/

import java.io.*;
class PrintWriterDemo{
	public static void main(String[] args)throws IOException
	{
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	
		//PrintWriter pw=new PrintWriter(System.out);
		
		PrintWriter out=new PrintWriter(new FileWriter("打印流.txt"),true);
		String line=null;
		while((line=br.readLine())!=null){
			//pw.write(line.toUpperCase());
			//因为newLine()是缓冲区的方法,所以
			//pw.println(line.toUpperCase());
			//pw.flush();
			
			out.println(line);
		}
		br.close();
		out.close();
		//pw.close();
	}
}

二、文件的分割


1、建立一个文件字节读取流对象,创建一个字节数组,数组大小三分之一,再通过循环创建输出流对象,并同时创建文件,


/*		对文件进行切割
思路:1,通过建立一个读取流,并且控制byte[]数组的大小
	2.在循环内循环建立输出流对象,
	将每次读到byte[] 数组中的数据写入到每次建立的:FlieOutputStream(" 1.part ")文件中

*/
import java.io.*;
import java.util.*;
class SplitFileDemo{
	public static void main(String[] args)throws IOException
	{
		splitFile();
		
	}	
	//将一个完整的文件,进行切割成多个碎片文件
	public static void splitFile()throws IOException
	{
		FileInputStream fis=new FileInputStream("G:\\IO\\其他流\\SplitFile\\psu.jpg");
		
		FileOutputStream fos=null;
		byte[] b=new byte[1024*24];
		int len=0;
		int count=1;
		while((len=fis.read(b))!=-1){
			fos=new FileOutputStream("G:\\IO\\其他流\\SplitFile\\"+(count++)+".part");
			fos.write(b,0,len);
			fos.close();
		}
		fis.close();
	}
}
三、合并流:SepuenceInputStream类

1、构造函数:SequenceInputStream(Enumeration<? extends InputStream>e)

SequenceInputStream(InputStream s1, InputStream s2)

代码练习:

之合并流:把多个流对象合并成一个流对象
SequenceInoutStream类   继承InputStream类
构造方法摘要 
	SequenceInputStream(Enumeration<? extends InputStream> e) 
           接受一个Enumeration,中存储的流对象
		    Enumeration<E> elements() 
				返回此向量的组件的枚举。
			Vector集合,方法:element();返回一个Enumeration	
	SequenceInputStream(InputStream s1, InputStream s2) 


*/
import java.io.*;
import java.util.*;
class SequenceInputStreamDemo{
	public static void main(String[] args)throws IOException
	{
		Vector<FileInputStream > v=new Vector<FileInputStream >();
		v.add(new FileInputStream("1.txt"));
		v.add(new FileInputStream("2.txt"));
		v.add(new FileInputStream("3.txt"));
		
		Enumeration<FileInputStream > en=v.elements();
		SequenceInputStream si=new SequenceInputStream(en);
	
		FileOutputStream fos=new FileOutputStream("4.txt");
		
		byte[] b=new byte[1024];
		int len= 0;
		while((len=si.read(b))!=-1){
			fos.write(b,0,len);
		}
		si.close();
		fos.close();
	}
}

将分割流和合并流封装成两个功能函数:

import java.io.*;
import java.util.*;
class SplitFileDemo{
	public static void main(String[] args)throws IOException
	{
		//splitFile();
		sequenceInputStream();
	}
	
	//通过SequenceInputStream    合并3个碎片文件的字节流对象
	public static void sequenceInputStream()throws IOException
	{	//因为Vector  低效,所以用ArrayList集合
		ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();
		for(int x=1;x<=3;x++){
			al.add(new FileInputStream("G:\\IO\\其他流\\SplitFile\\"+x+".part"));
		}
		final Iterator<FileInputStream> it=al.iterator();
		
		//建立匿名Enumeration对象,
		Enumeration<FileInputStream>  en=new  Enumeration<FileInputStream>(){
			public boolean hasMoreElements(){
				return it.hasNext();
			}
			public FileInputStream nextElement(){
				return it.next();
			}
		};
		//合并流对象:SequenceInputStream对象
		SequenceInputStream sis=new SequenceInputStream(en);
		
		//建立输出流对象:通过read()方法读到字节数组中的数据写入文件中
		FileOutputStream fos=new FileOutputStream("G:\\IO\\其他流\\SplitFile\\秀云.jpg");
		byte[] b= new byte[1024];
		int len=0;
		while((len=sis.read(b))!=-1){
			fos.write(b,0,len);
		}
		fos.close();
		sis.close();
	}
	
	//将一个完整的文件,进行切割成多个碎片文件
	public static void splitFile()throws IOException
	{
		FileInputStream fis=new FileInputStream("G:\\IO\\其他流\\SplitFile\\psu.jpg");
		
		FileOutputStream fos=null;
		byte[] b=new byte[1024*24];
		int len=0;
		int count=1;
		while((len=fis.read(b))!=-1){
			fos=new FileOutputStream("G:\\IO\\其他流\\SplitFile\\"+(count++)+".part");
			fos.write(b,0,len);
			fos.close();
		}
		fis.close();
	}
}

四、管道流对象

1、PipedInputStream类

PipedOutputStream类

读取流可以直接连接输出流,通过线程进行使用,通过输出流的connect()方法进行连接读取流

注意:不建议在单线程中使用,可能发生死锁

练习代码:

/*管道流,PipedInputStream  和PipedOutputStream  ( void connect(PipedInputStream snk) 
								//将此管道输出流连接到接收者。 )
输出输入直接进行连接,与线程相结合;单线程会死锁

*/
import java.io.*;
//
class Read implements Runnable{
	private PipedInputStream in;
	//接收管道读取流对象
	Read(PipedInputStream in){
		this.in=in;
	}
	public void run(){
		try{
			byte[] b=new byte[1024];
			int len=in.read(b);
			String s=new String(b,0,len);
			
			System.out.println(s);
			in.close();	
			
		}
		catch(Exception e){
			throw new RuntimeException("输入流失败");
		}
	}
}
class Write implements Runnable{
	private PipedOutputStream out;
	//接收一个管道输出流对象
	Write(PipedOutputStream out){
		this.out=out;
	}
	public void run(){
		try{
			Thread.sleep(4000);
			out.write("北京,北京,我来了".getBytes());
			out.close();
		}
		catch(Exception e){
			throw new RuntimeException("输出流失败");
		}
	}
}


class PipedOutputStreamConnectDemo{
	public static void main(String[] args)throws Exception
	{
		PipedInputStream in=new PipedInputStream();
		PipedOutputStream out=new PipedOutputStream();
		
		out.connect(in);//进行管道流连接
		
		Read r=new Read(in);
		Write w=new Write(out);
		//开启线程
		new Thread(r).start();
		new Thread(w).start();
	}
}

五、随机访问文件的读取和写入

1、 RandomAccessFile类,继承Object类,此类实例支持对随机访问文件的读取和写入,

2、 具备读和写的功能,内部封装了数组,而且可以通过指针对数组进行操作

3、 getFilePonter()获取指针的位置

seek()方法可以改变指针的位置

4.       通过查看该类的API,RandomAccessFile(File file,String mode)RandomAccessFile(String name,String mode)发现它的构造函数必须接收一个文件,可以是以字符串的表现形式传入,当然也可以是以File对象类型封装文件的方法传入,另外其第二个参数是必须要传入一个字符串,该字符串传入后,用来表示对文件的读写操作模式的,其可使用值只有四种,如下所示:


“r”: 以只读方式打开。调用结果对象的任何write 方法都将导致抛出IOException
“rw”: 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
“rws”:打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到基础存储设备。
"rwd":打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到基础存储设备。

5.      使用RandomAccessFile对象的write方法是向文件中写入字节数据,而我们打开记事看的的信息不是字节数据,是因为记事本在做了一个解码的动作,将写入的字节码去查平台默认的码表,将码表上对应的字符显示出来。

6.       而使用read的方法是将读取到的是字节码,但是会自动将其提升为int类型的,而提升为int类型。

练习代码:

/*RandomAccessFile类  随机访问文件随机访问文件随机访问文件“另类另类”
1.继承Object类,不属于IO体系,但是是IO包中的成员
2,此类对象支持对随机访问文件的读取写入;
	具备读取和写入的功能,内部封装了一个数组,而且通过指针对数组
	获取指针的位置的方法:getFilePoinrer();
	同时可以通过seek(long pos)设置指针位置
	
其实完成读写的原理就是内部封装了字节输入流和输出流

通过构造函数可以看出,该类只能操作文件
而且操作文件还有模式:“r”只读模式,  "rw"读写模式,..等4种模式

如果模式为“r”,不会创建文件。会去读取已存在的文件,如果该文件不存在,则报错
如果模式“rw”,要操作的文件不存在,会自动创建。如果存在,则不会被覆盖

而且该对象的构造函数要操作的文件不存在,会自动创建。如果存在,则不会被覆盖

注意:可以结合线程将数据分段输出,但保证数据是有规律的
*/
import java.io.*;
class RandomAccessFileDemo{
	public static void main(String[] args)throws IOException
	{
		//writeFile();
		readFile();
	}
	public static void readFile()throws IOException
	{
		RandomAccessFile raf=new RandomAccessFile("G:\\IO\\其他流\\SplitFile\\随机访问.txt","r");
		raf.seek(8);
		
		byte[] b=new byte[4];
		raf.read(b);
		
		String name=new String(b);
		int age=raf.readInt();
		
		System.out.println(name+"--"+age);
		
		/*System.out.println(raf.readLine());*/
	}
	public static void writeFile()throws IOException
	{
		RandomAccessFile raf=new RandomAccessFile("G:\\IO\\其他流\\SplitFile\\随机访问.txt","rw");
		raf.write("李四".getBytes());
		//将int字节4个8位写入
		raf.writeInt(97);
		//文件已在,元文件不被覆盖
		raf.write("万云".getBytes());
		raf.writeInt(99);
		raf.close();
	}
}

六、  File类

File类对象表示的是一个文件或者一个目录路径的抽象表现形式,但我们可以将其看作是一个文件或一个目录,只不过文件被封装成File对象后,可以得到更多更加方便的操作。

1. File 类中的重要字段,separator表示与系统有关的默认目录名称分隔符,出于方便考虑,它被表示为一个字符串。

2.File类中的的创建、删除、修改、获取、查询、判断功能:
创建
createNewFile():当某个File对象调用此方法时,可以创建一个该File对象所表示的文件,如果该文件已经存在,返回false该方法只能创建文件,不能创建目录,

File f = newFile(“g:\\test.log”);

f.createNewFile();

mkdir() 当某个File对象调用此方法时候,可以创建一个该File对象所表示的文件目录,当该文件已经存在时,返回false,如果指定的文件目录的上一级目录不存在,将无法创建,返回为false。

mkdirs()当某个File对象调用此方法时候,可以创建一个该File对象所表示的文件目录,当该文件已经存在时,返回false,如果指定的文件目录的上一级目录不存在,则依然可以创建成功。

删除:

delete()方法,当某个File对象调用此方法时,可以删除该对象所表示的一个文件活一个目录,当次文件或者该目录不存在的时候,返回为false,若要删除的对象是一个非空目录,将无法删除,返回false,需要遍历该目录将该目录下的文件都删除后,才可删除。

deleteOnExit() 在虚拟机终止时,请求删除此File对象所表示的文件或目录。

判断:

isFile()方法用来判断一个File对象所表示的是否为文件,当所表示的文件不存在时,返回为false。

isDirectory()方法用来判断一个File对象多表示的是否为一个文件目录, 当所表示的文件目录不存在时,返回为false。

isHidden()判断File对象所表示的文件或目录是否是一个隐藏类型的,当所表示的文件或目录不存在的时候,返回false。

 

exists()判断File对象所表示的文件或目录是否存在,当所表示的文件或目录不存在的时候,返回false。

List功能:

list():返回一个String[]类型的数组,存储着这个File对象所表示的目录中的文件和目录的名称所组成字符串数组,当该对象为一个文件时,返回null,当所表示的文件目录不存在则抛出空指向异常。

list(FilenameFilter filter)返回String[]数组:一个带有过滤功能的list()方法使用匿名内部内去实现该接口的方式去传递一个FilenameFilter类的对象,但是必须实现其accept()做为过滤的条件,当返回值为true时,遍历到的File对象会被保存带File数组中

获取:

返回String类型-----getPath()获取对象的路径

getAbsolutePath()获取绝对路径

getParent()获取绝对路径的父目录,如果想对路径就返回null

long ---lastModified()    返回文件最后一次修改的时间
long---length() 获取文件大小

renameTo()替换文件名

File[]  ----listFiles()将获取的文件封装成File对象,返回一个File对象的数组

练习代码:

/*文件对象File类
 long   |length() 
          返回由此抽象路径名表示的文件的长度。 
 String[] | list() 
          返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 
 
 String[]| list(FilenameFilter filter) //可以用于文件过滤
          返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。 
			FilenameFilter抽象类:其中只有一个方法-- boolean accept(File dir, String name) 
													测试指定文件是否应该包含在某一文件列表中。 
  

*/

import java.io.*;
class FileDemo{
	public static void main(String[] args)
	{
		//listRootsDemo();
		//listDemo();
		listDemo2();//带参数的list方法
		
	}
	//文件名过滤
	public static void listDemo2()
	{
		File dir=new File("G:\\IO\\OutputStream");//建立文件对象,调用list()有参数的方法
		
		String[] arr=dir.list(new FilenameFilter()//参数接收一个接口的子类对象
		{
			public boolean accept(File dir,String name)//复写boolean accept()抽象方法
			{
				return name.endsWith(".jpg");
			}
		});
		for(String f:arr)
		{
			System.out.println(f);
		}
	}
	/*
	public static void listDemo()
	{
		File f=new File("G:\\IO\\OutputStream");
		
		String[] name=f.list();//方法返回一数组,获取的是指定文件的
					//文件夹和文件的名称,(包括隐私的)
		for(String names:name)
		{
			System.out.println(names);
		}
		
	}
	public static void listRootsDemo(){
	//获取有效排符
		File[] fi=File.listRoots();
		for(File f:fi)
		{
			System.out.println(f);
		}
	}*/
}

递归思想:

嗲吗练习:

/*
	递归应用:函数调用函数本身
	
new 文件对象,打印出目录下的文件或者文件夹中的文件,
也就是遍历指定目录下的所有内容
用到:File[]  |    listFiles() 
          返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
boolean b---isDirectory();判断此文件中是否还有目录

函数自身调用自身==这种表现形式。或者编程手法:称之为递归
注意:1,要限定条件
	2.要注意递归的次数,避免内存溢出
*/


import java.io.*;
class FileDemo1{
	public static void main(String[] args)
	{
		File f=new File("G:\\java");
		showF(f);
		
		getSum(10);
	}
	//打印文件名:只要是文件夹,就调用本函数递归,是文件就打印出来
	public staitc void showF()
	{
		System.out.println(f);//每一次开始遍历文件夹中的的目录是,打印一下文件夹name
		File[] fi=f.listFiles();
		for(x=0;x<fi.length;x++)
		{
			if(fi[x].isDirectory())//;判断此文件中是否还有目录的文件夹
				show(fi[x]);//再把文件夹传递给showF()方法进行遍历
			else
				System.out.println(fi[x]);
		}
		//累加运算1+2+3...100
	public static int getSum(int sum){
		if(sum==1)
			return 1;
		return sum+getSum(sum-1);
	}
}

递归应用2:

/*递归应用:
注意:1,要限定条件
2,要注意递归的次数,防止内存溢出(函数在栈内存中开辟空间,
只有倒数第一个函数运行结束,才会运行倒数第二个函数....依次到第一个函数
,如果次数太多,栈内存装不下,就溢出了)
*/


import java.io.*;
class FileDemo2{
	public static void main(String[] args)
	{
		toBin(6);
		int n=getSum(100);//求和的递归例子
		System.out.println(n);
	}
	public static int getSum(int n)
	{
		if(n==1)
			return 1;
		return n+getSum(n-1);
	}
	//求10进制转2进制的函数
	public static void toBin(int num)
	{
		if(num>0){
			toBin(num/2);//函数自身调用自身
			System.out.println(num%2);
		}
	}
}

递归应用3:打印一个文件夹中的所有文件路径

/*
	需求:打印一个盘中的所有文件名。在每个文件夹的时候,要有层次感
	思路:1.接收一个文件对象,首先打印一次文件名
	2,调用listFiles()返回一个文件数组File[] .遍历数组,
	
*/

import java.io.*;
class FileDemo3{
	public static void main(String[] args){
		File f=new File("G:\\IO\\");
		fileName(f,0);
	}
	public static String getLevel(int level){
		StringBuilder sb=new StringBuilder();
		int y=1;
		for(int x=0;x<level;x++){
			if(level==1)
				sb.append((y++)+":"+"\t"+"\r\n");
			else
				sb.append((y++)+"、");					
		}
		return sb.toString();       
	}
	public static void fileName(File f,int level){
		System.out.println(getLevel(level)+f.getName());
		level++;
		File[] f1=f.listFiles();
		
		for(int x=0;x<f1.length;x++){
			if(f1[x].isDirectory())
				fileName(f1[x],level);
			System.out.println(getLevel(level)+f1[x]);
		}
	}
}



















---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值