java基础-IO流

IO流是用来处理不同设备之间数据传输的。不同的流表示的是不同的输入输出设备。

0.File

(1)File是对文件对象的封装。File是对文件的属性,大小,位置,可读性等文件的信息的疯传的类。

(2)File表示的文件或者文件夹

(3)File可以作为参数传递给流的构造函数

1.一个重要的属性:文件分隔符File.separator

public static void test6(){
    String s = File.separator;
    System.out.println(s);//\
}

具有跨平台的特性

public static void test6(){
	//File f = new File("C:\\Users\\huer\\Desktop\\text1.java");
	File f = new File("C:"+File.separator+"Users"+File.separator+"huer\\Desktop\\text1.java");
}

2.File常见操作

(1)创建文件或文件夹f.createNewFile()

        文件存在的话就不创建了。与流有区别:写入流一定会创建文件(可以控制覆盖和续写)

返回一个boolean值,表示创建成功或者失败。

(2)删除

delete()

deleteOnExit() 退出的时候删除(用于临时文件的删除)

(3)判断文件是否存在

boolean exists()

这个是经常与IO流一起使用的,比如读入流,读的文件是必须存在的,所以可以用这个方法进行判断。

。。。。。

使用:

package cn.bishe.solrj;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class SolrJManager {
	public static void main(String[] args) throws IOException {
		/*String separator = File.separator;
		File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a.txt");
		System.out.println(f.getAbsolutePath());//C:\Users\huer\Desktop\a.txt
		System.out.println(f.isFile());
		System.out.println(f.isDirectory());
		System.out.println(f.isAbsolute());//true
		System.out.println(f.exists());//false
		*/
		
		/*String separator = File.separator;
		File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a.txt");
		boolean flag = f.createNewFile();
		System.out.println(flag);//true
		System.out.println(f.exists());//true
		*/
		
		/*String separator = File.separator;
		File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a"+separator+"a.txt");
		boolean flag = f.mkdirs();
		System.out.println(f.getAbsolutePath());//C:\Users\huer\Desktop\a\a.txt
		System.out.println(f.exists());//true
		System.out.println(f.getName());//a.txt
		System.out.println(f.getPath());//C:\Users\huer\Desktop\a\a.txt
		*/
		
		/*String separator = File.separator;
		File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a");
		String[] list = f.list();//列出文件名字集合
		for(String s :list){
			System.out.println(s);//a.txt
		}*/
		
		
		//文件过滤
		/*String separator = File.separator;
		File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a");
		String[] list = f.list(new FilenameFilter(){
			public boolean accept(File dir, String name) {
				//这里只过滤文件名结尾是.txt的
				return name.endsWith(".txt");
			}	
		});
		System.out.println(f.length());//文件没有长度,文件夹有
		for(String s :list){
			System.out.println(s);
		}*/
		
		
		//f.list()与f.listFiles()区别
		//返回的一个是String[]集合,一个是File[]集合
		
		
		/*String separator = File.separator;
		File f = new File("C:"+separator+"Users"+separator+"huer"+separator+"Desktop"+separator+"a");
		File[] list2 = f.listFiles(new FilenameFilter(){
			public boolean accept(File dir, String name) {
				//这里只过滤文件名结尾是.txt的
				return name.endsWith(".txt");
			}	
		});
		System.out.println(list2.length);
		for(File s :list2){
			System.out.println(s.getName());
			System.out.println(s.length());
		}*/
		
	}
	
		//递归得到指定目录下文件的内容
		//递归打印指定目录下的全部文件
		//参数传进来的是路径
		public static void showp(File dir){
			//打印路径
			System.out.println(dir);
			File[] files = dir.listFiles();
			for(File f:files){
				if(f.isDirectory()){
					showp(f);
				}else{
					System.out.println(f);//打印的文件就是文件完整路径
					System.out.println(f.getName());//只会打印文件的名字
				}
			}
		}
}

