Java面向对象 IO (三)

时间:2023-03-09 09:51:45
Java面向对象  IO  (三)


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);

所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,

 需要用到转换流。

Java面向对象  IO  (三)

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(); }
}