黑马程序员——IO(二)——File类、Properties类、打印流、序列流等 .

来源:互联网 发布:wi fi万能钥匙mac版 编辑:程序博客网 时间:2024/06/06 02:18

黑马程序员--IO(二)--File类、Properties类、打印流、序列流等

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、File类

File类用来将文件或文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。
File对象可以作为参数传递给流的构造函数。一旦创建,File对象表示的抽象路径名将永不改变。

[java] view plaincopyprint?
  1. //封装对象的方式:可以将已存在或不存在的文件或目录封装成file对象。   
  2. import java.io.File;  
  3. class  FileDemo  
  4. {  
  5.     public static void main(String[] args)   
  6.     {  
  7.         constructorDemo();  
  8.     }  
  9.     public static void constructorDemo()  
  10.     {  
  11.         //方式一:   
  12.         File f1 = new File("d:\\demo\\a.txt");  
  13.   
  14.         //方式二:   
  15.         File f2 = new File("d:\\demo","a.txt");  
  16.   
  17.         //方式三:   
  18.         File f = new File("d:\\demo");  
  19.         File f3 = new File(f,"a.txt");  
  20.   
  21.         //跨系统方式.File.separator是与系统有关的默认名称分隔符。UNIX系统上值为'/';  
  22.         File f4 = new File("d:"+File.separator+"demo"+File.separator+"a.txt");  
  23.     }  
  24. }  
PS:
流只能操作数据。
1、常见方法:
1.1 创建
boolean creatNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。只能创建一级文件夹。
boolean mkdirs():创建多级文件夹
1.2 删除
boolean delete():删除文件或目录。文件存在,返回true。文件不存在或正在被执行,返回false。
void deleteOnExit():在程序退出时删除指定文件。避免程序异常时,删除动作执行不到的问题。
1.3 判断
boolean canExecute():测试程序是否可以执行此路径名表示的文件。
boolean exists():判断文件是否存在。
boolean isDirectory():判断路径名是否是目录(文件夹)。
boolean isFile():判断路径名是否是文件。
boolean isHidden():判断路径名是否是一个隐藏文件。
boolean isAbsolute():判断路径名是否是绝对路径名。
PS:
判读文件对象是否是文件或目录时,必须要判断该文件对象封装的内容是否存在。
1.4 获取信息。
String getName():获取文件名。
String getPath():获取文件的相对路径。即创建的对象传入的参数是什么就获取到什么。
String getParent():返回文件绝对路径中的父目录。若获取相对路径,有明确父目录时,返回父目录,否则返回null。
String getAbsolutePath():获取文件的绝对路径。
long lastModified():返回文件最后一次被修改时间。判断文件是否被修改过。
long length():返回文件长度。

[java] view plaincopyprint?
  1. //File类常见方法:   
  2. import java.io.*;  
  3. class  FileDemo1  
  4. {  
  5.     public static void main(String[] args) throws IOException   
  6.     {  
  7.         method_create();  
  8.         method_delete();  
  9.         method_judge();  
  10.         method_get();  
  11.         method_list();  
  12.     }  
  13.     public static void method_create() throws IOException  
  14.     {  
  15.         File f = new File("file.txt");  
  16.         //指定位置创建文件。因为它调用、启用资源有产生异常的可能。   
  17.         sop("create:"+f.createNewFile());  
  18.   
  19.         File dir1 = new File("abc");  
  20.         //创建一级文件夹   
  21.         sop("mkdirs:"+dir1.mkdir());  
  22.   
  23.         File dir2 = new File("abc\\a\\aad\\e");  
  24.         //创建多级文件夹   
  25.         sop("mkdirs:"+dir2.mkdirs());  
  26.     }  
  27.     public static void method_delete() throws IOException  
  28.     {  
  29.         File f = new File("a.txt");  
  30.         //删除文件或目录。文件存在,返回true。文件不存在或正在被执行,返回false。  
  31.         sop("delete:"+f.delete());  
  32.   
  33.         //在程序退出时删除指定文件。   
  34.         File f2 = new File("file.txt");  
  35.         f2.deleteOnExit();  
  36.     }  
  37.     public static void method_judge() throws IOException  
  38.     {  
  39.         File f = new File("d:\\Demo\\IO3\\FileDemo\\file.txt");  
  40.           
  41.         sop("canExecute:"+f.canExecute());  
  42.         //如果流存在才可以读写,所以exists方法可以直接判断流存在问题。  
  43.         sop("exists:"+f.exists());  
  44.   
  45.         f.mkdir();  
  46.         //当判断文件对象是否是文件或目录时,必须要先判断该文件对象封装的内存是否存在。  
  47.         sop("dir:"+f.isDirectory());  
  48.         sop("file:"+f.isFile());  
  49.         sop("hidden:"+f.isHidden());  
  50.   
  51.         sop(f.isAbsolute());  
  52.     }  
  53.     public static void method_get() throws IOException  
  54.     {  
  55.         File f = new File("d:\\a.txt");  
  56.   
  57.         sop("path:"+f.getPath());  
  58.         sop("abspath:"+f.getAbsolutePath());  
  59.         sop("parent:"+f.getParent());  
  60.         sop("length:"+f.length());  
  61.     }  
  62.     public static void method_list() throws IOException  
  63.     {  
  64.         File f1 = new File("d:\\helloworld.java");  
  65.         File f2 = new File("d:\\a.java");  
  66.           
  67.         //列出可以文件系统根目录   
  68.         sop("root"+f2.listRoots());  
  69.         //列出当前目录下所有文件   
  70.         sop("list"+f2.list());  
  71.         sop("rename:"+f1.renameTo(f2));  
  72.     }  
  73.     public static void sop(Object obj)  
  74.     {  
  75.         System.out.println(obj);  
  76.     }  
  77. }  