打印出带有层次的文件的结构

public class Demo {
	public static void main(String[] args) throws IOException{
		File file = new File("D:\\files\\数据库");
		getFile(file,0);
	}
	//打印空格数目
	public static String getKonge(int level){
		StringBuilder s = new StringBuilder();//可以不断追加的容器
		s.append("|--");//每次调用在结尾加|
		for(int i=0;i<level;i++){
			s.insert(0," ");//每次调用在最前面添加level个空格
		}
		return s.toString();
	}
	//打印出文件目录树结构
	public static void getFile(File file,int level){
		System.out.println(getKonge(level)+file);
		level ++;
		File[] f = file.listFiles();
		for(File ff:f){
			if(ff.isDirectory()){
				getFile(ff,level+1);
			}else{
				System.out.println(getKonge(level+1)+ff);
			}
		}
	}
}

显示的数据格式:

|--xxx

     |--xxx


递归删除文件,不删除隐藏文件:

public static void removeFile(File dir){
		File[] files = dir.listFiles();
		for(File f:files){
			if(!f.isHidden() && f.isDirectory()){
				removeFile(f);
			}else if(!f.isHidden() && !f.isDirectory()){
				f.delete();
			}
		}
		//删除目录
		dir.delete();
	}
	public static void main(String[] args) throws IOException{
		File f = new File("C:\\Users\\huer\\Desktop\\b");
		removeFile(f);
	}

迭代指定目录下的文件,找出所有的文件名字,将所有的文件名字放置到一个List中,然后将文件名字统一的放到一个文本文件中:

//将指定文件名放到List中
	public static void fileToList(File dir,List<File> list){
		File[] files = dir.listFiles();
		for(File f:files){
			if(f.isDirectory()){
				fileToList(f,list);
			}else{
				if(f.getName().endsWith(".java")){
					list.add(f);
				}
			}
		}
	}
	
	//将List中的文件名字放到一个文件中
	public static void writeToFile(List<File> list,String fileName){
		BufferedWriter bw = null;
		try{
			bw = new BufferedWriter(new FileWriter(fileName));
			for(File f:list){
				bw.write(f.getAbsolutePath());
				bw.newLine();
				bw.flush();
			}
		}catch(Exception e){
			throw new RuntimeException("写入文件发生异常");
		}finally{
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					throw new RuntimeException("写入流关闭异常");
				}
			}
		}
	}
	
	public static void main(String[] args) throws IOException{
		File f = new File("C:\\Users\\huer\\Desktop\\a");
		List<File> list = new ArrayList<File>();
		String fileName = "C:\\Users\\huer\\Desktop\\text.txt";
		fileToList(f,list);
		writeToFile(list,fileName);
	}
}
/*
 * 硬盘上的文件结构:
 * a----a1.java/a2.java/c(c1.java/c2.java)
 * 
 * 运行结果:
 * 	C:\Users\huer\Desktop\a\a1.java
	C:\Users\huer\Desktop\a\a2.java
	C:\Users\huer\Desktop\a\c\c1.java
	C:\Users\huer\Desktop\a\c\c2.java
 */

一、字符流

(1)数据的存储都是二进制的形式。字符流是基于字节流的。也就是二进制byte字节到文本,所以文本的话就涉及到编码的问题。

(2)父类接口:Reader、Writer

(3)因为涉及到文本,所以有关于String的读写,看下面具体的介绍。

(一)文件

1.FileReader

(1)构造函数参数:(1)String(2)File

(2)读取的文件必须存在,不存在就会抛出异常

(3)常见操作:read()/read(char[])

       close()关闭之前不会刷新缓冲区

2.FileWriter

(1)构造函数参数:(1)String(2)File

(2)两种形式:文件覆盖/文件续写:文件不存在会创建,文件存在的时候默认的是文件覆盖,在构造参数加true实现文件续写

FileWriter f = new FileWriter("a.txt");//文件会覆盖

