Java面向对象 IO (三)
知识概要:
(1)IO 流的操作规律
(2)异常日志信息IO处理
(3)系统信息IO处理
(4)File类描述
(5)Properties与流的结合
IO流的操作规律
1, 需求:将键盘录入的东东打印在控制台上
源:键盘录入。
目的:控制台。
2,需求:想把键盘录入的数据存储到一个文件中。
源:键盘。
目的:文件。
3,需求:想要将一个文件的数据打印在控制台上。
源:文件。
目的:控制台。
流操作的基本规律:
通过三个明确来完成。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
1,将一个文本文件中数据存储到另一个文件中。复制文件。
源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。是!这时就可以选择Reader 。这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader 。是否需要提高效率:是!加入Reader体系中缓冲区
BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
练习:将一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确。
2,需求:将键盘录入的数据保存到一个文件中。
这个需求中有源和目的都存在。那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?
为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?
需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
字符编码输出
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
但是FileWriter是使用的默认编码表。GBK.
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter。
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");//转换流
需要高效吗?需要。
BufferedWriter bufw = new BufferedWriter(osw);
所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,
需要用到转换流。
class TransStreamDemo2
{
public static void main(String[] args) throws IOException
{
System.setIn(new FileInputStream("PersonDemo.java")); System.setOut(new PrintStream("zzz.txt")); //键盘的最常见写法。
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
} bufr.close(); }
}
异常日志信息IO处理
import java.io.*;
import java.util.*;
import java.text.*;
class ExceptionInfo
{
public static void main(String[] args)throws IOException
{
try
{
int[] arr = new int[2];
System.out.println(arr[3]);
}
catch (Exception e)
{ try
{
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String s = sdf.format(d); PrintStream ps = new PrintStream("exeception.log");
ps.println(s);
System.setOut(ps); }
catch (IOException ex)
{
throw new RuntimeException("日志文件创建失败");
}
e.printStackTrace(System.out);
}
}
}
系统信息处理
import java.util.*;
import java.io.*;
class SystemInfo
{
public static void main(String[] args) throws IOException
{
Properties prop = System.getProperties(); //System.out.println(prop);
prop.list(new PrintStream("sysinfo.txt"));
}
}
File类描述
用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作 。
File对象可以作为参数传递给流的构造函数。
了解File类中的常用方法。
File类常见方法:
1,创建。
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息。
getName():
getPath():
getAbsolutePath()
getParent():
long lastModified()
long length()
class FileDemo
{
public static void main(String[] args) throws IOException
{
method_5();
} public static void method_5()
{
File f1 = new File("c:\\Test.java");
File f2 = new File("d:\\hahah.java"); sop("rename:"+f2.renameTo(f1)); } public static void method_4()
{
File f = new File("file.txt"); sop("path:"+f.getPath());
sop("abspath:"+f.getAbsolutePath());
sop("parent:"+f.getParent());
//该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
//如果相对路径中有上一层目录那么该目录就是返回结果。 } public static void method_3()throws IOException
{
File f = new File("d:\\java1223\\day20\\file2.txt"); //f.createNewFile(); //f.mkdir(); //记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
//通过exists判断。
sop("dir:"+f.isDirectory());
sop("file:"+f.isFile()); sop(f.isAbsolute());
} public static void method_2()
{
File f = new File("file.txt"); //sop("exists:"+f.exists()); //sop("execute:"+f.canExecute()); //创建文件夹
File dir = new File("abc\\kkk\\a\\a\\dd\\ee\\qq\\aaa"); sop("mkdir:"+dir.mkdirs());
} public static void method_1()throws IOException
{
File f = new File("file.txt");
//sop("create:"+f.createNewFile());
//sop("delete:"+f.delete()); } //创建File对象
public static void consMethod()
{
//将a.txt封装成file对象。可以将已有的和为出现的文件或者文件夹封装成对象。
File f1 = new File("a.txt"); File f2 = new File("c:\\abc","b.txt"); File d = new File("c:\\abc");
File f3 = new File(d,"c.txt"); sop("f1:"+f1);
sop("f2:"+f2);
sop("f3:"+f3); File f4 = new File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"a.txt"); } public static void sop(Object obj)
{
System.out.println(obj);
}
}
递归
函数自己调用自己。
注意:递归时一定要明确结束条件。
应用场景:
• 当某一功能要重复使用时。
练习:
• 列出一个文件夹下所有的子文件夹以及子文件
import java.io.*; class FileDemo2
{
public static void main(String[] args)
{
File dir = new File("c:\\");
File[] files = dir.listFiles(); for(File f : files)
{
System.out.println(f.getName()+"::"+f.length());
} } public static void listDemo_2()
{
File dir = new File("d:\\java1223\\day18"); String[] arr = dir.list(new FilenameFilter()
{
public boolean accept(File dir,String name)
{ //System.out.println("dir:"+dir+"....name::"+name); return name.endsWith(".bmp"); }
}); System.out.println("len:"+arr.length); for(String name : arr)
{
System.out.println(name);
}
} public static void listDemo()
{
File f = new File("c:\\abc.txt"); String[] names = f.list();//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
for(String name : names)
{
System.out.println(name);
}
}
public static void listRootsDemo()
{
File[] files = File.listRoots(); for(File f : files)
{
System.out.println(f);
}
}
}
import java.io.*; class FileDemo3
{
public static void main(String[] args)
{
File dir = new File("d:\\testdir"); System.out.println(dir.delete());
}
public static String getLevel(int level)
{
StringBuilder sb = new StringBuilder();
sb.append("|--");
for(int x=0; x<level; x++)
{
//sb.append("|--");
sb.insert(0,"| "); }
return sb.toString();
}
public static void showDir(File dir,int level)
{ System.out.println(getLevel(level)+dir.getName()); level++;
File[] files = dir.listFiles();
for(int x=0; x<files.length; x++)
{
if(files[x].isDirectory())
showDir(files[x],level);
else
System.out.println(getLevel(level)+files[x]);
}
} }
思考:
• 1,删除一个目录的过程是如何进行的?
删除原理:
在window中,删除目录从里面往外删除的。 既然是从里往外删除。就需要用到递归。 */
import java.io.*;
class RemoveDir
{
public static void main(String[] args)
{ File dir = new File("d:\\testdir");
removeDir(dir);
} public static void removeDir(File dir)
{
File[] files = dir.listFiles(); for(int x=0; x<files.length; x++)
{
if(files[x].isDirectory())
removeDir(files[x]);
else
System.out.println(files[x].toString()+":-file-:"+files[x].delete());
} System.out.println(dir+"::dir::"+dir.delete());
} }
Properties与流的结合
Properties是hashtable的子类。
也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
是集合中和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。
那么在加载数据时,需要数据有固定格式:键=值。
练习:限制程序运行次数。当运行次数到达5次时,给出,请您注册的提示。并不再让该程序执行。
用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。
下一次在启动该程序,又重新开始从0计数。这样不是我们想要的。程序即使结束,该计数器的值也存在。
下次程序启动在会先加载该计数器的值并加1后在重新存储起来。
所以要建立一个配置文件。用于记录该软件的使用次数。
该配置文件使用键值对的形式。
这样便于阅读数据,并操作数据。
键值对数据是map集合。
数据是以文件形式存储,使用io技术。
那么map+io -->properties.
配置文件可以实现应用程序数据的共享。
import java.io.*;
import java.util.*;
class RunCount
{
public static void main(String[] args) throws IOException
{
Properties prop = new Properties(); File file = new File("count.ini");
if(!file.exists())
file.createNewFile(); FileInputStream fis = new FileInputStream(file); prop.load(fis); int count = 0;
String value = prop.getProperty("time"); if(value!=null)
{
count = Integer.parseInt(value);
if(count>=5)
{
System.out.println("您好,使用次数已到,拿钱!");
return ;
} } count++; prop.setProperty("time",count+""); FileOutputStream fos = new FileOutputStream(file); prop.store(fos,""); fos.close();
fis.close(); }
}