1.5 列出文件及文件过滤
static File[] listRoots():列出可用的文件系统根目录,即系统盘符。
String[] list():列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个已存在的目录。
String[] list(FilenameFilter filter):返回一个字符串数组,获取目录中满足指定过滤器的文件和目录。
FilenameFilter:文件名过滤器,是一个接口,其中包含一个方法:accept(File dir,String name),返回的是boolean。
File[] listFiles():返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹。
boolean renameTo(File dest):重命名。
list和listFiles区别:
list返回当前目录下的文件和名称;listFiles返回当前目录下的文件和文件对象。
即list只能获取名,listFiles可以通过方法获取更多属性。

[java] view plaincopyprint?
  1. //list方法   
  2. import java.io.*;  
  3. class FileDemo2  
  4. {  
  5.     public static void main(String[] args)   
  6.     {  
  7.         listRootsDemo();  
  8.         listDemo();  
  9.         listDemo_2();  
  10.         listfileDemo();  
  11.     }  
  12.     public static void listfileDemo()  
  13.     {  
  14.         File dir = new File("D:\\Demo\\IO3");  
  15.   
  16.         File[] files = dir.listFiles();  
  17.   
  18.         for(File f:files)  
  19.         {  
  20.             System.out.println(f.getName()+"::"+f.length());  
  21.         }     
  22.     }  
  23.     public static void listDemo_2()  
  24.     {  
  25.         File dir = new File("D:\\Demo\\IO3");  
  26.   
  27.         String[] arr = dir.list(new FilenameFilter()  
  28.         {  
  29.             //list依据accept的返回值来判断数组内容。  
  30.             public boolean accept(File dir,String name)  
  31.             {  
  32.                 return name.endsWith(".txt");  
  33.             }  
  34.         });  
  35.         System.out.println("len:"+arr.length);  
  36.         for(String name:arr)  
  37.         {  
  38.             System.out.println(name);  
  39.         }  
  40.     }  
  41.     public static void listDemo()  
  42.     {  
  43.         File f = new File("D:\\");  
  44.   
  45.         //调用list方法的file对象必须是封装了一个目录。该目录必须存在。  
  46.         String[] names = f.list();  
  47.         for(String name:names)  
  48.         {  
  49.             System.out.println(name);  
  50.         }  
  51.     }  
  52.     //打印系统有效盘符。   
  53.     public static void listRootsDemo()  
  54.     {  
  55.         File[] files = File.listRoots();  
  56.   
  57.         for(File f:files)  
  58.         {  
  59.             System.out.println(f);  
  60.         }  
  61.     }  
  62. }  

2、递归
2.1 定义
递归:函数自身调用自身的表现形式或编程手法。因为目录中还有目录,只有使用同一个
列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。
2.2 注意事项:
a 限定次数。
b 注意递归次数,避免内存溢出。因为每次调用自己都会执行下一次调用自己的方法,所以会不断
在栈内存中开辟新空间,次数过多,会导致内存溢出。

[java] view plaincopyprint?
  1. /* 
  2. 列出指定目录下文件或文件夹,包含子目录的内容。 
  3.  
  4. 因为目录中还有目录,只有使用同一个列出目录功能的函数完成即可。 
  5. 在列出过程中出现的还是目录的话,还可以再次调用本功能。 
  6. 也就是函数自身调用自身。 
  7. 这种表现形式或编程手法,称为递归。 
  8.  
  9. 递归注意事项: 
  10. 1,限定次数。 
  11. 2,注意递归次数,避免内存溢出。 
  12. */  
  13. import java.io.*;  
  14. class FileDemo3  
  15. {  
  16.     public static void main(String[] args)   
  17.     {  
  18.         File dir = new File("D:\\Demo");  
  19.         showDir(dir);  
  20.         //int n = getSum(25000);   
  21.         //System.out.println(n);  
  22.     }  
  23.     //递归会不断开辟栈对象次数过多,有内存溢出风险。   
  24.     public static int getSum(int n)  
  25.     {  
  26.         if(n==1)  
  27.             return 1;  
  28.         return n+getSum(n-1);  
  29.     }  
  30.     //递归:自我调用。因为没有次数限制,会成为无限循环,失去价值。   
  31.     public static void method()  
  32.     {  
  33.         method();  
  34.     }  
  35.     public static void showDir(File dir)  
  36.     {  
  37.         //打印目录   
  38.         System.out.println(dir);  
  39.         File[] files = dir.listFiles();  
  40.   
  41.         //递归   
  42.         for(int x=0; x<files.length; x++)  
  43.         {  
  44.             //如果文件中有文件夹,再次调用自己。   
  45.             if(files[x].isDirectory())  
  46.                 showDir(files[x]);  
  47.             System.out.println(files[x]);  
  48.         }  
  49.     }  
  50. }  