FileWriter f = new FileWriter("a.txt",true);//文件不会覆盖,续写

(3)常见操作:writer(char[]/String/int),flush

       close(关闭之前会先刷新缓存区)

(4)换行符:windows下默认的是\r\n,一般不会单独使用

3.例子

使用read(char[] )都文件的时候有换行符,所以写过去的时候不用写换行符。

public static void main(String[] args) {
		//从文件读,读进char[],然后写进文件
		FileReader fr = null;
		FileWriter fw = null;
		try{
                        //读的文件必须存在
			fr = new FileReader("C:\\Users\\huer\\Desktop\\text1.java");
			fw = new FileWriter("C:\\Users\\huer\\Desktop\\text2.java");
			char[] ch = new char[1024];
			int num = 0;
			while((num = fr.read(ch))!=-1){
				fw.write(ch, 0, num);//写进去实际的长度
				fw.flush();//每写进去一点就进行刷新
			}
		}catch(Exception e){
			throw new RuntimeException("文件读写失败");
		}finally{
			if(fr != null){
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

(二)缓冲流

使用在基础流上,为了提高效率的。关闭的时候只需要关闭最外层的缓冲流,基础流就不需要管了。

1.BufferedWriter

(1)构造函数参数:Writer

(2)常用方法:writer(int/char[]/String),flush,close

(3)尤其推荐的方法:newLine()换行符,可以跨平台

2.BufferedReader

(1)构造函数参数:Reader

(2)常用方法:read()/read(char[]),readLine(),close()

        readLine()不会读到换行符,所以一般是和newLine()一起使用的

(3)尤其推荐的方法:readLine()读取一行,但是不会读取终止符,换行符这些

3.例子

public static void test4(){
		BufferedReader br = null;
		BufferedWriter bw = null;
		try{
			br = new BufferedReader(new FileReader("C:\\Users\\huer\\Desktop\\text1.java"));
			bw = new BufferedWriter(new FileWriter("C:\\Users\\huer\\Desktop\\text2.java"));
			String line = "";
			while((line = br.readLine()) != null){
				bw.write(line.toUpperCase());
				bw.newLine();//写入换行符
				bw.flush();
			}
		}catch(Exception e){
			throw new RuntimeException("键盘读取发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("键盘读入发生异常");
				}
			}
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					throw new RuntimeException("控制台写入发生异常");
				}
			}
		}
	}

关闭的时候只需要关闭最外层的缓冲流。

4.LineNumberReader(BufferedReader子类),用来显示行号

(1)构造函数参数:Reader

(2)常用方法:readLine(),setLineNumber(),getLineNumber()

public static void test4(){
		LineNumberReader br = null;	
		try{
			br = new LineNumberReader(new FileReader("C:\\Users\\huer\\Desktop\\text1.java"));
			String s = "";
			while((s = br.readLine())!= null){
				System.out.println(br.getLineNumber()+":"+s);
			}
		}catch(Exception e){
			throw new RuntimeException("文件读写发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("关闭读入发生异常");
				}
			}
		}
	}


知识点

(1)解释字符流为什么要flush()?

因为字符设计到编码的问题,不能立刻输出到目的地,需要缓存一下,所以需要刷新。

(2)字符流涉及到文本,所以有读写String的操作

二、字节流

操作的是字节,比如图片传输。父类接口:输入流InputStream,输出流OutputStream。

(一)文件

1.FileInputStream

(1)构造函数参数:(1)String(2)File

(2)常用方法:read()/read(byte[])

(3)特别的方法:得到流中字节大小:available(),但是这个方法也不常用

2.FileOutputStream

(1)构造函数参数:(1)String(2)File

(2)常用方法:write(int/byte[]),close,flush

