Java操作文件那点事

时间:2023-03-09 22:01:33
Java操作文件那点事

刚开始学Java时候,一直搞不懂Java里面的io关系,在网上找了很多大多都是给个结构图草草描述也看的不是很懂。而且没有结合到java7 的最新技术,所以自己结合API来整理一下,有错的话请指正,也希望大家提出宝贵意见。

首先看个图:(如果你也是初学者,我相信你看了真个人都不好了,想想java设计者真是煞费苦心啊!)

Java操作文件那点事

Java I/O系统的类实在是太多了,这里我们只学习一些基本的和常用的,相信能够掌握这些就可以解决我们以后的普通应用了

什么是数据流(字节流)

数据流是指所有的数据通信通道;

有两类流,InputStream and OutputStream。

Java中每一种流的基本功能依赖于它们InputStream 用于read,OutputStream 用于write, 读和写都是相对与内存说的,读就是从其他地方把数据拿进内存,写就是把数据从内存推出去
这两个都是抽象类,不能直接使用

InputStream 的方法有:                                                                                                                             

1.read() :从流中读入数据 有3中方式:
2.int read(): 一次读一个字节
3.int read(byte[]) :读多个字节到数组中
4.int read(byte[],int off,int len) :指定从数组的哪里开始,读多长
5.skip() :跳过流中若干字节
6.available() :返回流中可用字节数,但基于网络时无效,返回0
7.markSupported(): 判断是否支持标记与复位操作
8.mark() :在流中标记一个位置,要与markSupported()连用
9.reset() :返回标记过的位置
10.close() :关闭流

OutputStream 的方法:                                                                                                                               

1.write(int) :写一个字节到流中
2.write(byte[]): 将数组中的内容写到流中
3.write(byte[],int off,int len): 将数组中从off指定的位置开始len长度的数据写到流中
4.close() :关闭流
5.flush() :将缓冲区中的数据强制输出

File 类                                                                                                                                                      

File 可以表示文件也可以表示目录,File 类控制所有硬盘操作
构造器:
1.File(File parent,String child): 用父类和文件名构造
2.File(String pathname) :用绝对路径构造
3.File(String parent,String child): 用父目录和文件名构造
4.File(URI uri) :用远程文件构造
常用方法:

-----------------------------------------------------------------------------------------------------------------------------------------------------------

1.boolean createNewFile();

2.boolean exists();

例子:
//建立 test.txt 文件对象,判断是否存在,不存在就创建

  1. import java.io.*;
  2. public class CreateNewFile{
  3. public static void main(String args[]){
  4. File f=new File("test.txt");
  5. try{
  6. if(!f.exists())
  7. f.createNewFile();
  8. else
  9. System.out.println("exists");
  10. }catch(Exception e){
  11. e.printStackTrace();
  12. }
  13. }
  14. }

---------------------------------------------------------------------------------------------------------------------------------------------------------

3.boolean mkdir()/mkdirs()

4.boolean renameTo(File destination)
例子://看一下这 mkdir()/mkdirs() 的区别和 renameTo 的用法

  1. import java.io.*;
  2. public class CreateDir{
  3. public static void main(String args[]){
  4. File f=new File("test.txt");
  5. File f1=new File("Dir");
  6. File f2=new File("Top/Bottom");
  7. File f3=new File("newTest.txt");
  8. try{
  9. f.renameTo(f3);
  10. f1.mkdir();
  11. f2.mkdirs();
  12. }catch(Exception e){
  13. e.printStackTrace();
  14. }
  15. }
  16. }

--------------------------------------------------------------------------------------------------------------------------------------------------------------

String getPath()/getAbsolutePath()

String getParent()/getName()

例子://硬盘上并没有parent 目录和 test.txt 文件,但我们仍然可以操作,因为我们创建了他们的对象,是对对象进行操

  1. import java.io.*;
  2. public class Test{
  3. public static void main(String args[]){
  4. File f=new File("parent/test.txt");
  5. File f1=new File("newTest.txt");
  6. try{
  7. System.out.println(f.getParent());
  8. System.out.println(f.getName());
  9. System.out.println(f1.getPath());
  10. System.out.println(f1.getAbsolutePath());
  11. }catch(Exception e){
  12. e.printStackTrace();
  13. }
  14. }
  15. }

----------------------------------------------------------------------------------------------------------------------------------------------------------

String list[] //显示目录下所有文件
long lastModified() //返回 1970.1.1 到最后修改时间的秒数
boolean isDirectory()
例子://列出目录下的所有文件和目录,最后修改时间,是目录的后面标出<DIR>,是文件的后面标出文件长度

  1. import java.io.*;
  2. import java.util.*;
  3. public class Dir{
  4. public static void main(String args[]){
  5. File f=new File("Dir");
  6. String[] listAll=null;
  7. File temp=null;
  8. try{
  9. listAll=f.list();
  10. for(int i=0;i<listAll.length;i++){
  11. temp=new File(listAll<i>);
  12. System.out.print(listAll<i>+"\t");
  13. if(temp.isDirectory())
  14. System.out.print("\t<DIR>\t");
  15. else
  16. System.out.print(temp.length()+"\t");
  17. System.out.println(new Date(temp.lastModified()))
  18. }
  19. }catch(Exception e){
  20. e.printStackTrace();
  21. }
  22. }
  23. }