二、Properties类

Properties是hashtable的子类。所以它具备Map集合的特点。而且它存储的键值对都是字符串。无泛型定义。
它是集合和IO技术集合的集合容器。
1、特点:
a 可以用于键值对形式的配置文件。
b 在加载数据时,需要数据有固定格式:键=值。
c 集合中的数据可以保存到流中或从流中获取。
2、特有方法:
2.1 设置
Object setProperty(String key,String value):设置键和值,调用Hashtable的方法put。
2.2 获取
String getProperty(String key):通过键获取值。
Set<String> stringPropertyNames():返回此属性列表中的键集。将map变成set,带泛型。
3.3 加载与存储
void load(InputStream ism):将字节流中的数据加载进集合。
void load(Reader reader):将字符流中的数据加载进集合。
void list(PrintStream out):将属性列表输出到指定的输出流中。
void store(OutputStream out,String comments):对应load(InputStream)将属性列表(键值对)写入输出流。comments注释信息。
void store(Writer writer,String comments):对应load(Reader)将属性列表(键值对)写入输出流。
[java] view plaincopyprint?
  1. /* 
  2. Properties类实例: 
  3. 本文件解决问题: 
  4. 1,设置和获取元素。 
  5. 2,将流中的数据存储到集合中。 
  6.     思路: 
  7.     1,用一个流和info.txt文件关联。 
  8.     2,读取一行数据,将该行数据用“=”进行切割。 
  9.     3,等号左边作为键,右边作为值。存入到Properties集合中即可。 
  10. */  
  11. import java.io.*;  
  12. import java.util.*;  
  13.   
  14. class PropertiesDemo  
  15. {  
  16.     public static void main(String[] args) throws IOException   
  17.     {  
  18.         setAndGet();  
  19.         method_1();  
  20.         loadDemo();  
  21.     }  
  22.     public static void loadDemo() throws IOException   
  23.     {  
  24.         Properties prop = new Properties();  
  25.         FileInputStream fis = new FileInputStream("info.txt");  
  26.   
  27.         //将流中的数据加载进集合   
  28.         prop.load(fis);  
  29.   
  30.         //修改数据信息,但是无法改源文件。   
  31.         prop.setProperty("wangwu","39");  
  32.   
  33.         FileOutputStream fos = new FileOutputStream("info.txt");  
  34.   
  35.         //将属性列表(键值对)写入输出流。   
  36.         prop.store(fos,"haha");  
  37.   
  38.         //System.out.println(prop);   
  39.         //另一种输出方式。   
  40.         prop.list(System.out);    
  41.   
  42.         fos.close();  
  43.         fis.close();  
  44.     }  
  45.     //模拟load方法。将流中的数据存储到集合中。   
  46.     public static void method_1() throws IOException  
  47.     {  
  48.         BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));  
  49.   
  50.         String line = null;  
  51.         Properties prop = new Properties();  
  52.   
  53.         while((line=bufr.readLine())!=null)  
  54.         {  
  55.             String[] arr = line.split("=");  
  56.             //将键值对存入Properties中   
  57.             prop.setProperty(arr[0],arr[1]);  
  58.         }  
  59.   
  60.         bufr.close();  
  61.   
  62.         System.out.println(prop);  
  63.     }  
  64.     //设置和获取元素。   
  65.     public static void setAndGet()  
  66.     {  
  67.         Properties prop = new Properties();  
  68.   
  69.         //设置   
  70.         prop.setProperty("zhangsan","30");  
  71.         prop.setProperty("lisi","34");  
  72.         //System.out.println(prop);   
  73.   
  74.         //获取   
  75.         String value = prop.getProperty("lisi");  
  76.         //System.out.println(value);   
  77.   
  78.         //修改信息、   
  79.         prop.setProperty("lisi",98+"");  
  80.   
  81.         //取出所有元素   
  82.         Set<String> names = prop.stringPropertyNames();  
  83.         for(String s : names)  
  84.         {  
  85.             System.out.println(s+":"+prop.getProperty(s));  
  86.         }  
  87.     }  
  88. }  