public static void test6(){
		FileInputStream fi = null;
		FileOutputStream fo = null;
		try{
			fi = new FileInputStream("C:\\Users\\huer\\Desktop\\图片\\a.jpg");
			fo = new FileOutputStream("C:\\Users\\huer\\Desktop\\图片\\b.jpg");
			byte[] b = new byte[1024];
			int len = 0;
			while((len=fi.read(b))!= -1){
				fo.write(b,0,len);//为了保险起见,这里最好写上flush()
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(fi != null){
				try {
					fi.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
			if(fo != null){
				try {
					fo.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

(二)缓冲流

1.BufferedInputStream

(1)构造函数参数:InputStream

(2)常用方法:read()/read(byte[]) 

        因为没有中文,所以没有读String的方法

2.BufferedOutputStream

(1)构造函数参数:OutputStream

(2)常用方法:write(int)/write(byte[])

知识点

字节流,操作的是byte,所以没有String的读写

三、转换流(字节流转为字符流)

转换流出现的原因?

(1)字符流最多只能以字节数组的形式读写,如果想使用BufferedReader/BufferedWriter的String的读写来提高效率的话,可以使用转换流。将字节流转为字符流。起点和终点还是原来的,只不过对流进行了包装,提高效率。

(2)编码的问题。使用转换流可以传入编码格式。


1.InputStreamReader

(1)构造函数参数:InputStream

(2)构造函数参数注意:可以传入编码参数

2.OutputStreamWriter

(1)构造函数参数:OutputStream

(2)构造函数参数注意:可以传入编码参数

(3)标准输入in:System.in---->InputStream

        标准输出out: System.out--->PrintStream(父类是OutputStream)

public static void test3(){
		BufferedReader br = null;
		BufferedWriter bw = null;
		try{
			br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\Users\\huer\\Desktop\\text1.java")));
			bw = new BufferedWriter(new OutputStreamWriter(System.out));
			String line = "";
			while((line = br.readLine()) != null){
				bw.write(line.toUpperCase());
				bw.newLine();//写入换行符
				bw.flush();
			}
		}catch(Exception e){
			throw new RuntimeException("键盘读取发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("键盘读入发生异常");
				}
			}
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					throw new RuntimeException("控制台写入发生异常");
				}
			}
		}
	}

转换流,指明编码

public static void test3(){
		BufferedReader br = null;
		BufferedWriter bw = null;
		try{
			br = new BufferedReader(new InputStreamReader(System.in));
			//可以放进去英文,也可以中文,写入文件默认使用的编码就是GBK
			bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\huer\\Desktop\\text2.java"),"GBK"));
			//写入文件编码使用utf-8会出现乱码
			//bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\huer\\Desktop\\text2.java"),"utf-8"));
			String line = "";
			while((line = br.readLine()) != null){
				if("over".equals(line)){//从键盘读,应该有结束的时候
					break;
				}
				bw.write(line.toUpperCase());
				bw.newLine();//写入换行符
				bw.flush();
			}
		}catch(Exception e){
			throw new RuntimeException("键盘读取发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("键盘读入发生异常");
				}
			}
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					throw new RuntimeException("控制台写入发生异常");
				}
			}
		}
	}

四、标准输入输出流

1.System.in(键盘):InputStream

2.System.out(控制台):PrintStream(它是OutputStream子类)

public static void test2(){
		BufferedReader br = null;
		BufferedWriter bw = null;
		try{
			br = new BufferedReader(new InputStreamReader(System.in));
			bw = new BufferedWriter(new OutputStreamWriter(System.out));
			String line = "";
			while((line = br.readLine()) != null){
				if("over".equals(line)){//键盘需要有结束的时候
					break;
				}
				bw.write(line.toUpperCase());
				bw.newLine();//写入换行符
				bw.flush();
			}
		}catch(Exception e){
			throw new RuntimeException("键盘读取发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("键盘读入发生异常");
				}
			}
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					throw new RuntimeException("控制台写入发生异常");
				}
			}
		}
	}

readLine()没有换行符,所以写的时候要加上,使用BufferdWriter的newLine()或者Println():