文件流的建立                                                                                                                                                                               
File f=new File("temp.txt");
FileInputStream in=new FileInputStream(f);
FileOutputStream out=new FileOutputStream(f);
例子:文件拷贝

  1. import java.io.*;
  2. public class Copy{
  3. public static void main(String args[]){
  4. FileInputStream fis=null;
  5. FileOutputStream fos=null;
  6. try{
  7. fis=new FileInputStream("c2.gif");
  8. fos=new FileOutputStream("c2_copy.gif");
  9. int c;
  10. while((c=fis.read()) != -1)
  11. fos.write(c);
  12. }catch(Exception e){
  13. e.printStackTrace();
  14. }finally{
  15. if(fis != null) try{ fis.close(); }catch(Exception e){ e.printStackTrace(); }
  16. if(fos!= null) try{ fos.close(); }catch(Exception e){ e.printStackTrace(); }
  17. }
  18. }
  19. }
  20. <span style="background-color: rgb(0, 102, 0);"><span style="color:#FFFFFF;"><strong>
  21. </strong></span></span>

缓冲区流                                                                                                                                                                                             
BufferedInputStream
BufferedOutputStream
他们是在普通文件流上加了缓冲的功能,所以构造他们时要先构造普通流
例子:文件拷贝的缓冲改进

  1. import java.io.*;
  2. public class Copy{
  3. public static void main(String args[]){
  4. BufferedInputStream bis=null;
  5. BufferedOutputStream bos=null;
  6. byte buf[]=new byte[100];
  7. try{
  8. bis=new BufferedInputStream(new FileInputStream("persia.mp3"));
  9. bos=new BufferedOutputStream(new FileOutputStream("persia_copy.mp3"));
  10. int len=0;
  11. while( true ){
  12. len=bis.read(buf);
  13. if(len<=0) break;
  14. bos.write(buf,0,len);
  15. }
  16. bos.flush();//缓冲区只有满时才会将数据输出到输出流,用flush()将未满的缓冲区中数据强制输出
  17. }catch(Exception e){
  18. e.printStackTrace();
  19. }finally{
  20. if(bis != null) try{ bis.close(); }catch(Exception e){ e.printStackTrace(); }
  21. if(bos!= null) try{ bos.close(); }catch(Exception e){ e.printStackTrace(); }
  22. }
  23. }
  24. }

原始数据流

DataInputStream
DataOutputStream
他们是在普通流上加了读写原始型数据的功能,所以构造他们时要先构造普通流
方法:
readBoolean()/writeBoolean()
readByte()/writeByte()
readChar()/writeByte()
......
例子://这个流比较简单,要注意的就是读时的顺序要和写时的一样

  1. import java.io.*;
  2. public class DataOut{
  3. public static void main(String args[]){
  4. DataOutputStream dos=null;
  5. try{
  6. dos=new DataOutputStream(new FileOutputStream("dataout.txt"));
  7. dos.writeInt(1);
  8. dos.writeBoolean(true);
  9. dos.writeLong(100L);
  10. dos.writeChar('a');
  11. }catch(Exception e){
  12. e.printStackTrace();
  13. }finally{
  14. if(dos!=null)
  15. try{
  16. dos.close();
  17. }catch(Exception e){
  18. }
  19. }
  20. }
  21. }
  1. import java.io.*;
  2. public class DataIn{
  3. public static void main(String args[]){
  4. DataInputStream dis=null;
  5. try{
  6. dis=new DataInputStream(new FileInputStream("dataout.txt"));
  7. System.out.println(dis.readInt());
  8. System.out.println(dis.readBoolean());
  9. System.out.println(dis.readLong());
  10. System.out.println(dis.readChar());
  11. }catch(Exception e){
  12. e.printStackTrace();
  13. }finally{
  14. if(dis!=null)
  15. try{
  16. dis.close();
  17. }catch(Exception e){
  18. }
  19. }
  20. }
  21. }

对象流                                                                                                                                                                                             