应用:创建文件访问计数器。
[java] view plaincopyprint?
  1. /* 
  2. 需求:记录应用程序运行次数。如果使用次数已到,给出注册提示。 
  3. 思路: 
  4. 1、在程序中定义计数器,随着程序的运行存在并自增。但是普通计数器会随着程序退出而清0; 
  5. 2、建立一个配置文件,记录该软件的使用次数。 
  6. 3、为便于阅读、操作数据,该配置文件使用键值对的形式。 
  7. 4、键值对数据是map集合;数据是以文件形式存储,使用io技术;那么map+io -->properties。 
  8. 配置文件可以实现应用程序数据的共享。 
  9. */  
  10. import java.io.*;  
  11. import java.util.*;  
  12. class RunCount  
  13. {  
  14.     public static void main(String[] args) throws IOException  
  15.     {  
  16.         Properties prop = new Properties();  
  17.   
  18.         //将文件独立封装可以使用判读方法,防止文件不存在时抛出异常。   
  19.         File file = new File("count.ini");  
  20.         if(!file.exists())  
  21.             file.createNewFile();  
  22.   
  23.         FileInputStream fis = new FileInputStream(file);  
  24.   
  25.         prop.load(fis);  
  26.   
  27.         int count = 0;  
  28.         String value = prop.getProperty("time");  
  29.   
  30.         if(value!=null)  
  31.         {  
  32.             //将字符串转成基本数据类型。静态装换方法   
  33.             count = Integer.parseInt(value);  
  34.             if(count>=5)  
  35.             {  
  36.                 System.out.println("使用次数已到,请充值!");  
  37.                 return;  
  38.             }  
  39.         }  
  40.         count++;  
  41.   
  42.         prop.setProperty("time",count+"");  
  43.           
  44.         FileOutputStream fos = new FileOutputStream(file);  
  45.   
  46.         prop.store(fos,"");  
  47.   
  48.         fos.close();  
  49.         fis.close();  
  50.     }  
  51. }  

三、打印流

打印流:PrintStream、PrintWriter。可直接操作输入流和文件,将传入数据原样打印。
1、PrintStream:字节打印流。为其他输出流添加打印各种数据值的功能。特点:不会抛出IOException。
PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。当需要写入字符时应使用PrintWriter类。
构造函数可以接收的参数类型:
1.1 File对象。File
1.2 字符串路径。String
1.3 字节输出流。OutputStream
2、PrintWriter:字符打印流。
构造函数可以接收的参数类型:
2.1 File对象。File
2.2 字符串路径。String
2.3 字节输出流。OutputStream
2.4 字符输出流。Writer。
[java] view plaincopyprint?
  1. //打印流:提供打印方法,可以将各种数据类型的数据原样打印。   
  2. import java.io.*;  
  3.   
  4. class PrintStreamDemo  
  5. {  
  6.     public static void main(String[] args) throws IOException  
  7.     {  
  8.         PrintStream ps = new PrintStream("print.txt");   
  9.   
  10.         //write(int b):只写最低8位。   
  11.         ps.write(97);//a  
  12.         //print方法原数打印   
  13.         ps.print(97);//97  
  14.   
  15.         BufferedReader bufr =   
  16.             new BufferedReader(new InputStreamReader(System.in));  
  17.   
  18.         //PrintWriter构造函数的第二个参数设置为true,表示自动刷新。  
  19.         PrintWriter pw = new PrintWriter(System.out,true);  
  20.   
  21.         String line = null;  
  22.   
  23.         while((line=bufr.readLine())!=null)  
  24.         {  
  25.             if("over".equals(line))  
  26.                 break;  
  27.             pw.println(line.toUpperCase());//ln是刷新标记  
  28.             //pw.flush();   
  29.         }  
  30.         ps.close();  
  31.         pw.close();  
  32.         bufr.close();  
  33.     }  
  34. }  

四、序列流

SequenceInputStream:序列流(合并流)。多源对应一个目的时,省去部分关联和续写步骤,简化代码。
SequenceInputStream(InputStream s1, InputStreamS2 ): 依顺序读取s1,s2
SequenceInputStream(Enumeration<? extends InputStream> e):多个参数合并
[java] view plaincopyprint?
  1. /* 
  2. SequenceInputStream:序列流(合并流)。 
  3. 需求:将1.txt、2.txt、3.txt合并为一个文件4.txt。 
  4. */  
  5. import java.io.*;  
  6. import java.util.*;  
  7. class SequenceDemo  
  8. {  
  9.     public static void main(String[] args) throws IOException  
  10.     {  
  11.         Vector<FileInputStream> v = new Vector<FileInputStream>();  
  12.   
  13.         v.add(new FileInputStream("D:\\1.txt"));  
  14.         v.add(new FileInputStream("D:\\2.txt"));  
  15.         v.add(new FileInputStream("D:\\3.txt"));  
  16.   
  17.         Enumeration<FileInputStream> en = v.elements();  
  18.       
  19.         //合并流,统一源。   
  20.         SequenceInputStream sis = new SequenceInputStream(en);  
  21.   
  22.         //目的。   
  23.         FileOutputStream fos = new FileOutputStream("D:\\4.txt");  
  24.   
  25.         byte[] buf = new byte[1024];  
  26.   
  27.         int len = 0;  
  28.         while((len=sis.read(buf))!=-1)  
  29.         {  
  30.             fos.write(buf,0,len);  
  31.         }  
  32.         fos.close();  
  33.         sis.close();  
  34.     }  
  35. }  

五、操作对象

