转换流
转换流的由来:字符流与字节流之间的桥梁,方便字符流与字节流之间的操作。
转换流的应用:当操作文本文件时,流操作的都是字符,转换成字符流操作更高效。
转换流: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);
}
}