io(三)

本文深入探讨了流操作的基本概念,包括转换流在字符流与字节流之间的应用,以及如何通过改变标准输入输出设备实现文件的高效拷贝。文章详细介绍了流的操作规律,包括明确源和目的、数据类型、设备类型以及是否需要额外功能等步骤,并提供了实例代码进行说明。
摘要由CSDN通过智能技术生成

转换流

转换流的由来:字符流与字节流之间的桥梁,方便字符流与字节流之间的操作。
转换流的应用:当操作文本文件时,流操作的都是字符,转换成字符流操作更高效。
转换流:InputStreamReader(): 将字节转换成字符,解码 ; OutputStreamWriter(): 将字符转换成字节,编码。 

当使用字节流读取一个中文字符时需要读取两次,因为中问是由两个字符组成的,可能还会出现乱码。使用字符流时一次就读一个字符,不会出现乱码。

下面程序将实现了字节流和字符流之间的转换。还通过改变标准的输入输出设备,实现了文件的拷贝。
import java.io.*;
public class ReadKey {

	public static void main(String[] args) throws IOException{
		//标准的输入设备是键盘,通过setIn()方法传进去一个字节流可以将这个字节流设置成输入设备。
		System.setIn(new FileInputStream("g:\\test.txt"));
		
		//标准的输出设备是控制台,通过setOut()方法传递进去一个PrintStream流可以将此流设置成输出设备。
		System.setOut(new PrintStream("g:\\print.txt"));
		
		//System.in:是标准的输出设备。返回的是一个字节流对象。
		//将字节流转换成字符流
		//考虑到BufferReader中的方法好用一些,将上面的字符流包装成BufferReader
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
		//System.put :获得一个PrintStream是OutputStream的子类
		//通过OutputStreamWriter,将字符流转换成字节流
		//将字符流包装成了BufferReader
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		String line = null ;
		while((line=br.readLine())!=null){
			if(line.equals("over"))
				break;
			bw.write(line.toUpperCase());
			bw.newLine();
			//BufferReader中有缓冲区,要刷新一下数据才会输出到指定的地方。
			bw.flush();
		}
		br.close();
		bw.close();
	}

}

将一个文本文件通过字节流将其中的类容复制到另一个文件中:
public class CopyFile {

	public static void main(String[] args)throws IOException {
		//将FileInputStream流转换成字符流
		//接着将字符流包装成BufferedReader
		//直接可以使用BufferedReader中功能更强的方法。
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("g:\\test.txt")));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("g:\\copt.txt")));
		String line = null ;
		while((line=br.readLine())!=null){
			if(line.equals("over"))
				break;
			bw.write(line);
			bw.newLine();
			//BufferReader中有缓冲区,要刷新一下数据才会输出到指定的地方。
			bw.flush();
		}
		br.close();
		bw.close();
	}

}

流的操作规律:

之所以要弄清楚这个规律,是因为流的对象太多,开发时不知道使用那个对象。
在开发时只要通过以下四步即可。
1、明确源和目的
源:InputStream Reader
目的:OurputStream Writer

2、明确数据是否是纯文本数据
源:是纯文本:Reader
不是文本:InputStream
目的: 是纯文本:Writer
不是文本:OutputStream
通过上面两步即可以明确使用哪个体系。
3、明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
内存:数组
控制台:System.out
网络:Socket流

4、是否需要其他额外功能
是否需要高效:
是:加上Buffer


使用UTF-8进行文件的存储

任何Java识别的字符数据使用的都是Unicode码表,但是FileWriter写如本地文件使用的是本地的码表。
OutputStreamWriter可以使用指定的编码将要写入流中的字符编码成字节。

public class TransStreamTest {

	
	public static void main(String[] args) throws IOException{
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		//将字符串按照UTF-8码表进行储存
		BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(new FileOutputStream("g:\\transStream.txt"),"UTF-8"));
		//按UTF-8码表从文件中读数据
		BufferedReader br2 = new BufferedReader(new InputStreamReader(new FileInputStream("g:\\transStream.txt"),"UTF-8")) ;
		
		String line ;
		while((line=br.readLine())!=null){
			bw.write(line);
			bw.flush();
			System.out.print(br2.readLine());
		}
		br.close();
		bw.close();
		br2.close();
	}

}


File类

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

流只能操作数据,不能操纵文件。


public class FileTest {