public static void test1() {
		BufferedReader br = null;
		try{
			br = new BufferedReader(new InputStreamReader(System.in));
			String line = "";
			while((line = br.readLine()) != null){//readLine不会读到换行符的
				if("over".equals(line)){//从键盘读没有读到结尾的时候
					break;
				}
				System.out.println(line.toUpperCase());//但是这里会打印出换行出来
			}
		}catch(Exception e){
			throw new RuntimeException("键盘读取发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
键盘读,写入文件:
public static void test3(){
		BufferedReader br = null;
		BufferedWriter bw = null;
		try{
			br = new BufferedReader(new InputStreamReader(System.in));
			bw = new BufferedWriter(new FileWriter("C:\\Users\\huer\\Desktop\\text2.java"));
			String line = "";
			while((line = br.readLine()) != null){
				if("over".equals(line)){//键盘读取需要有结束的时候
					break;
				}
				bw.write(line.toUpperCase());
				bw.newLine();//写入换行符
				bw.flush();
			}
		}catch(Exception e){
			throw new RuntimeException("键盘读取发生异常");
		}finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					throw new RuntimeException("键盘读入发生异常");
				}
			}
			if(bw != null){
				try {
					bw.close();
				} catch (IOException e) {
					throw new RuntimeException("控制台写入发生异常");
				}
			}
		}
	}

知识点:

可以改变标准输入输出:

System.setIn(InputStream in)

System.setOut(PrintStream out)

InputStream in = System.in; PrintStream out = System.out


知识点:

字符流比字节流的一个优点是可以read一个String,字节流最多就是数组。

五、输出流:PrintStream与PrintWriter

1.区别

(1)PrintWriter的父类是Writer,PrintStream的父类是OutputStream。

(2)一个是字符流,一个是字节流,都没有对应的输入流。

(3)PrintStream的构造函数参数:OutputSream/File/String;

(4)PrintWriter的构造函数参数:OutputSream/File/String/Writer

(5)构造函数参数都可以设定自动刷新,都可以打印各种类型的数据

2.PrintWriter使用优先于BufferedWriter的原因

(1)PrintWriter输出的目的地可以是:String,File,OutputStream,Writer多样化

(2)PrintWriter可以设定自动刷新,但是如果使用BufferedWriter的话需要flush()

(3)BufferedReader读readLine(没有终止符)的时候,PrintWriter的println可以直接把终止符传输过去,比BufferedWriter的newLine()简单

//暂时不考虑从键盘输入停止的情况,暂时不考虑编码的问题
	public static void test() throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(System.out,true);//自动刷新
		String s = null;
		while((s = br.readLine())!= null){
			pw.println(s);//有换行符或者终止符
		}
		br.close();
		pw.close();
	}

PrintWriter的构造函数参数可以是Buffered,提高效率:

//暂时不考虑从键盘输入停止的情况,暂时不考虑编码的问题
	public static void test() throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("C:\\Users\\huer\\Desktop\\text.txt")),true);//自动刷新
		String s = null;
		while((s = br.readLine())!= null){
			pw.println(s);//输出终止符
		}
		br.close();
		pw.close();
	}

六、IO流输出异常信息

(1)异常输出流

printStackTrace(PrintStream s) 

printStackTrace(PrintWriter s) 

public static void test6(){
		try{
			int i = 1/0;
		}catch(Exception e){
			try {
				Date date = new Date();
				SimpleDateFormat df = new SimpleDateFormat("yyyy-mm-dd");
				String newDate = df.format(date);
				PrintStream ps = new PrintStream("C:\\Users\\huer\\Desktop\\text2.java");
				//先在流里面写上当前日期
				ps.println(newDate);
				//然后设置标准输出流
				System.setOut(ps);
				
			} catch (FileNotFoundException e1) {
				throw new RuntimeException("日志文件创建失败");
			}	
			e.printStackTrace(System.out);
		}
	}
	/*
	 * 2018-35-16
	java.lang.ArithmeticException: / by zero
	at Test.test6(Test.java:158)
	at Test.main(Test.java:176)
	 */