操作对象:ObjectInputStream、ObjectOutputStream。
ObjectOutputStream:将Java对象的基本数据类型和图形写入OutputStream。
被操作的对象需要实现Serializable接口才能使用序列化功能。
Serializable接口是标记接口,它用于给被序列化的类加入ID号,以判断类和对象是否是同一个版本。
静态不能被序列化,因为静态在方法区中,不在堆中。
serialVersionUID:给类定义固定标识,方便序列化。新类可以操作曾经被序列化的对象。
transient:是让非静态成员无法序列化的关键字。保证它的值在堆内存中存在,而不显示在文本文件中。
[java] view plaincopyprint?
  1. /* 
  2. 操作对象:ObjectInputStream、ObjectOutputStream 
  3. NotSerializableException:某个要序列化的对象不能实现 java.io.Serializable 接口异常。 
  4. */   
  5. import java.io.*;  
  6. class Person implements Serializable  
  7. {  
  8.     //serialVersionUID:给类定义固定标识,使新类还可以用之前的序列化对象。  
  9.     public static final long serialVersionUID = 42L;  
  10.   
  11.     private String name;  
  12.     transient int age;//不想非静态成员序列化加关键字:transient  
  13.   
  14.     //静态不能被序列化,因为静态在方法区中,不在堆中。   
  15.     static String country = "cn";   
  16.     Person(String name,int age,String country)  
  17.     {  
  18.         this.name=name;  
  19.         this.age=age;  
  20.         this.country = country;  
  21.     }  
  22.     public String toString()  
  23.     {  
  24.         return name+":"+age+":"+country;  
  25.     }  
  26. }  
  27. class ObjectStreamDemo   
  28. {  
  29.     public static void main(String[] args) throws Exception  
  30.     {  
  31.         writeObj();  
  32.         readObj();  
  33.     }  
  34.   
  35.     public static void readObj() throws Exception  
  36.     {  
  37.         ObjectInputStream ois =   
  38.             new ObjectInputStream(new FileInputStream("obj.txt"));  
  39.   
  40.         Person p = (Person)ois.readObject();  
  41.   
  42.         System.out.println(p);  
  43.         ois.close();  
  44.   
  45.     }  
  46.     public static void writeObj() throws IOException  
  47.     {  
  48.         //目的:将对象保存成文件   
  49.         ObjectOutputStream oos =  
  50.             new ObjectOutputStream(new FileOutputStream("obj.txt"));  
  51.   
  52.         oos.writeObject(new Person("lisi0",339,"USA"));  
  53.   
  54.         oos.close();  
  55.     }  
  56. }  
PS:
1 对象的实体化存储:将对象存储在硬盘上。也可称为对象的序列化、对象的可串联性。
2 标记接口:没有方法的接口。只是为了标识其信息。

六、RandomAccessFile

RandomAccessFile:随机访问文件,自身具备读写方法。它直接继承自Object,不算是IO体系中子类。
1、特点:
1.1 具备读和写功能;
1.2 该对象内部封装了一个byte数组,并通过指针可以操作数组中的元素;
1.3 可以通过getFilePointer方法获取指针位置,通过seek方法改变指针位置。
1.4 该对象只能操作文件,而且操作文件还有模式:只读:r,读写:rw。
PS:
1 读写原理:内部封装了字节输入流和输出流。
2 操作文件模式:
如果模式为只读 r:不创建文件。只读取一个已存在的文件,如果该文件不存在,则会出现异常。
如果模式为读写rw:操作的文件不存在,会自动创建。如果存在不会覆盖。
2、常用方法:
skipBytes()跳过指定的字节数; 
seek()调整对象中指针;
[java] view plaincopyprint?
  1. //RandomAccessFile:随机访问文件。   
  2. import java.io.*;  
  3. class RandomAccessFileDemo   
  4. {  
  5.     public static void main(String[] args) throws IOException   
  6.     {  
  7.         writeFile();  
  8.         readFile();  
  9.         writeFile_2();  
  10.     }  
  11.   
  12.     public static void readFile() throws IOException  
  13.     {  
  14.         RandomAccessFile raf = new RandomAccessFile("ran.txt","r");//只读  
  15.   
  16.         //通过seek访问任意位置。   
  17.         //raf.seek(8);   
  18.   
  19.         //跳过指定的字节数。不能回跳   
  20.         raf.skipBytes(8);  
  21.   
  22.         byte[] buf = new byte[4];  
  23.   
  24.         raf.read(buf);  
  25.   
  26.         String name = new String(buf);  
  27.   
  28.         int age = raf.readInt();  
  29.   
  30.         System.out.println("name="+name);  
  31.         System.out.println("age="+age);  
  32.   
  33.         raf.close();  
  34.     }  
  35.     public static void writeFile() throws IOException  
  36.     {  
  37.         RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");  
  38.   
  39.         raf.write("Lisi".getBytes());  
  40.   
  41.         //使用write方法写入最后一个字节。只取8位,超过256时存在数据丢失。  
  42.         raf.write(257);  
  43.   
  44.         //使用writeInt方法写入四个字节(int类型)   
  45.         raf.writeInt(97);  
  46.         raf.write("wagnwu".getBytes());  
  47.         raf.writeInt(99);  
  48.   
  49.         raf.close();  
  50.     }  
  51.     public static void writeFile_2() throws IOException  
  52.     {  
  53.         RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");  
  54.   
  55.         //往指定位置写入数据   
  56.         raf.seek(2*8);  
  57.         raf.write("周期".getBytes());  
  58.         raf.writeInt(103);  
  59.   
  60.         raf.close();  
  61.     }  
  62. }  