串行化:对象通过写出描述自己状态的数值来记述自己的过程叫串行话
对象流:能够输入输出对象的流
将串行化的对象通过对象流写入文件或传送到其他地方
对象流是在普通流上加了传输对象的功能,所以构造对象流时要先构造普通文件流
注意:只有实现了Serializable接口的类才能被串行化
例子:

  1. import java.io.*;
  2. class Student implements Serializable{
  3. private String name;
  4. private int age;
  5. public Student(String name,int age){
  6. this.name=name;
  7. this.age=age;
  8. }
  9. public void greeting(){
  10. System.out.println("hello ,my name is "+name);
  11. }
  12. public String toString(){
  13. return "Student["+name+","+age+"]";
  14. }
  15. }
  1. public class ObjectOutTest{
  2. public static void main(String args[]){
  3. ObjectOutputStream oos=null;
  4. try{
  5. oos=new ObjectOutputStream(new FileOutputStream("student.txt"));
  6. Student s1=new Student("Jerry",24);
  7. Student s2=new Student("Andy",33);
  8. oos.writeObject(s1);
  9. oos.writeObject(s2);
  10. }catch(Exception e){
  11. e.printStackTrace();
  12. }finally{
  13. if(oos!=null)
  14. try{
  15. oos.close();
  16. }catch(Exception e){
  17. e.printStackTrace();
  18. }
  19. }
  20. }
  21. }
  1. import java.io.*;
  2. public class ObjectInTest{
  3. public static void main(String args[]){
  4. ObjectInputStream ois=null;
  5. Student s=null;
  6. try{
  7. ois=new ObjectInputStream(
  8. new FileInputStream("student.txt"));
  9. System.out.println("--------------------");
  10. s=(Student)ois.readObject();
  11. System.out.println(s);
  12. s.greeting();
  13. System.out.println("--------------------");
  14. s=(Student)ois.readObject();
  15. System.out.println(s);
  16. s.greeting();
  17. }catch(Exception e){
  18. e.printStackTrace();
  19. }finally{
  20. if(ois!=null)
  21. try{
  22. ois.close();
  23. }catch(Exception e){
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. }

字符流

InputStreamReader/OutputStreamWriter                                                                                                                                  
上面的几种流的单位是 byte,所以叫做字节流,写入文件的都是二进制字节,我们无法直接看,下面要学习的是字节流
Java采用 Unicode 字符集,每个字符和汉字都采用2个字节进行编码,ASCII 码是 Unicode 编码的自集
InputStreamReader 是 字节流 到 字符桥的桥梁 ( byte->char 读取字节然后用特定字符集编码成字符)
OutputStreamWriter是 字符流 到 字节流的桥梁 ( char->byte )
他们是在字节流的基础上加了桥梁作用,所以构造他们时要先构造普通文件流
我们常用的是:
BufferedReader 方法:readLine()
PrintWriter 方法:println()

例子:

  1. import java.io.*;
  2. public class PrintWriterTest{
  3. public static void main(String args[]){
  4. PrintWriter pw=null;
  5. try{
  6. pw=new PrintWriter(new OutputStreamWriter(new FileOutputStream("bufferedwriter.txt")));
  7. pw.println("hello world");
  8. }catch(Exception e){
  9. e.printStackTrace();
  10. }finally{
  11. if(pw!=null)
  12. try{
  13. pw.close();
  14. }catch(Exception e){
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  19. }
  1. import java.io.*;
  2. public class BufferedReaderTest{
  3. public static void main(String args[]){
  4. BufferedReader br=null;
  5. try{
  6. br=new BufferedReader(new InputStreamReader(new FileInputStream("bufferedwriter.txt")));
  7. System.out.println(br.readLine());
  8. }catch(Exception e){
  9. e.printStackTrace();
  10. }finally{
  11. if(br!=null)
  12. try{
  13. br.close();
  14. }catch(Exception e){
  15. e.printStackTrace();
  16. }
  17. }
  18. }
  19. }

随机存取文件

RandomAccessFile                                                                                                                                                       
可同时完成读写操作
支持随机文件操作的方法:
readXXX()/writeXXX()
seek() 将指针调到所需位置
getFilePointer() 返回指针当前位置
length() 返回文件长度
例子:把若干个32位的整数写到一个名为 “temp.txt”的文件中,然后利用seek方法,以相反的顺序再读取这些数据

  1. import java.io.*;
  2. public class RandomFile{
  3. public static void main(String args[]){
  4. RandomAccessFile raf=null;
  5. int data[]={12,31,56,23,27,1,43,65,4,99};
  6. try{
  7. raf=new RandomAccessFile("temp.txt","rw");
  8. for(int i=0;i<data.length;i++)
  9. raf.writeInt(data<i>);
  10. for(int i=data.length-1;i>=0;i--){
  11. raf.seek(i*4);
  12. System.out.println(raf.readInt());
  13. }
  14. }catch(Exception e){
  15. e.getMessage();
  16. }finally{
  17. if(raf!=null)
  18. try{
  19. raf.close();
  20. }catch(Exception e){
  21. e.getMessage();
  22. }
  23. }
  24. }
  25. }

小结                                                                                                                                                                                                  

这部分的难点就是类比较复杂,尤其是每个类的构造方式,我认为记住下面这个图比记类的继承关系更好些

字节流:

InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
OutputStream 同上图
BufferedInputStream DataInputStream ObjectInputStream 只是在 FileInputStream 上增添了相应的功能,构造时先构造FileInputStream

字符流:
Reader
|-- InputStreamReader (byte->char 桥梁)
|-- BufferedReader (常用)

Writer
|-- OutputStreamWriter (char->byte 桥梁)
|-- BufferedWriter
|-- PrintWriter (常用)

随机存取文件 RandomAccessFile

 

欢迎各位同学关注拓薪教育,与众多Java开发人员交流技术心得!

Java操作文件那点事