Java的IO流总结
一:主要内容
二:File类
java.io.File类:文件和目录路径名的抽象表示形式,与平台无关。File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。File对象可以作为参数传递给流的构造函数。
File类的常见构造方法:
public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储(可以通过system.getproperty("user.dir")查看)。
public File(String parent,String child)
以parent为父路径,child为子路径创建File对象
1 package IO; 2 3 import org.junit.Test; 4 5 import java.io.File; 6 import java.io.IOException; 7 import java.util.Date; 8 /* 9 * java.io.File类 10 * 1.凡是与输入、输出相关的类、接口等都定义在java.io包下 11 * 2.File是一个类,可以有构造器创建其对象。此对象对应着一个文件(.txt .avi .doc .ppt .mp3 .jpg)或文件目录 12 * 3.File类对象是与平台无关的。 13 * 4.File中的方法,仅涉及到如何创建、删除、重命名等等。只要涉及文件内容的,File是无能为力的,必须由io流来完成。 14 * 5.File类的对象常作为io流的具体类的构造器的形参。 15 */ 16 public class TestFile { 17 /* 18 * 路径: 19 * 绝对路径:包括盘符在内的完整的文件路径 20 * 相对路径:在当前文件目录下的文件的路径 21 * 22 * getName() 23 getPath() 24 getAbsoluteFile() 25 getAbsolutePath() 26 getParent() 27 renameTo(File newName) 28 29 */ 30 @Test 31 public void test1(){ 32 File file1 = new File("D:/config.txt"); 33 File file2 = new File("D:/co.txt"); 34 System.out.println(file1.getName()); 35 System.out.println(file1.getAbsoluteFile()); 36 System.out.println(file1.getAbsolutePath()); 37 System.out.println(file1.getPath()); 38 System.out.println(file1.getParent()); 39 System.out.println(); 40 System.out.println(file2.getName()); 41 System.out.println(file2.getAbsoluteFile()); 42 System.out.println(file2.getAbsolutePath()); 43 System.out.println(file2.getPath()); 44 System.out.println(file2.getParent()); 45 boolean b = file1.renameTo(file2);//要提供完整路径 46 System.out.println(b); 47 } 48 /** 49 * 文件检测 50 * exists() 51 * canWrite() 52 * canRead() 53 * isFile() 54 * isDirectory() 55 */ 56 @Test 57 public void test2(){ 58 System.out.println(System.getProperty("user.dir"));//通过改行代码确定当前路径的相对位置。 59 File file = new File("src/IO/config.txt");//注意File的相对路径是相对于当前的user.dir来说的, 60 File dir = new File("src/IO/test"); 61 System.out.println(file.exists()); 62 System.out.println(file.canExecute()); 63 System.out.println(file.canRead()); 64 System.out.println(file.canWrite()); 65 System.out.println(file.isDirectory()); 66 System.out.println(new Date(file.lastModified())); 67 System.out.println(file.length()); 68 System.out.println(); 69 System.out.println(dir.exists()); 70 System.out.println(dir.canExecute()); 71 System.out.println(dir.canRead()); 72 System.out.println(dir.canWrite()); 73 System.out.println(dir.isDirectory()); 74 System.out.println(new Date(dir.lastModified())); 75 System.out.println(dir.length()); 76 } 77 /* 78 * createNewFile() 79 delete() 80 mkDir():创建一个文件目录。只有在上层文件目录存在的情况下,才能返回true 81 mkDirs():创建一个文件目录。若上层文件目录不存在,一并创建 82 list() 83 listFiles() 84 */ 85 @Test 86 public void test3() throws IOException { 87 File file1 = new File("src/IO/a.txt"); 88 System.out.println(file1.createNewFile());//创建新的文件 89 File file2 = new File("src/IO/a"); 90 file2.mkdir();//创建相对目录,如果成功返回true否则返回false,注意要保证上级目录存在 91 File file3 = new File("D:/TTT/TTT"); 92 file3.mkdirs();//创建目录,如果上级目录不存在则一并创建。 93 File file4 = new File("src/IO"); 94 File[] files = file4.listFiles();//返回目录下的文件列表 95 for (int i = 0; i < files.length; i++) { 96 System.out.println(files[i]); 97 } 98 } 99 }
三:Java IO流
字符流以字符为单位,字节流以byte为单位
因此BufferedReader和BufferedWriter可以包装在FileReader和FileWriter上加快文件读写速度。
3.1 输入输出流的基类InputStream和Reader,OutputStram和Writer
1 FileReader fr = null; 2 try{ 3 fr = new FileReader("c:\\test.txt"); 4 char[] buf = new char[1024]; 5 int len= 0; 6 while((len=fr.read(buf))!=-1){ 7 System.out.println(new String(buf ,0,len));} 8 }catch (IOException e){ 9 System.out.println("read-Exception :"+e.toString());} 10 finally{ 11 if(fr!=null){ 12 try{ 13 fr.close(); 14 }catch (IOException e){ 15 System.out.println("close-Exception :"+e.toString()); 16 } } }
FileWriter fw = null; try{ fw = new FileWriter("Test.txt"); fw.write("text"); } catch (IOException e){ System.out.println(e.toString()); } finally{ If(fw!=null) try{ fw.close(); } catch (IOException e){ System.out.println(e.toString());} }
3.2 FileInputStream和FileOutputStream
package IO; import org.junit.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class TestInputOutput { @Test public void test1() {//读取文件,并把结果输出到控制台上面 FileInputStream fis = null; try { fis = new FileInputStream(new File("src/IO/config.txt")); byte[] b = new byte[5]; int len; while ((len = fis.read(b)) != -1) { System.out.print(new String(b, 0, len)); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void test2() { // 1.创建一个File对象,表明要写入的文件位置。 // 输出的物理文件可以不存在,当执行过程中,若不存在,会自动的创建。若存在,会将原有的文件覆盖 FileOutputStream fos = null; try { fos = new FileOutputStream(new File("src/IO/b.txt")); fos.write("你好,我在发消息".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Test public void test3(){// 从硬盘读取一个文件,并写入到另一个位置。(相当于文件的复制) FileInputStream fis = null; FileOutputStream fos = null; long start = System.currentTimeMillis(); try { fis = new FileInputStream(new File("a.jpg")); fos = new FileOutputStream(new File("a1.jpg")); byte[] b = new byte[1000];//会发现数组的大小影响文件写出的效率,文件太小多次写入浪费时间,太大则浪费空间。 int len; while ((len = fis.read(b))!=-1){ fos.write(b,0,len);//注意使用len而不是b.length的原因是防止在后一次循环若数组为读满导致多余的数据被写入的错误 } } catch (IOException e) { e.printStackTrace(); } finally { if(fos!=null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(fis!=null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } long end = System.currentTimeMillis(); System.out.println("时间共花了"+(end-start)); } }
3.3FileReader和FileWriter
package IO; import org.junit.Test; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /** * FileReader和FileWriter用来对文本文件进行读写(注意一般指txt文件,doc文件不是文本文件),其速度效率要快于字节流读取 * 文本文件,对于非文本文件(视频文件、音频文件、图片),只能使用字节流! */ public class TestFileReaderWriter { @Test public void test() throws IOException { FileReader fr = null; FileWriter fw = null; try { fr = new FileReader(new File("src/IO/a.txt")); fw =new FileWriter(new File("src/IO/bb.txt")); char[] a = new char[5]; int len; while((len = fr.read(a))!=-1){ System.out.println(len); System.out.println(new String(a,0,len)); fw.write(a,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if(fw!=null){ fw.close(); } if(fr!=null){ fr.close(); } } } }
3.4缓冲流
1 package IO; 2 3 import org.junit.Test; 4 5 import java.io.*; 6 7 /* 8 * 抽象基类 节点流(文件流) 缓冲流(处理流的一种,可以提升文件操作的效率) 9 * InputStream FileInputStream BufferedInputStream 10 * OutputStream FileOutputStream BufferedOutputStream (flush()) 11 * Reader FileReader BufferedReader (readLine()) 12 * Writer FileWriter BufferedWriter (flush()) 13 */ 14 public class TestBuffered { 15 @Test//使用缓冲流加速字节流读取非文本文件的速度 16 public void test() { 17 BufferedInputStream br = null; 18 BufferedOutputStream bw = null; 19 FileInputStream fis = null; 20 FileOutputStream fos = null; 21 long start = System.currentTimeMillis(); 22 try { 23 fis = new FileInputStream(new File("a.jpg")); 24 fos = new FileOutputStream(new File("a3.jpg")); 25 br = new BufferedInputStream(fis); 26 bw = new BufferedOutputStream(fos); 27 byte[] b = new byte[1024];//会发现数组的大小影响文件写出的效率,文件太小多次写入浪费时间,太大则浪费空间。 28 int len; 29 while ((len = br.read(b)) != -1) { 30 bw.write(b, 0, len);//注意使用len而不是b.length的原因是防止在后一次循环若数组为读满导致多余的数据被写入的错误 31 } 32 bw.close(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } finally { 36 if (fos != null) { 37 try { 38 fos.close(); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } 42 } 43 if (fis != null) { 44 try { 45 fis.close(); 46 } catch (IOException e) { 47 e.printStackTrace(); 48 } 49 } 50 if (br != null) { 51 try { 52 br.close(); 53 } catch (IOException e) { 54 e.printStackTrace(); 55 } 56 } 57 58 } 59 long end = System.currentTimeMillis(); 60 System.out.println("时间共花了" + (end - start)); 61 } 62 63 @Test//使用缓冲流加速字节流读取非文本文件的速度 64 public void test2() { 65 BufferedReader br = null; 66 BufferedWriter bw = null; 67 FileReader fr = null; 68 FileWriter fw = null; 69 try { 70 fr = new FileReader(new File("src/IO/a.txt")); 71 fw =new FileWriter(new File("src/IO/bb.txt")); 72 br = new BufferedReader(fr); 73 bw = new BufferedWriter(fw); 74 char[] a = new char[5]; 75 int len; 76 while((len = br.read(a))!=-1){ 77 System.out.println(len); 78 System.out.println(new String(a,0,len)); 79 bw.write(a); 80 } 81 82 } catch (IOException e) { 83 e.printStackTrace(); 84 } finally { 85 if(fw!=null){ 86 try { 87 fw.close(); 88 } catch (IOException e) { 89 e.printStackTrace(); 90 } 91 } 92 if(fr!=null){ 93 try { 94 fr.close(); 95 } catch (IOException e) { 96 e.printStackTrace(); 97 } 98 } 99 if(bw!=null){ 100 try { 101 fw.close(); 102 } catch (IOException e) { 103 e.printStackTrace(); 104 } 105 } 106 if(fr!=null){ 107 try { 108 fr.close(); 109 } catch (IOException e) { 110 e.printStackTrace(); 111 } 112 } 113 }} 114 }
3.5转换流
@Test public void test() throws IOException {//转换流 InputStreamReader isr = new InputStreamReader(new FileInputStream(new File("src/IO/a.txt")));//解码,把字节数组变成字符流 OutputStreamWriter osr = new OutputStreamWriter(new FileOutputStream(new File("src/IO/bbb.txt")),"utf-8");//编码,把字符流变成字节数组 BufferedReader br = new BufferedReader(isr); BufferedWriter bw = new BufferedWriter(osr); int len; char[] c = new char[10]; while((len = br.read(c))!=-1){ bw.write(c,0,len); bw.flush(); } bw.close(); br.close(); osr.close(); isr.close(); }
3.6 标准输入输出流
@Test public void test1() throws IOException {//标准输入输出流 InputStream is = System.in; InputStreamReader inputStreamReader = new InputStreamReader(is); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); while (true){ String str = bufferedReader.readLine(); System.out.println(str); if(str.equals("bye")){ break; } } bufferedReader.close(); inputStreamReader.close(); is.close(); }
3.7 打印流
@Test public void test3() throws IOException { FileOutputStream fos = new FileOutputStream(new File("b.txt")); PrintStream printStream = new PrintStream(fos); if(printStream != null){ System.setOut(printStream);//改变流的方向 } System.out.println("这句话将输入到b.txt文件而不是控制台"); printStream.close(); InputStream inputStream = new FileInputStream("b.txt"); System.setIn(inputStream);//输入被调整为从文件里面输入 Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()){ System.out.println(scanner.nextLine()); } inputStream.close(); }
3.8数据流
@Test public void test4() throws Exception {//数据流:用来处理基本数据类型、String、字节数组的数据:DataInputStream DataOutputStream DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("data.txt")); dataOutputStream.writeUTF("我爱你,而你不知道"); dataOutputStream.writeBoolean(true); dataOutputStream.writeInt(12); dataOutputStream.close();//会乱码,但是再次读的时候会恢复 DataInputStream dataInputStream = new DataInputStream(new FileInputStream(new File("data.txt"))); // byte[] b =new byte[10]; // int len; // while((len = dataInputStream.read(b))!=-1){ // System.out.println(new String(b,0,len)); // } System.out.println(dataInputStream.readUTF()); System.out.println(dataInputStream.readBoolean()); System.out.println(dataInputStream.readInt()); dataInputStream.close(); }
3.9对象流
1 package IO; 2 3 import org.junit.Test; 4 5 import java.io.*; 6 7 public class TestObjectInputOutputStream { 8 @Test 9 public void test() throws IOException {// 对象的序列化过程:将内存中的对象通过ObjectOutputStream转换为二进制流,存储在硬盘文件中 10 Person person = new Person("花花", 12, new Pet("哈哈")); 11 Person person1 = new Person("瓜瓜", 22, new Pet("大大")); 12 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt")); 13 oos.writeObject(person); 14 oos.flush(); 15 oos.writeObject(person1); 16 oos.flush(); 17 oos.close(); 18 } 19 @Test 20 public void test1() throws IOException, ClassNotFoundException {// // 对象的反序列化过程:将硬盘中的文件通过ObjectInputStream转换为相应的对象 21 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt")); 22 Person person = (Person) ois.readObject(); 23 Person person1 = (Person) ois.readObject(); 24 System.out.println(person); 25 System.out.println(person1); 26 } 27 } 28 /* 29 * 要实现序列化的类: 1.要求此类是可序列化的:实现Serializable接口 30 * 2.要求类的属性同样的要实现Serializable接口 31 * 3.提供一个版本号:private static final long serialVersionUID 32 * 4.使用static或transient修饰的属性,不可实现序列化 33 */ 34 class Person implements Serializable{ 35 private static final long serialVersionUID = 23456789L; 36 String name; 37 Integer age; 38 Pet pet; 39 public Person(String name, Integer age,Pet pet) { 40 this.name = name; 41 this.age = age; 42 this.pet = pet; 43 } 44 45 @Override 46 public String toString() { 47 return "Person{" + 48 "name='" + name + '\'' + 49 ", age=" + age + 50 ", pet=" + pet + 51 '}'; 52 } 53 } 54 class Pet implements Serializable{ 55 String name; 56 57 public Pet(String name) { 58 this.name = name; 59 } 60 61 @Override 62 public String toString() { 63 return "Pet{" + 64 "name='" + name + '\'' + 65 '}'; 66 } 67 }
transient是 Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程
3.10 randomAccessFile类
package IO; import org.junit.Test; import java.io.File; import java.io.RandomAccessFile; public class TestRandomAccessFile { @Test//RandomAccessFile进行文件的读写 public void test1() throws Exception { RandomAccessFile randomAccessFile = new RandomAccessFile(new File("src/IO/a.txt"),"r"); RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw"); int len; byte[] b = new byte[10]; while ((len = randomAccessFile.read(b))!=-1){ randomAccessFile1.write(b,0,len); } randomAccessFile1.close(); randomAccessFile.close(); } @Test//实现的实际上是覆盖的效果 public void test2() throws Exception { RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw"); randomAccessFile1.seek(4); randomAccessFile1.write("xy".getBytes());//在第四个字符出写入xy,实则是覆盖,注意汉字一个字占两个字符,如26个字符覆盖后abcdxyghijklmnopqrstuvwxyz randomAccessFile1.close(); } @Test//处理覆盖 public void test3() throws Exception { RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw"); randomAccessFile1.seek(4); String str = randomAccessFile1.readLine();//弊端是只能处理一行 randomAccessFile1.seek(4);//指针已经移动,需要调整 randomAccessFile1.write("xy".getBytes()); randomAccessFile1.write(str.getBytes());//拿出来在追加上 randomAccessFile1.close();//abcdxyefghijklmnopqrstuvwxyz } @Test//更通用 public void test4() throws Exception { RandomAccessFile randomAccessFile1 = new RandomAccessFile(new File("src/IO/aa.txt"),"rw"); randomAccessFile1.seek(4); byte[] b = new byte[10]; int len; StringBuffer sb = new StringBuffer(); while((len = randomAccessFile1.read(b)) != -1){ sb.append(new String(b,0,len)); } randomAccessFile1.seek(4);//指针已经移动,需要调整 randomAccessFile1.write("xy".getBytes()); randomAccessFile1.write(sb.toString().getBytes());//拿出来在追加上 randomAccessFile1.close();//abcdxyefghijklmnopqrstuvwxyz } }
四:其他小知识
首先为什么要设置缓冲?
如果不设置缓冲的话,CPU取一个存一个。设置缓冲区的话:就好比是把基础流用DMA方式包装起来如下:
CPU通常会使用 DMA 方式去执行 I\O流 操作。CPU 将这个工作交给DMA控制器来做,自己腾出时间做其他的事,当DMA完成工作时,DMA会主动告诉CPU“操作完成”。这时,CPU接管后续工作。在此,CPU 是被动的。DMA是专门 做 I\O 与 内存 数据交换的,不仅自身效率高,也节约了CPU时间,CPU在DMA开始和结束时做了一些设置罢了。 缓冲区就是内存里的一块区域,把数据先存内存里,然后一次性写入,类似数据库的批量操作,显然效率比较高。还节省CPU的使用。
总结:使用缓冲处理流包装就是一堆一堆的干活,还能不用CPU多次处理数据转换,只是设置一下数据转换成功后的文件。
不使用缓冲处理流包装就是CPU傻傻的一个字节一个字节循环来干活存储写入文件中,相比可见效率明显变慢。
JAVA中的flush()方法
序列化uid的作用