	public static void main(String[] args)throws IOException {
		// TODO Auto-generated method stub
		//可以将已经存在或是不存在的文件或是目录封装成Flile对象
		//将一个字符串封装成file
		File f1 = new File("g:\\file1") ;
		//指定一个file为父路径,和一个字符串
		File f2 = new File(f1,"file2.txt") ;
		//指定一个String的父路径,和一个字符串
		File f3 = new File("g:\\file1","file3.txt");
		//因为Windows和Linux的路径分隔符不同,使用File.separator实习那跨平台。
		File f4 = new File("g:"+File.separator+"file1"+File.separator+"file4.txt") ;
		
		File f5 = new File("g:\\12\\23\\34\\34\\34");
		
		//获得父路径
		System.out.println(f1.getParent()) ;
		//获得对应文件的大小
		System.out.println(f2.length()) ;
		//获得文件路径
		System.out.println(f2.getPath()) ;
		
		//获得最后的修改时间
		System.out.println(f3.lastModified()) ;
		
		//创建目录,只能创建一个
		f1.mkdir();
		//创建file对应的多级目录,当父路径没有时会创建。
		f5.mkdirs();
		//创建file对应的文件,如果文件已经存在,则不会创建。
		f2.createNewFile();
		f3.createNewFile();
		f4.createNewFile();
		
		//删除文件夹的时候,如果文件夹里面有文件,则会删除失败。
		f1.delete();
		f3.delete();
		f4.delete();
		
		//判读file是否是目录,只有创建了目录才能正确调用。
		System.out.println(f1.isDirectory()) ;
		//判读file是不是文件,只有创建了文件才能正确调用。
		System.out.println(f1.isFile()) ;
		
		//判读file对应的文件或是目录是不是存在。
		System.out.println("f1:"+f1.exists()) ;
		
		reName();
	}
	
	/*
	 * 重命名
	 */
	public static void reName(){
		File f1 = new File("g:\\file1\\file.txt") ;
		File f2 = new File("g:\\file.txt");
		System.out.println(f1.renameTo(f2));
	}
	
}

系统根目录和容量获取:

public class FileMedthTest {

	public static void main(String[] args)throws IOException {
		// TODO Auto-generated method stub
		listRoot();
	}
	
	public static void listRoot()throws IOException{
		File[] files = File.listRoots(); 
		
		for(File file : files){
			System.out.println(file);
		}
		
		File file = new File("G:\\") ;
		
		System.out.println("getFreeSpace:"+file.getFreeSpace());
		System.out.println("getTotalSpace"+file.getTotalSpace());
		System.out.println("getUseedSpace:"+file.getUsableSpace());
	}
}

获得指定目录内的文件:
public class FileListTest {

	public static void main(String[] args)throws IOException {
		listDemo();
		System.out.println("------------------------") ;
		listTxt();
		System.out.println("------------------------") ;
		listTxt2();
	}
	
	public static void listDemo()throws IOException{
		File file = new File("g:\\") ;
		
		//获得目录下的文件以及目录,包含隐藏文件
		//调用list放的File对象必须是目录,否则会报NullPointerException
		//如果访问系统级的目录也会发生NullPointerException
		//如果目录内存在但是没有内容,返回的数组是一个长度为0的数组。
		File[] files = file.listFiles();
		
		for(File f : files){
			System.out.println(f.getName());
		}
	}
	/*
	 * 获得目录内的以.txt结尾的文件
	 */
	public static void listTxt()throws IOException{
		File file = new File("g:\\") ;
		
		File[] files = file.listFiles();
		
		for(File f : files){
			//判断文件是不是.txt结尾
			if(f.getName().endsWith(".txt")){
				System.out.println(f.getName());
			}
				
		}
	}
	
	
	/*
	 * 获得目录下面以.txt结尾的文件
	 * 通过FilenameFilter对象过滤文件,accept方法中具体执行判读。
	 */
	public static void listTxt2()throws IOException{
		File file = new File("g:\\") ;
		
		File[] files = file.listFiles(new FilenameFilter() {
			
			@Override
			public boolean accept(File dir, String name) {
				// TODO Auto-generated method stub
				return name.endsWith(".txt");
			}
		});
		
		for(File f : files){
			System.out.println(f.getName());
		}
	}
		
}

递归

递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法解决问题的特点:
(1) 递归就是在过程或函数里调用自身。
(2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。
(3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。
列出指定的目录下所有的文件:
public class RecursionTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		getFiles(file);
		
		System.out.println(getSUM(100));
	}
	
	 /*
	 * 使用递归
	 * 打印目录下面所有的文件,包括子目录下面的
	 */
	
	static File file = new File("g:\\items");
	static int count =0;
	public static void  getFiles(File file){
		myPrint(count);
		count++ ;
		System.out.println(file.getName());
		File[] files = file.listFiles();
		
		for(File f :files){
			//递归条件,条件不满足时往下执行,自动返回
			if(f.isDirectory()){
				getFiles(f);
			}
			myPrint(count);
			System.out.println(f.getName());
		}
	}
	
	public static void myPrint(int p){
		
		for(int i=0;i<p;i++){
			System.out.print("    ");
		}
		
		System.out.print("|--");
	}
	
	
	/*
	 * 递归求和
	 */
	
	public static int getSUM(int i){
		int sum=i;
		//返回条件
		if(sum==0){
			return 0;
		}
		//不断调用本身的方法
		return sum = sum+getSUM(sum-1);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值