七、系统信息集合Properties,集合与IO流结合的集合

Properties集合的数据结构:key-value

(1)Properties类,父类是Hashtable,是一个Map,不是IO流框架中的。

(2)是IO流与集合结合使用的集合

(3)注意的使用是通过IO流,加载并输出配置文件信息。但是在Web项目中关于配置文件都是框架自动管理的

从IO流中读取数据进Propeties集合:load(InputStream/Reader)

Propeties集合中的属性信息输出到IO流:store(OutputStream/Writer)

(4)Properties配置信息类与IO流使用的例子

a.配置文件控制用户登录次数(可以作为一个工具类)

登陆次数控制,使用Properties的例子:public static void test() throws IOException{
		Properties p = new Properties();
		File file = new File("C:\\Users\\huer\\Desktop\\text.ini");
		if(!file.exists()){
			file.createNewFile();
		}
		FileInputStream fi = new FileInputStream(file);
		//将流中数据存储到属性文件集合中
		p.load(fi);
		int count = 0;
		
		String value = p.getProperty("time");//读取配置信息
		if(value != null){
			count = Integer.parseInt(value);
			if(count >= 5){
				System.out.println("免费使用次数已经到期,请付费使用!");
				return;
			}	
		}
		
		count++;
		//修改配置信息,这里会覆盖掉原来存在的key-value
		p.setProperty("time", count+"");
		FileOutputStream fo = new FileOutputStream(file);
		
		p.store(fo,"" );//重新写回文件
		fi.close();
		fo.close();
	}

b.读取一个文件进Properties集合,然后存储进另一个文件

public static void test5(){
		FileReader f = null;
		Properties prop = new Properties();
		OutputStream os = null;
		try{
			f = new FileReader("C:\\Users\\huer\\Desktop\\text.txt");
			os = new FileOutputStream("C:\\Users\\huer\\Desktop\\text1.txt");
			prop.load(f);//直接从流加载到集合中
			System.out.println(prop+"-------");
			//第二个参数是描述注释
			prop.store(os, "hahaha");//直接将集合中的数据存储到流中
			
		}catch(Exception e){
			throw new RuntimeException("发生异常");
		}finally{
			if(f != null){
				try {
					f.close();
				} catch (IOException e) {
					throw new RuntimeException("发生异常");
				}
			}
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
					throw new RuntimeException("键盘读入发生异常");
				}
			}
		}
	}

八、其他流

(一)合并输入流SequenceInputStream

(1)没有输出流,具有的功能是:合并多个输入流

(2)构造函数参数:(1)两个InputStream(2)多个InputStream的集合Enumeration

(3)关闭输入流的时候,只需要关闭合并流

//这个显示的结果存在的缺陷:多个文件中的存储到一个统一文件中的时候没有文件结尾的符号
	public static void test11() throws Exception{
		Vector<FileInputStream> ve = new Vector<FileInputStream>();
		ve.add(new FileInputStream("C:\\Users\\huer\\Desktop\\t1.txt"));
		ve.add(new FileInputStream("C:\\Users\\huer\\Desktop\\t2.txt"));
		ve.add(new FileInputStream("C:\\Users\\huer\\Desktop\\t3.txt"));
		Enumeration<FileInputStream> elements = ve.elements();
		SequenceInputStream si = new SequenceInputStream(elements);
		FileOutputStream fo = new FileOutputStream("C:\\Users\\huer\\Desktop\\tn.txt");
		byte[] b = new byte[1024];
		int s = 0;
		while((s = si.read(b))!= -1){
			fo.write(b,0,s);
			fo.flush();
		}
		si.close();
		fo.close();
	}

(二)传输对象的流ObjectInputStream/ObjectOutputStream