七、管道流

管道流:PipedInputStream、PipedOutputStream。
1、特点:
1.1 将输入流和输出流连接,省去了用数组存储数据的中转环节。
1.2 使用多线程解决管道执行顺序问题,防止死锁情况。
2、连接方式:
2.1 connect(PipedOutputStream src):将PipedInputStream连接到PipedOutputStream。
2.2 PipedInputStream():创建尚未连接的PipedInputStream。
2.3 PipedOutputStream():创建尚未连接的PipedOutputStream。
[java] view plaincopyprint?
  1. //管道流:PipedInputStream、PipedOutputStream  
  2. import java.io.*;  
  3. class Read implements Runnable  
  4. {  
  5.     private PipedInputStream in;  
  6.     Read(PipedInputStream in)  
  7.     {  
  8.         this.in = in;  
  9.     }  
  10.     public void run()  
  11.     {  
  12.         try  
  13.         {  
  14.             byte[] buf = new byte[1024];  
  15.   
  16.             System.out.println("读取前。。。未阻塞");  
  17.             int len = in.read(buf);  
  18.             System.out.println("读取后。。。阻塞结束");  
  19.   
  20.             String s = new String(buf,0,len);  
  21.             System.out.println(s);  
  22.             in.close();  
  23.         }  
  24.         catch (IOException e)  
  25.         {  
  26.             throw new RuntimeException("管道读取流失败");  
  27.         }     
  28.     }  
  29. }  
  30. class Write implements Runnable  
  31. {  
  32.     private PipedOutputStream out;  
  33.     Write(PipedOutputStream out)  
  34.     {  
  35.         this.out = out;  
  36.     }  
  37.     public void run()  
  38.     {  
  39.         try  
  40.         {  
  41.             System.out.println("6秒后写入数据");  
  42.             //释放执行权   
  43.             Thread.sleep(6000);  
  44.             out.write("piped coming".getBytes());  
  45.             out.close();  
  46.         }  
  47.         catch (Exception e)  
  48.         {  
  49.             throw new RuntimeException("管道输出流失败");  
  50.         }  
  51.     }  
  52. }  
  53. class PipedStreamDemo    
  54. {  
  55.     public static void main(String[] args) throws IOException  
  56.     {  
  57.         PipedInputStream in = new PipedInputStream();  
  58.         PipedOutputStream out = new PipedOutputStream();  
  59.         //连接输入流和输出流   
  60.         in.connect(out);  
  61.   
  62.         Read r = new Read(in);  
  63.         Write w = new Write(out);  
  64.         new Thread(r).start();  
  65.         new Thread(w).start();  
  66.     }  
  67. }  
PS:
集合中涉及到IO流的是Properies;IO中涉及到多线程的是管道流。

八、其他

1、操作基本数据类型:DataInputStream、DataOutputStream:用于操作基本数据类型的流对象。
相关方法:
writeUTF(String str):以与机器无关方式使用UTF-8修改版编码将一个字符串写入基础输出流。
意味着:只能通过对应的方法读取数据,用转换流读不出来。
readUTF(String str):专门用于读取UTF-8修改版编码。
PS:
UTF-8修改版占8个字节;UTF-8占6个字节;gbk占4个字节。假如用其他方法读取UTF-8修改版编码,
会出现EOFException异常,因为它需要读取8个字节才能结束,用其他方法读取会提前结束。
[java] view plaincopyprint?
  1. //操作基本数据类型:DataInputStream、DataOutputStream  
  2. import java.io.*;  
  3. class DataStreamDemo   
  4. {  
  5.     public static void main(String[] args) throws IOException   
  6.     {  
  7.         writeData();  
  8.         readData();  
  9.         writeUTFDemo();  
  10.         readUTFDemo();  
  11.     }  
  12.     public static void readUTFDemo() throws IOException  
  13.     {  
  14.         DataInputStream dis = new DataInputStream(new FileInputStream("utf.txt"));  
  15.   
  16.         String s = dis.readUTF();  
  17.   
  18.         System.out.println(s);  
  19.         dis.close();  
  20.     }  
  21.     public static void writeUTFDemo() throws IOException  
  22.     {  
  23.         DataOutputStream dos = new DataOutputStream(new FileOutputStream("utf.txt"));  
  24.   
  25.         dos.writeUTF("你好");  
  26.   
  27.         dos.close();  
  28.     }  
  29.     public static void readData() throws IOException  
  30.     {  
  31.         DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));  
  32.   
  33.         //读取顺序要与写入顺序相同   
  34.         int num = dis.readInt();  
  35.         boolean b = dis.readBoolean();  
  36.         double d = dis.readDouble();  
  37.   
  38.         System.out.println("num="+num);  
  39.         System.out.println("b="+b);  
  40.         System.out.println("d="+d);  
  41.           
  42.         dis.close();  
  43.     }  
  44.     public static void writeData() throws IOException  
  45.     {  
  46.         DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));  
  47.   
  48.         dos.writeInt(255);  
  49.         dos.writeBoolean(true);  
  50.         dos.writeDouble(9885.1516);  
  51.   
  52.         dos.close();  
  53.     }  
  54. }  
