I/O流
1.File类:它既能代表一个文件的名称,又能代表一个文件下一组文件集,我们可以对此集合调用list(),返回一个字符数组。
练习:1.请写出File类的构造方法的定义:
File(File parent,String child) 根据parent的抽象路径名和child路径名创建一个新的File实例。
File(String parent,String child)根据parent路径名和child路径名创建一个新的File实例。
2.请写出File中常见的方法定义:
boolean createNewFile() throws IOExeception;该方法只能用于创建文件,不能用于创建文件夹,且文件路径中包含的文件夹必须存在。
boolean delete(); 删除文件或文件夹,删除文件夹时,文件夹内不能有任何文件。
boolean exist();判断当前文件或文件夹是否存在。
String getName();获取当前文件或文件夹的名称。例如c:\test\1.t,则返回1.t.
String getParent();获取当前路径的父路径。例如c:\test\1.t,则返回c:\test
boolean isDirectory();判断当前File对象是否是目录。
boolean isFile ();判断当前File对象是否是文件。
long length();返回文件在存储时占用的字节数。
String[] list();返回当前文件夹下所有的文件和文件夹的名称。
File[] listFiles();返回当前文件夹下所有的文件对象,包含属性。
boolean mkdir();创建文件夹,文件夹路径中包含的文件夹必须存在,否则返回false;
boolean mkdirs();创建文件夹,文件夹路径中包含的文件夹不存在时存在,会自动创建;
boolean renameTo(File dest):重命名,如果该路径下已存在该文件,那么返回false;
void setReadOnly();设置当前文件或文件夹只读。
3.RandomAccessFile类
定义:JAVA语言最为丰富的文件访问类,支持跳转到任意位置读写
构造方法,和常用读写方法的定义:
new RandomAccessFile(f,"rw");//读写方式打开
new RandomAccessFile(f,"r");//读方式
2.I\O流:java中有两种流,字符流和字节流,字符流继承自Reader和Writer,字节流继承自InputStream和OutputStream。
- 根据处理数据类型的不同分为:字符流和字节流。
- 根据数据流向的不同分为:输入流和输出流。(输入流只能进行读操作,输出流只能进行写操作。)
字符流和字节流的区别?
- 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的文件,如(图片,avi等),而字符流,只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先使用字符流,除此之外都是用字节流。
3.输入字节流InputStream
1.InputStream是所有输入字节流的父类,它是一个抽象类。
2.ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流,他们分别向byte数组,StringBuffer、和本地文件中读取数据。
3.ObjectInputStream和FilterInputStream的子类都是装饰流(装饰器模式的主角)
4.输出字节流OutputStream
1.OutputStream是所有输出字节流的父类,它是一个抽象类。
2.ByteArrayOutputStream和FileOutputStream是是两种基本的输出介质流,他们分别指向byte数组和本地文件中写入数据。
3.ObjectOutputStream和FilterOutputStream(BufferedOutputStream和DataOutputStream)的子类都是装饰流(装饰器模式的主角)
5.字节流输入和输出的对应。
红色部分基本可以理解为被废弃的部分。
6.字符输入流Reader
1.reader是所有输入字符流的父类,它是一个抽象类。
2.CharArrayReader和StringReader是两种基本的介质流,他们分别从char数组和String中读取数据。
3.BufferedReader是一个装饰器,它和其子类负责装饰其它Reader对象。
4.FilterReader是所有自定义装饰流的父类,其子类PushBackReader对Reader对象进行装饰,会增加一个行号
5.InputStreamReader是连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader是一个达到此功能常用的工具类,在其源码中,将FIleInputStream转变为Reader。
7.字符输出流writer
1.Writer是所有输出字符流的父类,它是一个抽象类。
2.CharArrayWriter和StringWriter是两种基本的介质流,他们分别从char数组和String中读取数据。
3.BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
4.OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似。
8.字节流和字符流的转换。
具体对象的体现:InputStreamReader、OutputStreamWritter:它们是字符流体系的成员,本身又具有转换功能,在构造时需传入字节流。
转换流的特点:
a.是字节流和字符流之间的桥梁。
b.可以读取到字节数据经过制定编码转换成字符。
c.可以读取到字符数据经过指定编码转换成字节。
何时使用转换流?
a.当字节和字符之间需要相互转换时。
b.流操作的数据需要编码或解码时。
练习题:
1.在电脑D盘下创建一个HelloWord.txt文件,然后判断一下它是文件还是目录,再创建一个目录IOTest,将HelloWord.txt移动到这个文件夹下,之后遍历这个文件夹下的文件。
1 public static void main(String[] args) throws IOException { 2 //NO1.创建一个文件 3 File file = new File("D:","HelloWord.txt"); 4 boolean isCreate ; 5 try { 6 isCreate = file.createNewFile(); 7 System.out.println(isCreate?"创建文件夹成功!":"创建文件夹失败!"); 8 } catch (IOException e) { 9 System.out.println("创建文件夹失败"); 10 } 11 System.out.println(file.isFile()?"是一个文件!":"是一个目录!"); 12 //NO.2创建一个目录 13 File file2 = new File("D:/IOTest"); 14 file2.mkdir(); 15 //NO.3将文件移动到目录下 16 System.out.println(file.renameTo(file2)?"移动成功!":"移动失败!"); 17 //NO.4遍历IOTest下的文件 18 for(String str :file2.list()){ 19 System.out.println(str); 20 } 21 }
2.递归实现输入任意目录,列出文件。
1 public class FileUtils { 2 public static List<File> getAllFiles(String dir){ 3 List<File> files = new ArrayList<File>(); 4 File file = new File(dir); 5 //文件夹必须存在 并且要是文件夹 继续遍历 6 if(file.exists()&&file.isDirectory()){ 7 longErgodic(file,files);//把遍历得到的东西存放在files里面 8 } 9 return files; 10 } 11 12 private static void longErgodic(File file, List<File> files) { 13 File[] fileArr = file.listFiles(); 14 if(null==fileArr){ 15 return; 16 } 17 for (File file2 : fileArr) { 18 files.add(file2); 19 longErgodic(file2,files); 20 } 21 } 22 23 }
3.递归实现当前工程下所有的JAVA文件。
1 public class FindJavaFile { 2 public static void main(String[] args) { 3 List<File> files = FileUtils.getAllFiles("."); 4 for (File file : files) { 5 if(file.toString().endsWith(".java")){ 6 System.out.println(file.getName()); 7 } 8 } 9 } 10 }
4.从磁盘中读取一个文件到内存中,在打印到控制台。
1 public class Test4 { 2 /** 3 * 从磁盘读取一个文件到内存中,再打印到控制台。 4 * 5 * 程序设计: 6 * 1、把文件读取到FileInputStream 7 * 2、把读取的内容不断加入到StringBuffer 8 * 3、再把StringBuffer打印出来就可以 9 * */ 10 public static void main(String[] args) { 11 File file = new File("E:\\pro.txt"); 12 try { 13 FileInputStream fileInputStream = new FileInputStream(file); 14 int len = 0; 15 byte[] buf = new byte[1024]; 16 StringBuffer sb = new StringBuffer(); 17 while((len=fileInputStream.read(buf))!=-1){ 18 sb.append(new String(buf,0,len)); 19 }; 20 System.out.println(sb.toString()); 21 fileInputStream.close(); 22 } catch (Exception e) { 23 System.out.println(e); 24 } 25 } 26 27 }
5.在程序中写一个HelloWord,输出到磁盘的hello.txt中。
1 public class Test5 { 2 public static void main(String[] args) { 3 File file = new File("E:\\pro.txt"); 4 try { 5 FileOutputStream os = new FileOutputStream(file); 6 os.write("Hello word".getBytes()); 7 os.flush(); 8 os.close(); 9 } catch (Exception e) { 10 } 11 } 12 }
6.拷贝一张图片,从一个目录到另一个目录。
1 public class Test6 { 2 /** 3 * 拷贝一张图片,从一个目录到另一个目录下 4 * 5 * 设计思路: 6 * 1、在目标地址创建一个图片文件 7 * 2、读取源地址文件的字节流 8 * 3、把读取到的字节流写入目标文件 9 * 4、刷新字节流并关闭 10 * */ 11 public static void main(String[] args) { 12 File fileFrom = new File("E:/TEST1/11.jpg"); 13 File fileTo = new File("E:/TEST1/TEST2/11.jpg"); 14 try { 15 if (!fileTo.createNewFile()) { 16 System.out.println("创建文件失败!"); 17 } 18 FileInputStream is = new FileInputStream(fileFrom); 19 FileOutputStream os = new FileOutputStream(fileTo); 20 byte[] buf = new byte[1024]; 21 int len = 0; 22 while((len=is.read(buf))!=-1){ 23 os.write(buf, 0, len); 24 } 25 os.flush(); 26 os.close(); 27 } catch (Exception e) { 28 } 29 30 31 } 32 33 }
7.统计一个文件中A和a出现的次数。
1 public class Test7 { 2 /** 3 * 统计一个文件中A和a出现的次数 4 * 5 * 程序分析: 读取文件用FileInputStream 一次只读一个字节(一个字母就是一个字节,当字节内容A和a相等时,相应的数量加1) 6 * */ 7 public static void main(String[] args) { 8 try { 9 File file = new File("E:/TEST1/TEST2/111.TXT"); 10 FileInputStream fis = new FileInputStream(file); 11 int numa = 0; 12 int numA = 0; 13 int len = 0; 14 while ((len = fis.read()) != -1) { 15 if(new String((char) len + "").equals("a")) 16 numa++; 17 if(new String((char) len + "").equals("A")) 18 numA++; 19 } 20 System.out.println("A的数量"+numA); 21 System.out.println("a的数量"+numa); 22 fis.close(); 23 } catch (Exception e) { 24 // TODO: handle exception 25 } 26 } 27 28 }
8.統計一个文件中出现各个字符的个数(如果需统计中文的个数只能使用FileReader)
1 package com.vvning.io; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.util.HashMap; 6 import java.util.Iterator; 7 import java.util.Map.Entry; 8 9 public class Test8 { 10 /** 11 * 统计一个文件中各个字母出现的次数 12 * 13 * 程序分析: 14 * 1、读取文件用FileInputStream 一次只读一个字节 15 * 2、不能保存相同的主键值,可以使用HashMap 16 * 3、先获得key的value,如果key存在的话value+1 17 * */ 18 public static void main(String[] args) { 19 File file = new File("E:/TEST1/TEST2/111.txt"); 20 try { 21 FileInputStream fis = new FileInputStream(file); 22 HashMap<String, Integer> map = new HashMap<String, Integer>(); 23 int len = 0; 24 int count = 0; 25 while ((len = fis.read()) != -1) { 26 char c = (char) len; 27 try { 28 // 通过每次的key值获取它的value值, 29 // 但是在它的key值没有时或报空指针错误,所以要try catch处理 30 // 当她有key值,就可以获取到相应的value值 31 count = map.get(c + ""); 32 } catch (Exception e) {// 什么都不用输出 33 } 34 map.put(c + "", count + 1); 35 } 36 fis.close(); 37 // 读完后把结果打印出来 38 // 迭代器的使用 39 Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator(); 40 while (iterator.hasNext()) { 41 Entry<String, Integer> entry = iterator.next(); 42 System.out.print(entry.getKey() + "(" + entry.getValue() + ") \t"); 43 } 44 } catch (Exception e) { 45 System.out.println(e); 46 } 47 } 48 49 }
9.使用随机文件流类RandomAccessFile将一个文本倒置读出。
1 public class Test9 { 2 /** 3 * 使用RandomAccessFile将一个文本文件倒置读出。 1、RandomAccessFile的seek()方法能将光标移动到指定位置。 4 * 2、但是有一点值得注意(汉字占两个字节,字母和数字占一个字节) 5 * */ 6 public static void main(String[] args) { 7 File file = new File("E:/TEST1/TEST2/111.txt"); 8 try { 9 RandomAccessFile raf = new RandomAccessFile(file, "r"); 10 long length = raf.length(); 11 StringBuffer sb = new StringBuffer(); 12 while (length > 0) { 13 length--; 14 raf.seek(length); 15 int c = raf.readByte(); 16 // asc在0~255之间判断为英文字符, 17 if (c >= 0 && c <= 255) { 18 sb.append((char) c); 19 } else { 20 length--; 21 byte[] bf = new byte[2]; 22 raf.readFully(bf); 23 sb.append(new String(bf)); 24 } 25 } 26 System.out.println(sb.toString()); 27 } catch (Exception e) { 28 e.printStackTrace(); 29 } 30 } 31 32 }