(1)希望实现网络传输对象,那么这个对象需要实现Serialiable接口,这是一个标记接口。实现序列化

       序列化就是持久化,就是可以进行网络传输的效果。

(2)可以读对象,可以写对象

(3)序列化,网络传输的是内存区的。静态的不能序列化。被transient修饰的成员变量不能序列化。

(三)管道流

(1)读写都是一个流,一般与线程同时使用,防止死锁

(2)连接的方式:PipedInputStream与PipedOutputStream可以创建的时候连接,也可以以后连接,但是必须连接之后进行使用

(3)演示用多线程使用管道流进行数据传输

public class Test{
	
	public static void main(String[] args) throws Exception{
		PipedOutputStream out = new PipedOutputStream();
		PipedInputStream in = new PipedInputStream();
		in.connect(out);//必需建立连接
		new Thread(new Write(out)).start();
		new Thread(new Read(in)).start();	
	}
}

//读的线程
class Read implements Runnable{
	private PipedInputStream pi = null;
	public Read(PipedInputStream pi){
		this.pi = pi;
	}
	@Override
	public void run() {
		try{
			byte[] b = new byte[1024];
			int len = pi.read(b);
			String s = new String(b,0,len);
			System.out.println(s);
			pi.close();
		}catch(Exception e){
			throw new RuntimeException("管道读入流发生异常");
		}
	}
}

//写的线程
class Write implements Runnable{
	private PipedOutputStream po = null;
	public Write(PipedOutputStream po){
		this.po = po;
	}
	@Override
	public void run() {
		try{
			po.write("hello,world".getBytes());
			po.close();
		}catch(Exception e){
			throw new RuntimeException("管道写入流发生异常");
		}
	}
}

(四)RandomAccessFile随机访问文件

(1)不是IO流体系中的一员,但是包是io包

(2)只能操作文件,进行文件读写控制,文件模式可以控制

(3)控制不同的位置的文件内容的读取和写入seek

import java.io.RandomAccessFile;
public class Test{

	//写
	public static void writeS() throws Exception{
		 RandomAccessFile ra = new RandomAccessFile("C:\\Users\\huer\\Desktop\\a.txt", "rw");
                 ra.write("你好啊".getBytes());
                 ra.close();
	}
	public static void readS() throws Exception{
		RandomAccessFile ra = new RandomAccessFile("C:\\Users\\huer\\Desktop\\a.txt", "r");
		byte[] b = new byte[1024];
		int count = ra.read(b);
		String s = new String(b,0,count);
		System.out.println(s);
                ra.close();
	}
	public static void main(String[] args) throws Exception {
		writeS();
		readS();    
    }
}
(*)注意:写入是以byte[],那么读出来的时候也要以byte[]

(五)操作基本数据类型的流对象DataInputStream/DataOutputStream

(1)写入的是二进制,所以是有乱码的,但是使用DataInputStream读出来的就没有乱码了

(2)读写各基本类型的数据

(3)指定编码的:writeUTF()/readUTF()

public class Test{
	public static void test1() throws Exception{
	DataOutputStream ra = new DataOutputStream(new FileOutputStream("C:\\Users\\huer\\Desktop\\text.txt"));
        ra.writeInt(10);
        ra.writeBoolean(true);
        ra.writeDouble(20);
        ra.close(); 
	}
	public static void test2() throws Exception{
	DataInputStream ra = new DataInputStream(new FileInputStream("C:\\Users\\huer\\Desktop\\text.txt"));
        int i1 = ra.readInt();
        boolean i2 = ra.readBoolean();
        double i3 = ra.readDouble();
        System.out.println(i1);
        System.out.println(i2);
        System.out.println(i3);
        ra.close(); 
	}
	
	 public static void main(String[] args) throws Exception {
		 Test.test1();
		 Test.test2();
	 }
}

(六)文件的切割与合并

(1)切割就是一个输入流对应多个输出流

(2)合并就是多个输入流(可以使用合并流)对应一个输出流






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值