2、操作字节数组
ByteArrayInputStream:在构造时,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream:在构造时,不用定义数据目的。因为该对象中已经在内部封装了可变长度的字节数组,
也就是数据目的地。其缓冲区随着数据的不断写入而自动增长。
特点:这两个流对象都操作的是数组,没使用系统资源,不用进行close关闭。
优点:增加了对象的封装性;代码的复用性;用流的读写思想来操作数组,简化了书写。
流操作规律:
源设备:
  键盘 System.in  硬盘 FileStream  内存 ArrayStream
目的设备:
  控制台 System.out 硬盘 FileStream  内存 ArrayStream

[java] view plaincopyprint?
  1. //操作字节数组:ByteArrayInputStream、ByteArrayOutputStream  
  2. import java.io.*;  
  3. class ByteArrayStream   
  4. {  
  5.     public static void main(String[] args)   
  6.     {  
  7.         //数据源   
  8.         ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFG".getBytes());  
  9.       
  10.         //数据目的   
  11.         ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  12.   
  13.         int by = 0;  
  14.   
  15.         while((by=bis.read())!=-1)  
  16.         {  
  17.             bos.write(by);  
  18.         }  
  19.         //获取输出数组大小   
  20.         System.out.println(bos.size());  
  21.         System.out.println(bos.toString());  
  22.         //将此byte数组输出流的全部内容写入到指定的输出流参数中,会报出异常。  
  23.         //bos.writeTo(new FileOutputStream("a.txt"));  
  24.     }  
  25. }  
3、操作字符数组:CharArrayReader、CharArrayWrite
4、操作字符串:StringReader、StringWriter

九、字符编码

1、编码表由来:
计算机只能识别二进制数据,早期由来是电信号。为了方便用于计算机,让它可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表--->编码表。
2、分类
ASCII:美国标准信息交换码:用一个字节的7位表示;
ISO8859-1:拉丁码表(欧洲码表):用一个字节的8位表示;
GB2312:中国的中文编码表;两个字节表示一个字符,两个字节的高位都是1,兼容和避免了跟ASCII码重复;
GBK:升级版的中文编码表,融合了更多的中文文字符号;有两万左右字符;
Unicode:国际标准码,融合入了多种文字。所有文字都用两个字节来表示,java语言使用的就是Unicode;
UTF-8:按字符大小分配存储空间,最多三个字节表示一个字符,并在首字母加入标识符,便于区分。
3、字符编码
3.1字符流的出现为了方便操作字符,更重要的是加入了编码转换。
编码转换通过子类转换流来完成:InputStreamReader、OutputStreamWriter。
在两个对象进行构造的时候可以加入字符集。
[java] view plaincopyprint?
  1. //字符编码:编码转换:InputStreamReader、OutputStreamWriter  
  2. import java.io.*;  
  3. class EncodeStream   
  4. {  
  5.     public static void main(String[] args) throws IOException  
  6.     {  
  7.         writeText();  
  8.         readText();  
  9.     }  
  10.     public static void readText() throws IOException  
  11.     {  
  12.         InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"UTF-8");  
  13.   
  14.         char[] buf = new char[10];  
  15.         int len =isr.read(buf);  
  16.   
  17.         String str = new String(buf,0,len);  
  18.   
  19.         System.out.println(str);  
  20.   
  21.         isr.close();  
  22.     }  
  23.     public static void writeText() throws IOException  
  24.     {  
  25.         OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");  
  26.   
  27.         osw.write("你好");  
  28.   
  29.         osw.close();  
  30.     }  
  31. }  
3.2 编码:
字符串变字节数组:String-->byte[];  
byte[] getBytes(String charsetName):使用指定的字符集将此String解码为字节序列,并存储到数组中。
3.3 解码:
字节数组变字符串:byte[]-->String;  
String(byte[],charsetName):将数组变成字符串。

[java] view plaincopyprint?
  1. /* 
  2. 编码:字符串变字节数组;解码:字节数组变字符串。 
  3. 注意utf-8和GBK都识别中文的情况,因为都是别中文,它们之间解码会造成源码改变的情形。 
  4. */  
  5. import java.util.*;  
  6. class  EncodeDemo  
  7. {  
  8.     public static void main(String[] args) throws Exception  
  9.     {  
  10.         String s = "你好";  
  11.         //编码   
  12.         byte[] b1 = s.getBytes("gbk");  
  13.           
  14.         System.out.println(Arrays.toString(b1));  
  15.         //错误解码  因为ISO8859-1是拉丁码表,不包含中文码表,必然造成乱码。  
  16.         String s1 = new String(b1,"ISO8859-1");  
  17.   
  18.         System.out.println("s1="+s1);  
  19.   
  20.         //再编码  虽然s1是乱码,但也是一个字符对象,它的字节数组未变。  
  21.         //所以我们依旧可以通过字节数组获取正确的解码值。  
  22.         byte[] b2 = s1.getBytes("ISO8859-1");   
  23.   
  24.         System.out.println(Arrays.toString(b2));  
  25.   
  26.         //正确解码   
  27.         String s2 = new String(b2,"gbk");  
  28.         System.out.println("s2="+s2);         
  29.     }  
  30. }  
