Java基础之IO流知识点总结三
2014-12-01 21:02
701 查看
File类: 该类的出现是对文件系统中的文件以及文件夹进行对象的封装。可以通过对象的思想来操作文件以及文件夹。 1. 构造函数: File(String filename):将一个字符串路径(相对或者绝对)封装成File对象,该路径是可以存在的,也是可以不存在的。 File(Stringparent,String child); File(Fileparent,String child); 2. 特别的字段:separator:跨平台的目录分隔符 eg.File file = newFile(“C:”+File.separator+”abc”+File.separator+”a.txt”); 3. 常见方法: 1) 创建: boolean createNewFile() throwsIOException:创建文件,如果被创建的文件已经被创建,则不再创建。 boolean mkdir():创建文件夹。 boolean mkdirs():创建多级文件夹。 2) 删除: boolean delete():可用于删除文件或者文件夹。 注意:对于文件夹只能删除不带内容的空文件夹;则对于带内容的文件夹,不可以直接删除,必须要从里往外依次删除。 void deleteOnExit():删除动作将在系统完成时触发。无论是否发生异常,系统在退出时执行删除动作。 3) 判断: boolean canExecute():该文件是否能执行。 boolean canWrite():是否是可写文件 boolean canRead():是否是可读文件 boolean exists():判断文件或者文件夹是否存在。 boolean isFile():判断File对象中封装的是否是文件。 boolean isDirectory():判断File对象中封装的是文件夹。 boolean isHidden():判断文件或者文件夹是否隐藏,在获取硬盘文件或者文件夹时,对于系统目录中的文件,java是无法访 问的。所以遍历,可以避免遍历隐藏文件。 4) 获取: String getName():获取文件或者文件夹的名称。 String getPath():File对象中封装的路径是什么,获取的就是什么。 String getAbsolutePath():无论File对象中封装的路径是什么,获取的都是绝对路径。 String getAbsoluteFile():也返回绝对路径,但是把绝对路径封装成了对象。 getParent():获取File对象封装文件或者文件夹的父目录。 注意:如果封装的相对路径,那么返回的是null; long length():获取文件大小。 long lastModified():获取文件或者文件最后一次修改的时间 static File[] listRoots():获取的是被系统所用的有效盘符。 string[] list():获取指定目录下当前的文件以及文件夹名称。 string[] list(Filenamefilter): 可以根据指定的过滤器,过滤后的文件及文件夹名称。 File[] listFiles():获取指定目录下的文件以及文件夹对象。 5) 重命名: renameTo(File): File f1 = newFile("c:\\a.txt"); File f2 = newFile("c:\\b.txt"); f1.renameTo(f2);//将c盘下的a.txt文件改名为b.txt文件。
例子1:File类的基本方法的使用。
package cn.itheima.day04; /** * File类的常见方法: * 1.创建 * boolean createNewFile() throws IOException * 特点:创建文件,如果被创建的文件已经被创建,则 * 不再被创建。和输出流对象不一样,输出流对象 * 一建立创建文件,而且文件已经存在回覆盖。 * boolean mkdir():创建文件夹。 boolean mkdirs():创建多级文件夹。 * 2.删除 * boolean delete():可用于删除文件或者文件将夹。 * 如果文件中有内容,是直接删除删除不掉的。 * 删除失败返回false * void deleteOnExit():删除动作将在系统完成时触发。 * 无论是否发生异常,系统在退出时执行删除动作。 * 3.判断 * boolean exists():文件是否存在。 * boolean isFile():判断File对象中封装的是否是文件。 boolean isDirectory():判断File对象中封装的是文件夹。 boolean isHidden():判断文件或者文件夹是否隐藏,在获取硬盘文件或者文件夹时,对于系统目录中的文件,java是无法访问的。所以遍历,可以避免遍历隐藏文件。 * String getName():获取文件或者文件夹的名称。 String getPath():File对象中封装的路径是什么,获取的就是什么。 String getAbsolutePath():无论File对象中封装的路径是什么,获取的都是绝对路径。 String getAbsoluteFile():也返回绝对路径,但是把绝对路径封装成了对象。 getParent():获取File对象封装文件或者文件夹的父目录。 注意:如果封装的相对路径,那么返回的是null; long length():获取文件大小。 long lastModified():获取文件或者文件最后一次修改的时间 static File[] listRoots():获取的是被系统所用的有效盘符。 string[] list():获取指定目录下当前的文件以及文件夹名称。 string[] list(Filenamefilter): 可以根据指定的过滤器,过滤后的文件及文件夹名称。 File[] listFiles():获取指定目录下的文件以及文件夹对象。 重命名: renameTo(File): File f1 = new File("c:\\a.txt"); File f2 = new File("c:\\b.txt"); f1.renameTo(f2);//将c盘下的a.txt文件改名为b.txt文件。 */ import java.io.File; import java.io.IOException; public class FileDemo { public static void main(String[] args) throws IOException { consMethod(); //method_1(); //method_2(); //method_3(); method_5(); } public static void method_5(){ File f1 = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file.txt"); File f2 = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file_copy.txt"); sop("rename"+f1.renameTo(f2)); } public static void method_3(){ 18aa5 File f1 = new File("a.txt"); sop("path:"+f1.getPath()); sop("AbsolutePath:"+f1.getAbsolutePath()); //该方法返回的是绝对路径下的付目录,如果获取相对路径,返回null //如果相对路径中有上一层目录,那么该目录就是返回结果。 sop("parent:"+f1.getParent()); } public static void method_2(){ File file = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file.txt"); sop("execute:"+file.canExecute()); sop("exists:"+file.exists()); File dir = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\wang\\abc\\dd"); //System.out.println("mkdir:"+dir.mkdir()); //返回最多一级文件夹 sop("mkdirs:"+dir.mkdirs()); //返回多级文件夹 //注意:对一个文件对象或者文件夹判断是它是文件还是文件夹时,此时, //文件必须是存在的,通过exists()方法判断。 sop("file:"+file.isFile()); //判断是否为文件 sop("dir:"+dir.isDirectory()); //判断是否为文件夹 sop("absolute:"+file.isAbsolute()); //判断是否为绝对路径 } public static void method_1() throws IOException{ File file = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\file.txt"); File deletefile = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04\\deletefile.txt"); sop("create:"+file.createNewFile()); sop("delete:"+deletefile.delete()); } //创建File对象 public static void consMethod(){ //将a.txt封装成file对象,可以将已有的和未出现的文件及文件夹封装成对象 File f1 = new File("a.txt"); //第二种方式(想操作的目录下的文件时可以变化的) File f2 = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04","b.txt"); //第三种方式 File d = new File("F:\\Javajichu\\JavaLianXi\\src\\cn\\itheima\\day04"); File f3 = new File(d,"c.txt"); //separator跨平台的分隔符 File f4= new File("F:"+File.separator+"Javajichu"+File.separator+"JavaLianXi" +File.separator+"src"+File.separator+"cn"+File.separator+"itheima" +File.separator+"day04"+File.separator+"e.txt"); sop("f1="+f1); sop("f2="+f2); sop("f3="+f3); sop("f4="+f4); } public static void sop(Object obj){ System.out.println(obj); } }
递归: 其实就是在使用一个功能过程中,又对该功能有需求。就出现了函数自身调用自身。 注意: 1,一定要限定条件,否则内存溢出。 2,使用递归时,调用次数不要过多,否则也会出现内存溢出。
例子2:想要列出指定目录下的文件以及文件夹中的文件(子文件)。
package cn.itheima.day04; import java.io.File; /** * 列出指定文件目录下的文件或者文件夹,包含子目录的内容, * 也就是列出该文件下的所有内容 * * 因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。 * 在列出的目录过程中列出的还是目录,还可以再次调用本功能,也就是 * ,函数自身调用自身,则我们称这种方式为递归。 * * 递归要限定的条件是: * 1.要有限定条件。 * 2.使用递归时,调用次数不要过多,否则也会出现内存溢出。 * @author wl-pc */ public class FileDemo3 { public static void main(String[] args) { File dir = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\"); showDir(dir,2); //toBin(6); //int n = getSum(10); //sop("n="+n); } 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){ sop(getLevel(level)+dir.getName()); level++; File[] files = dir.listFiles(); for (int x = 0;x<files.length; x++) { //判断files是否为文件夹还是文件 if(files[x].isDirectory()){ //若files是文件夹,则应该接着进行列表显示 showDir(files[x],level); }else{ sop(getLevel(level)+files[x]); } } } //求6的二进制数 public static void toBin(int num){ if(num>0){ //递归调用 toBin(num/2); sop(num%2); //没次都先被执行 //num = num/2; } } //求和 public static int getSum(int n){ if(n==1) return 1; return n+getSum(n-1); } public static void sop(Object obj){ System.out.println(obj); } }
例子3:删除一个带内容的目录。
package cn.itheima.day04; import java.io.File; /** * 删除一个带内容的目录。 * 删除原理: 在windows删除目录是从里面往外.既然 * 从里往外删除,就需要用到了递归。 * @author wl-pc */ public class RemoveDir { public static void main(String[] args) { File file = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\aa"); removeDir(file); } //删除文件夹 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.toString()+":dir:"+dir.delete()); } }
例子4:将一个指定目录下所有的java文件的绝对路径,存储到一个文本文件中,建立一个java文件的列表文件。
package cn.itheima.day04; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * 练习: * 将一个指定目录下所有的java文件的绝对路径,存储到一个文本文件中。 * 建立一个java文件的列表文件。 * 思路: * 1.对指定的目录进行递归。 * 2.获取在递归过程中所有java文件的路径。 * 3.将这些路径存储到集合中。 * 4.将集合中的数据写入到一个文件中。 * @author wl-pc */ public class JavaFileList { public static void main(String[] args) throws IOException { File dir = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\"); List<File> list = new ArrayList<File>(); fileToList(dir,list); System.out.println(list.size()); File file = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\","javaList.txt"); writeToFile(list,file.toString()); } public static void fileToList(File dir,List<File> list){ File[] files = dir.listFiles(); for (File file : files) { if(file.isDirectory()){ //遍历目录,如果是目录则继续遍历。 fileToList(file, list); //调用递归方法 }else{ if(file.getName().endsWith(".java")){ //将得到的java文件存储到集合中 list.add(file); } } } } //数据持久化 public static void writeToFile(List<File> list,String javaListFile) throws IOException{ BufferedWriter bufw=null; //javaListFile = "F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\"; try { bufw = new BufferedWriter(new FileWriter(javaListFile)); for (File f : list) { String path = f.getAbsolutePath(); //获取绝对路径 bufw.write(path); bufw.newLine(); bufw.flush(); } } catch (IOException e) { throw e; }finally{ try { if(bufw!=null){ bufw.close(); } } catch (IOException e) { throw e; } } } }
例子5:利用Perperties类得到它里面存储的数据信息的值。
package cn.itheima.day04; import java.util.Properties; import java.util.Set; /** * Perperties是hashtable的子类,也就是说它具备了map集合的特点,而且 * 它里面存储的都是字符串,不需要泛型。 * 是集合中和IO技术相结合的集合容器。 * 该对象的特点可以用于键值对形式的配置文件。 * @author wl-pc */ public class PropertiesDemo { public static void main(String[] args) { setAndGet(); } //设置和回去元素 public static void setAndGet(){ Properties properties = new Properties(); properties.setProperty("zhangsan", "30"); //设置属性,按键值对形式设置。 properties.setProperty("lisi", "39"); //System.out.println(properties); String value = properties.getProperty("lisi"); //System.out.println(value); properties.setProperty("lisi", "89"); Set<String> values = properties.stringPropertyNames(); for (String s : values) { System.out.println(s+"::"+properties.getProperty(s)); } } }
例子6:利用Properties类读取文件中的数据(数据格式为:键=值)存储到集合中,并读取到控制台上,并且可以修改文件中的数据。
package cn.itheima.day04; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.util.Properties; import java.util.Set; /** * Perperties是hashtable的子类,也就是说它具备了map集合的特点,而且 * 它里面存储的都是字符串,不需要泛型。 * 是集合中和IO技术相结合的集合容器。 * 该对象的特点可以用于键值对形式的配置文件。 * 在加载数据时需要数据要有固定的格式,通常是:键=值 * @author wl-pc */ public class PropertiesDemo { public static void main(String[] args) throws IOException { //setAndGet(); //method_1(); loadDemo(); } public static void loadDemo(){ FileInputStream fis=null; FileOutputStream fos=null; try { Properties properties = new Properties(); fis = new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\info.txt"); properties.load(fis); //将流中的数据加载到集合中 //System.out.println(properties); //properties.list(System.out); //列出集合目录 properties.setProperty("wangwu", "99"); //改变内存中的数据的值,不改变文件中的值 fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\info.txt"); properties.store(fos, "haha"); //将内存中的结果存储到一个流中,并且存储到一个文件中。 System.out.println(properties); } catch (FileNotFoundException e) { System.out.println(e.toString()); } catch (IOException e) { System.out.println(e.toString()); }finally{ if(fis!=null){ try { fis.close(); } catch (IOException e) { System.out.println(e.toString()); } } if(fos!=null){ try { fos.close(); } catch (IOException e) { System.out.println(e.toString()); } } } } //演示:如何将流中的数据存储到集合中 //想要将Info.xt中的键值数据存储到集合中的操作 /** * 思路: * 1.用一个流和info.txt文件关联。 * 2.读取一行数据,将该行数据用等号进行切割。 * 3.等号左边作为键,右边作为值,存入到Properties中即可。 * @throws IOException */ public static void method_1() throws IOException{ BufferedReader bufr=null; try { bufr = new BufferedReader(new FileReader("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\info.txt")); String line = null; Properties properties = new Properties(); while((line = bufr.readLine())!=null){ String[] arr = line.split("="); System.out.println(arr[0]+"----"+arr[1]); properties.setProperty(arr[0], arr[1]); } System.out.println(properties); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ if(bufr!=null){ bufr.close(); } } } //设置和回去元素 public static void setAndGet(){ Properties properties = new Properties(); properties.setProperty("zhangsan", "30"); //设置属性,按键值对形式设置。 properties.setProperty("lisi", "39"); //System.out.println(properties); String value = properties.getProperty("lisi"); //System.out.println(value); properties.setProperty("lisi", "89"); Set<String> values = properties.stringPropertyNames(); for (String s : values) { System.out.println(s+"::"+properties.getProperty(s)); } } }
例子7:用于记录应用程序运行的次数,如果使用次数已到,那么给出注册提示。
package cn.itheima.day04; <pre>import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; /** * 用于记录应用程序运行的次数。 * 如果使用次数已到,那么给出注册提示。 * 很容易想到使用计数器。 * 可是,该计数器定义在程序中,随着程序的运行而在内存中存在,并且进行自增, * 可是,随着该应用程序的退出,该计数器也在内存中消失了。 * 下一次,在程序启动时,又重新开始从0记数了 * 这样不是我们想要的。 * * 程序即使结束,该计数器的值也存在。 * 下次程序启动时也会先加载该计数器的值,并且技术加1后在重新存储起来, * * 所以要建立一个配置文件,用于记录该软件的使用次数。 * 该配置文件使用键值对的形式,这样便于阅读数据,操作数据。 * 键值对数据,是一个map集合。 * 数据是以文件的形式存储的,所以要使用io技术。 * 那么,map+io----->properties. * 配置文件可以实现应用程序的数据的共享。 * @author wl-pc */ public class RunCount { public static void main(String[] args) throws IOException { Properties properties = new Properties(); FileInputStream fis=null; File file = new File("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\count.txt"); if(!file.exists()) file.createNewFile(); else fis = new FileInputStream(file); properties.load(fis); int count = 0; String value = properties.getProperty("time"); if(value!=null){ count = Integer.parseInt(value); if(count>=5){ System.out.println("你好,你使用的次数已到,请注册后,使用。"); } } count++; properties.setProperty("time", count+""); FileOutputStream fos = new FileOutputStream(file); properties.store(fos, "hello"); fos.close(); fis.close(); }
}
IO包中常见的对象: 字节流: FileInputStream FileOutputStream BufferedInputStream BufferedOutputStream 字符流: FilerReader FileWriter BufferedReader BufferedWriter 转换流: InputStreamReader OutputStreamWriter 文件对象: File 打印流: PrintStream PrintWriter 注意:所有的带File的流对象都可以直接操作File对象。 IO包中的其他对象: 1.打印流 PrintStream:是一个字节打印流,System.out对应的类型就是PrintStream. 它的构造函数可以接收三种数据类型。 1. 字符串路径。 2. File对象 3. OutputStream PrintWriter:是一个字符打印流,构造函数可以接收四种类型的值。 1. 字符串路径。 2. File对象。 对于1.2类型的数据,还可以指定编码表。也就是字符集。 3. OutputStream 4. Writer 对于3.4类型的数据,可以指定自动刷新。 注意:该自动刷新的值为true时,只有三个方法可用:println,printf,format. //如果想要既有自动刷新,又可执行编码。如何完成流对象的包装呢? PrintWriter pw = new PrintWriter(newOutputStreamWriter(new FileOutputStream(“a.txt”))); //如果想要提高效率,还要使用打印方法。 PrintWrterpw = newPrintWriter(new BufferdWriter(new OutputSteamWriter(new FileOutputStream("a.txt"),"utf-8")),true);
例子8:用打印流对象,用打印流接收用户在控制台输入的数据,然后用打印流输出到控制台上或者一个文件中
package cn.itheima.day04; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; public class PrintStreamDemo { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); //PrintWriter out = new PrintWriter(System.out,true); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\a.txt")),true); String line=null; while((line=br.readLine())!=null){ if("over".equals(line)){ break; } out.println(line.toUpperCase()); //out.flush(); } out.close(); br.close(); } }
2.序列流,也成合并流。 SequenceInputStream: 特点:可以将多个读取流合并成一个流,这样操作起来很方便。 原理:其实就是将每一个读取流对象存储到一个集合中,最后一个流对象结尾作为这个流的结尾。 两个构造函数: 1. SequenceInputStream(InputStreamin1,InputStream in2):可以将两个读取流合并成一个流。 2. SequenceInputStream(Enumeration<?Extents InputStream> en):可以将枚举中的多个流合并成一个流。
例子9:将3个读取流文件合并成一个读取流文件。
package cn.itheima.day04; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; import java.util.Enumeration; import java.util.Vector; public class SequenceDemo { public static void main(String[] args) throws IOException { Vector<FileInputStream> v = new Vector<FileInputStream>(); v.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\1.txt")); v.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\2.txt")); v.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\3.txt")); Enumeration<FileInputStream> en = v.elements(); //枚举类型(将多个读取流合并成一个读取流) SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\4.txt"); byte[] buf = new byte[1024]; int len = 0; while((len=sis.read(buf))!=-1){ fos.write(buf,0,len); } fos.close(); sis.close(); } }
作用:可以用于多个数据的合并。 注意:因为Enumeration是Vector中特有的取出方式。而Vector被ArrayList取代。所以要使用ArrayList集合效率更高一些。
那么如何获取Enumeration呢?
ArrayList<FileInputStream > al = new ArrayList<FileInputStream>(); for(int x=1; x<4; x++) al.add(new FileInputStream(x+".txt")); Iterator<FileInputStream> it = al.iterator(); Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){ public boolean hasMoreElements(){ return it.hasNext(); } public FileInputStream nextElement(){ return it.next(); } }; //多个流就变成了一个流,这就是数据源。 SequenceInputStream sis = new SequenceInputStream(en); //创建数据目的。 FileOutputStream fos = new FileOutputStream("4.txt"); byte[] buf = new byte[1024*4]; int len = 0; while((len=sis.read(buf))!=-1){ fos.write(buf,0,len); } fos.close(); sis.close();
例子10.文件的切割和合并。
package cn.itheima.day04; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.SequenceInputStream; import java.util.ArrayList; import java.util.Enumeration; public class SplitFile { public static void main(String[] args) throws IOException { //splitFile(); merge(); } //合并文件 public static void merge() throws IOException{ ArrayList<FileInputStream> aList = new ArrayList<FileInputStream>(); for(int x = 1;x<=4;x++){ aList.add(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\pic\\"+x+".part")); } final java.util.Iterator<FileInputStream> it = aList.iterator(); Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() { public boolean hasMoreElements() { return it.hasNext(); } public FileInputStream nextElement() { return it.next(); } }; SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\pic\\0.png"); byte[] buf = new byte[1024]; int len=0; while((len=sis.read(buf))!=-1){ fos.write(buf,0,len); } fos.close(); sis.close(); } //切割文件 public static void splitFile() throws IOException{ FileInputStream fis = new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\1.png"); FileOutputStream fos = null; byte[] buf = new byte[1024*1024]; int len =0; int count =1; while((len=fis.read(buf))!=-1){ fos = new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day04\\pic\\"+(count++)+".part"); fos.write(buf,0,len); fos.close(); } if(fos!=null){ fos.close(); } fis.close(); } }
操作对象的流: ObjectInputStream ObjectOutputStream 可以通过这两个流对象直接操作已有的对象,并将对象进行本地持久化存储。存储后的对象可以进行网络传输。 两个对象的特有方法: ObjectInputStream Object readObject():该方法抛出异常:ClassNotFountException ObjectOutputStream void writeObject(Object):被写入的对象必须实现一个接口:Serializable,否则会抛出异常:NotSerializableException Serializable:该接口其实就是一个没有方法的标记接口。 用于给类指定一个UID。该UID是通过类中的可序列化成员的数字签名运出来的一个long型的值。只要是这些成员没有变化,那么该值每次运算都一样。该值用于判断被序列化的对象和类文件是否兼容。如果被序列化的对象需要被不同的类版本所兼容。可以在类中自定义UID。 定义方式:static final long serialVersionUID = 42L; 注意:对应静态的成员变量,不会被序列化。 对应非静态也不想被序列化的成员而言,可以通过transient关键字修饰。
例子11.利用ObjectInputStream和ObjectOutputStream,写入和读取文件中的数据
package cn.itheima.day05; import java.io.Serializable; public class Person implements Serializable{ private static final long serialVersionUID = 42L; //固定标示 private String name; transient int age; //对非静态的属性不想序列化的话,可以加一个关键字transient static String country="cn"; //静态不能被序列化 public Person() { super(); } public Person(String name, int age,String country) { super(); this.name = name; this.age = age; this.country=country; } public static String getCountry() { return country; } public static void setCountry(String country) { Person.country = country; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + ",country=" + country + "]"; } } package cn.itheima.day05; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class ObjectStreamDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { //writeObj(); readObj(); } //读文件中的持久化类 public static void readObj() throws IOException, ClassNotFoundException{ ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\obj.txt")); Person person = (Person)ois.readObject(); System.out.println(person); ois.close(); } //把类变成持久化 public static void writeObj() throws IOException{ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\obj.txt")); oos.writeObject(new Person("lisi0",39,"china")); oos.close(); } }
管道流: PipedInputStream PipedOutputStream 特点: 读取管道流和写入管道流可以进行连接。 连接的方式: 1. 通过两个流对象的构造函数。 2. 通过两个对象的connect方法。 通常两个流在使用时,需要加入多线程技术,也就是让读写同时运行。 注意:对于read方法。该方法是阻塞式的,也就是没有数据的情况,该方法会等
例子12.管道流的应用,用到多线程的知识。
package cn.itheima.day05; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; class Read implements Runnable { private PipedInputStream in; Read(PipedInputStream in){ this.in = in; } public void run() { try { byte[] buf = new byte[1024]; int len = 0; System.out.println("读取前没有数据,阻塞"); len = in.read(buf); System.out.println("读取到数据,阻塞结束"); String s = new String(buf,0,len); System.out.println(s); in.close(); } catch (IOException e) { throw new RuntimeException("管道读取流失败"); } } } class Writer implements Runnable { private PipedOutputStream out; public Writer(PipedOutputStream out) { this.out = out; } public void run() { try { System.out.println("开始写入数据等待6秒后"); Thread.sleep(6000); out.write("管道 来啦".getBytes()); out.close(); } catch (IOException e) { throw new RuntimeException("管道输出流失败"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public class PipedStream { public static void main(String[] args) throws IOException { PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(); in.connect(out); Read r = new Read(in); Writer w= new Writer(out); new Thread(r).start(); new Thread(w).start(); } }
RandomAccessFile类:
该类特点:该类不算IO体系中的子类,而是直接继承Object,但是它是IO包中的成员,因为它具备读和写功能,因为它内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过,getFilePointer获取指针位置,同时可以通过seek改变指针的位置。 其实完成读写的原理:内部封装了字节输入流和字节输出流。 通过构造函数,可以看出,该类只能操作文件,有局限性。 而且操作文件还有模式(4种):r(只读) rw(可读可写) rws rwd 而且该对象的构造函数要操作的文件不存在,会自动的创建,如果存在则不会覆盖。 如果模式是r: 则不会创建文件,会去读取一个已存在的文件,如果该文件不存在,则会出现异常。 如果模式是rw:操作的文件不存在,会自动创建,如果存在则不会原来的数据。
例子13:利用RandomAccessFile的seek()方法实现随机的读写和访问。
package cn.itheima.day05; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; public class RandomAccessFileDemo { public static void main(String[] args) throws IOException { //writeFile(); //writerFile_2(); readFile(); //System.out.println(Integer.toBinaryString(258)); } public static void readFile() throws IOException{ //RandomAccessFile可以随机的读写和访问。 RandomAccessFile raf=new RandomAccessFile("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\ran.txt", "r"); //raf.write("haha".getBytes());被屏蔽 //调整对象中的指针,来在指定的位置读取和写入数据 //raf.seek(8*1); //seek(long pos) 设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作(seek前后都能跳) //跳过指定的字节数((-1,0)缺点:不能往回跳(不能往-1跳),只能往前跳(往0跳)) raf.skipBytes(8*3); byte[] buf = new byte[4]; raf.read(buf); String name = new String(buf); System.out.println("name="+name); int age = raf.readInt(); System.out.println("age="+age); raf.close(); } public static void writerFile_2(){ try { RandomAccessFile raf = new RandomAccessFile("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\ran.txt", "rw"); //调整对象中的指针,来在指定的位置读取和写入数据 raf.seek(8*3); raf.write("周期".getBytes()); raf.writeInt(103); raf.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void writeFile(){ try { RandomAccessFile raf = new RandomAccessFile("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\ran.txt", "rw"); raf.write("张三".getBytes()); raf.writeInt(97); raf.write("王五".getBytes()); raf.writeInt(23); raf.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
操作基本数据类型的流对象:DataInputStream. DataInputStream: DatsInputStream(InputStream); 它操作的基本数据类型的方法: Int readInt():一次读取四个字节,并将其转换成int值。 booleanreadBoolean():一次读取一个字节。 short readShort(): longreadLong(); String readUTF():按照utf-8修改版读取字符。注意,它只能读取writeUTF()写入的字符数据。 DataOutputStream: DataOutputStream(OutputStream): 操作基本数据类型的方法: writeInt(int):一次写入四个字节。 注意和write(int)不同。write(int)只将该整数的最低一个8位写入。剩余三个8位丢弃。 writeBoolean(boolean); writeShort(short); writeLong(long); writeUTF(String):按照utf-8修改版将字符数据进行存储。只能通过readUTF读取。通常只要操作基本数据类型的数据。就需要通过DataStram进行包装。通常成对使用。
例子14:利用DataInputStream和DataOutputStream操作基本数据类型进行读写操作。
package cn.itheima.day05; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * 可以用于操作基本数据类型的数据。 * @author wl-pc */ public class DataStreamDemo { public static void main(String[] args) { //writeData(); //readData(); //WriteUtfDemo(); readUtfDemo(); } //读出utf格式的数据 public static void readUtfDemo(){ try { DataInputStream dis = new DataInputStream(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\utfdata.txt")); String value = dis.readUTF(); System.out.println(value); dis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //写入utf格式的数据 public static void WriteUtfDemo(){ try { DataOutputStream dos = new DataOutputStream(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\utfdata.txt")); dos.writeUTF("小明"); dos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //读取数据 public static void readData(){ try { DataInputStream dis = new DataInputStream(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\data.txt")); int num = dis.readInt(); boolean b = dis.readBoolean(); double d = dis.readDouble(); System.out.println("num="+num); System.out.println("b="+b); System.out.println("d="+d); dis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } //写入数据 public static void writeData(){ try { DataOutputStream dos = new DataOutputStream(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\data.txt")); dos.writeInt(234); dos.writeBoolean(true); dos.writeDouble(98.03); dos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
操作数组的流对象: 1,操作字节数组 ByteArrayInputStream:特点:在构造时需要接收数据源,而且数据源是一个字节数组, ByteArrayOutputStream 特点:在构造的时候,不用定义数组目的。因为该对象中已经内部封装了一个可变长度的字节数组。 toByteArray(); toString(); writeTo(OutputStream):输入内容到一个文件中。 因为这两个流对象都操作的是数组,并没有使用系统资源,所以,没有不用进行流的关闭。(即使流对象关闭,还是可以使用的。 在流---规律讲解时: 源设备: 键盘 System.in 硬盘FileStream 内存ArrayStream 目的: 控制台System.out 硬盘FileStream 内存ArrayStream 用流的读写思想去操作数据。
例子15:ByteArrayInputStream和ByteArrayOutputStream来读写数据。
package cn.itheima.day05; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class ByteArrayStream { public static void main(String[] args) throws FileNotFoundException, IOException { //明确数据源 ByteArrayInputStream bis = new ByteArrayInputStream("abcdefg".getBytes()); //明确数据目的 ByteArrayOutputStream bos = new ByteArrayOutputStream(); System.out.println(bos.size()); int by = 0; while ((by = bis.read())!=-1) { bos.write(by); } System.out.println(bos.size()); System.out.println(bos.toString()); bos.writeTo(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\a.txt")); } }
2,操作字符数组。 CharArrayReader CharArrayWriter 对于这些流,源是内存。目的也是内存。而且这些流并未调用系统资源。使用的就是内存中的数组。 所以这些在使用的时候不需要close。 操作数组的读取流在构造时,必须要明确一个数据源。所以要传入相对应的数组。 对于操作数组的写入流,在构造函数可以使用空参数。因为它内置了一个可变长度数组作为缓冲区。 编码转换: 在io中涉及到编码转换的流是转换流和打印流。但是打印流只有输出。在转换流中是可以指定编码表的。 默认情况下,都是本机默认的码表。GBK. 这个编码表怎么来的?System.getProperty("file.encoding"); 常见码表: ASCII:美国标准信息交换码。使用的是1个字节的7位来表示该表中的字符。 ISO8859-1:拉丁码表。使用1个字节来表示。 GB2312:简体中文码表。 GBK:简体中文码表,比GB2312融入更多的中文文件和符号。 unicode:国际标准码表。都用两个字节表示一个字符。 UTF-8:对unicode进行优化,每一个字节都加入了标识头。 编码转换: (String--àbyte[]) 字符串-->字节数组:编码。 通过str.getBytes(charset); (byte[]--àString) 字节数组-->字符串:解码。 通过String类的构造函数完成。new String(byte[],charset); 如果编错了,没救! 如果编对了,解错了,有可能还有救! String s = "你好"; //编码。 byte[] b =s.getBytes("GBK"); //解码。 String s1 = newString(b,"iso8859-1"); System.out.println(s1); //想要还原。 /* 对s1先进行一次解码码表的编码。获取原字节数据。 然后在对原字节数据进行指定编码表的解码。 */ byte[] b1 = s1.getBytes("iso8859-1"); String s2 = newString(b1,"gbk"); System.out.println(s2);//你好。 这种情况在tomcat服务器会出现。因为tomcat服务器默认是iso8859-1的编码表。所以客户端通过浏览器向服务端通过get提交方式提交中文数据时,服务端获取到会使用ISO8859-1进行中文数据的解码。会出现乱码。这时就必须要对获取的数据进行iso8859-1编码。然后在按照页面指定的编码表进行解码即可而对于post提交,这种方法也通用。但是post有更好的解决方式。 request.setCharacterEncoding("utf-8");即可。 所以建立客户端提交使用post提交方式。
例子16:写入和读出UTF-8编码和GBK编码的文件。
package cn.itheima.day05;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class EncodeStream {
public static void main(String[] args) {
//writeText();
readText();
}
public static void readText(){
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\gbk.txt"),"UTF-8");
int len = 0;
char[] buf = new char[10];
len = isr.read(buf);
String str = new String(buf,0,len);
System.out.println("str="+str);
isr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeText(){
try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\gbk.txt"),"UTF-8");
osw.write("你好");
osw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
例子17:中文乱码的解决方案。
package cn.itheima.day05; import java.io.UnsupportedEncodingException; import java.util.Arrays; public class EncodeDemo { public static void main(String[] args) throws UnsupportedEncodingException { String str = "你好"; byte[] b1 = str.getBytes("GBK"); //编码 //System.out.println(Arrays.toString(b1)); //Arrays.toString(b1) 把数组变成字符串 String s1 = new String(b1,"ISO8859-1"); //要用指定编码表来解码 //s1进行ISO8859-1编码 byte[] b2 = s1.getBytes("ISO8859-1"); System.out.println(Arrays.toString(b2)); //Arrays.toString(b2) 把数组变成字符串 //解码 String s2 = new String(b2,"GBK"); //解决方案,就是 编译一次,在解码一次 //System.out.println(s1); System.out.println(s2); } }
例子18:记事本敲“联通”,再次打开出现乱码的问题。查看“联通”的二进制数是符合GBK的编码,还是符合UTF-8的编码。
package cn.itheima.day05; import java.io.UnsupportedEncodingException; public class EncodeDemo2 { public static void main(String[] args) throws UnsupportedEncodingException { String s = "联通"; byte[] by = s.getBytes("GBK"); for (byte b : by) { System.out.println(Integer.toBinaryString(b&255)); } } }
例子19:有五名学生,每个学生有3门课的成绩,从键盘上输入以上数据,(包括姓名,和三门课的成绩,输出格式为:zhangsan,30,40,60,并且计算出总成绩,并把学生信息和计算出的总分数,按从高到低的顺序存放到硬盘的文件上”studentScore.txt”) 分析:1.描述学生对象。 2.定义一个可操作学生对象的工具类。 思想:1.通过获得键盘上录入的一行数据,并将该行中的信息,取出封装成学生对象 2.因为学生对象有很多,就需要使用集合,因为学生的总分要排序,所以可以使用TreeSet 3.将集合中的信息写入到一个文件中。
package cn.itheima.day05; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.Collections; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; class Student implements Comparable<Student>{ private String name; private int ma,cn,en; private int sum; public String getName() { return name; } public int getSum() { return sum; } public int hashCode(){ return name.hashCode()+sum*78; } public boolean equals(Object obj){ if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student s = (Student)obj; return this.name.equals(s.name) && this.sum==s.sum; } @Override public String toString() { return "Student [name=" + name + ", ma=" + ma + ", cn=" + cn + ", en=" + en + ", sum=" + sum + "]"; } public Student(String name, int ma, int cn, int en) { super(); this.name = name; this.ma = ma; this.cn = cn; this.en = en; sum = ma+cn+en; } @Override public int compareTo(Student s) { int num = new Integer(this.sum).compareTo(new Integer(s.sum)); if(num==0) return this.name.compareTo(s.name); return num; } } class StudentInfoTool{ public static Set<Student> getStudents() throws IOException{ return getStudents(null); } public static Set<Student> getStudents(Comparator<Student> cmp) throws NumberFormatException, IOException{ BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); String line = null; Set<Student> stus = null; if(cmp==null){ stus=new TreeSet<Student>(); }else { stus=new TreeSet<Student>(cmp); } while((line=bufr.readLine())!=null){ if("over".equals(line)) break; String[] info= line.split(","); Student stu = new Student(info[0], Integer.parseInt(info[1]), Integer.parseInt(info[2]), Integer.parseInt(info[3])); stus.add(stu); } bufr.close(); return stus; public static void writeFile(Set<Student> stus) throws IOException{ BufferedWriter bufw = new BufferedWriter(new FileWriter("F:\\Javajichu1\\JavaLianXi\\src\\cn\\itheima\\day05\\studentinfo.txt")); for (Student stu : stus) { bufw.write(stu.toString()+"\t"); bufw.write(stu.getSum()+""); bufw.newLine(); bufw.flush(); } bufw.close(); } } public class StudentInfoTest { public static void main(String[] args) throws NumberFormatException, IOException { Comparator<Student> cmp = Collections.reverseOrder(); Set<Student> students = StudentInfoTool.getStudents(cmp); StudentInfoTool.writeFile(students); } }
相关文章推荐
- Java基础之IO流知识点总结三
- Java基础之IO流知识点总结一
- Java基础之IO流知识点总结二
- Java基础之IO流知识点总结二
- Java基础IO流的简单总结(转)
- Java 面向对象(基础) 知识点总结I
- 黑马程序员 Java基础知识总结-IO流
- Java基础知识点总结七
- Java基础知识点总结三
- java基础重要知识点总结
- Java基础知识点总结四
- 黑马程序员-Java基础总结11——IO流(二)
- 黑马程序员 Java基础知识总结-IO流(应用总结)
- 黑马程序员-Java基础总结10——IO流体系(一)
- Java基础知识点总结一
- JAVA基础容易疏忽的知识点总结
- JAVA基础知识点(自己总结的)
- 黑马程序员:Java基础总结----(小知识点)foreach循环
- 黑马程序员---Java基础总结--IO流
- Java基础知识点总结五