运行结果:

十、应用

[java] view plaincopyprint?
  1. /* 
  2. 有五个学生,每个学生有3门课的成绩。 
  3. 从键盘输入以上数据(包括姓名,三门课成绩), 
  4. 输入的格式:如:zhangsan,30,40,60计算出总成绩。 
  5. 并把学生的信息和总分数从高到低存放在磁盘文件"stud.txt"中。 
  6.  
  7. 步骤: 
  8. 1,描述学生对象。 
  9. 2,定义一个可操作学生对象的工具类。 
  10.  
  11. 思路: 
  12. 1,通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象。 
  13. 2,学生有很多,那么就需要存储,使用到集合。要对学生的总分排序。可以使用TreeSet。 
  14. 3,将集合的信息写入到一个文件中。 
  15. */  
  16. import java.io.*;  
  17. import java.util.*;  
  18.   
  19. class Student implements Comparable<Student>  
  20. {  
  21.     private String name;  
  22.     private int ma,cn,en;  
  23.     private int sum;  
  24.     Student(String name,int ma,int cn,int en)  
  25.     {  
  26.         this.name = name;  
  27.         this.ma = ma;  
  28.         this.cn = cn;  
  29.         this.en = en;  
  30.         sum = ma + cn + en;  
  31.     }  
  32.     //自然排序:返回负整数、零或正整数。根据此对象是小于、等于还是大于指定对象。  
  33.     public int compareTo(Student s)   
  34.     {  
  35.         int num = new Integer(this.sum).compareTo(new Integer(s.sum));  
  36.         if(sum==0)  
  37.             return this.name.compareTo(s.name);  
  38.         return num;  
  39.     }  
  40.     public String getName()  
  41.     {  
  42.         return name;  
  43.     }  
  44.     public int getSum()  
  45.     {  
  46.         return sum;  
  47.     }  
  48.     public int hashCode()  
  49.     {  
  50.         return name.hashCode()+sum*78;//保证值的唯一性。  
  51.     }  
  52.     //判断是否是同一个人。   
  53.     public boolean equals(Object obj)  
  54.     {  
  55.         if(!(obj instanceof Student))  
  56.             throw new ClassCastException("类型不匹配");  
  57.         Student s = (Student)obj;  
  58.   
  59.         return this.name.equals(s.name) && this.sum==s.sum;  
  60.     }  
  61.     public String toString()  
  62.     {  
  63.         return "student["+name+","+ma+","+cn+","+en+"]";  
  64.     }  
  65. }  
  66. class StudentInfoTool  
  67. {  
  68.     //默认比较方式   
  69.     public static Set<Student> getStudents() throws IOException  
  70.     {  
  71.         return getStudents(null);  
  72.     }  
  73.     //比较器   
  74.     public static Set<Student> getStudents(Comparator<Student> cmp) throws IOException  
  75.     {  
  76.         BufferedReader bufr =  
  77.             new BufferedReader(new InputStreamReader(System.in));  
  78.   
  79.         String line = null;  
  80.   
  81.         Set<Student> stus = null;  
  82.         if(cmp==null)  
  83.             stus = new TreeSet<Student>();  
  84.         else  
  85.             stus = new TreeSet<Student>(cmp);  
  86.         while((line=bufr.readLine())!=null)  
  87.         {  
  88.             if("over".equals(line))  
  89.                 break;  
  90.             String[] info = line.split(",");  
  91.             //解析一个字符串,并返回一个整数   
  92.             Student stu = new Student(info[0],Integer.parseInt(info[1]),  
  93.                             Integer.parseInt(info[2]),  
  94.                             Integer.parseInt(info[3]));  
  95.   
  96.             stus.add(stu);  
  97.         }  
  98.         bufr.close();  
  99.   
  100.         return stus;  
  101.     }  
  102.     public static void writeFile(Set<Student> stus) throws IOException  
  103.     {  
  104.         BufferedWriter bufw = new BufferedWriter(new FileWriter("stuinfo.txt"));  
  105.   
  106.         for(Student stu : stus)  
  107.         {  
  108.             bufw.write(stu.toString() + "\t");  
  109.             bufw.write(stu.getSum() + "");  
  110.             bufw.newLine();  
  111.             bufw.flush();  
  112.         }  
  113.         bufw.close();  
  114.     }  
  115. }  
  116. class  StudentInfoTest  
  117. {  
  118.     public static void main(String[] args) throws IOException  
  119.     {  
  120.         //定义比较器,强行逆转   
  121.         Comparator<Student> cmp = Collections.reverseOrder();  
  122.   
  123.          Set<Student> stus = StudentInfoTool.getStudents(cmp);  
  124.   
  125.          StudentInfoTool.writeFile(stus);  
  126.     }  
  127. }
0 0
原创粉丝点击