java文件操作(超详细!)

  1. 文件IO流

文件流框架

9.0 File类

File类,即文件类。

我们如果需要获取文件的信息,或者在磁盘上创建新的文件,就需要用到File类。

File类的对象可以获取文件信息,不涉及文件的读写。文件读写需要用到下面的各种输入输出流。

  • File类3个构造方法:

    1. File (String filename) (以此创建文件,文件与当前应用程序在同一目录)
    2. File(String directoryPath,String filename)
    3. File(File dir,String filename)

    注:filename是文件名字,directoryPath是文件的路径,dir是目录。

  • File类常用方法:

    1. public String getName()

      调用getName(),获取文件名字

      例子

      File f = new File("test.txt");
      System.out.println(f.getName()); //=>test.txt
      
    2. public boolean canRead()

      调用canRead(),判断文件是否可读,可读返回true,否则false

      例子:

      File f = new File("test.txt");
      System.out.println(f.canRead()); //=>true
      
    3. public boolean canWrite()

      调用canWrite(),判断文件是否可写,可写返回true,否则false

      例子:

      File f = new File("test.txt");
      System.out.println(f.canWrite()); //=>true
      
    4. public boolean exists()

      调用exists(),判断文件是否存在,存在返回true,否则false

      例子:

      File f = new File("test.txt");
      System.out.println(f.exists()); //=>true
      
    5. public long length()

      调用length(),获取文件长度(单位是字节)

      例子:

      File f = new File("test.txt");
      System.out.println(f.length()); //=>0
      
    6. public String getAbsolutePath()

      调用getAbsolutePath(),获取文件的绝对路径

      例子:

      File f = new File("test.txt");
      System.out.println(f.length()); //=>/Users/console/IdeaProjects/firstTime/test.txt
      
    7. public String getParent()

      调用getParent(),获取文件的父目录

      例子:

      File f = new File("test.txt");
      System.out.println(f.getParent()); //=>null
      
    8. public boolean isFile()

      调用isFile(),判断文件是否是一个普通文件,而不是目录

      例子:

      File f = new File("test.txt");
      System.out.println(f.isFile());//=>true
      
    9. public boolean isDirectory()

      调用isDirectory(),判断文件是否是一个目录。

      例子:

      File f = new File("test.txt");
      System.out.println(f.isDirectory());//=>false
      
    10. public boolean isHidden()

      调用isHidden(),判断文件是否隐藏

      例子:

      File f = new File("test.txt");
      System.out.println(f.isHidden());//=>false
      
    11. public long lastModified()

      调用lastModified(),获取文件最后修改时间(时间戳)

      例子:

      File f = new File("test.txt");
      System.out.println(f.lastModified());//=>1666171192322
      
    12. public boolean createNewFile()

      调用createNewFile(),创建一个新文件,成功返回true,否则false

      例子:

      File f = new File("test.txt");
      f.createNewFile();//创建一个新文件test.txt
      
    13. public boolean delete()

      调用delete(),删除文件,成功返回true,否则false

      例子:

      File f = new File("test.txt");
      f.delete();//删除文件test.txt
      

      *tips:*以上是File类的常用方法,没有囊括全部方法。其他方法需要可自行查询。

9.1 字节流

java以字节为单位去操作文件,可以使用字节流。

java提供了字节输入流:FileInputStream(InputStream子类),字节输出流:FileOutputStream(OutputStream子类)。

  • 字节输入流(FileInputStream)

    字节输入流作用:读取文件内容。

    读取文件步骤:

    1. 打开文件
    2. 读取文件内容
    3. 关闭文件

    ​ 1. 打开文件

    ​ 使用2个构造方法打开文件:

    • FileInputStream(String name);

      name是文件名

      例子

      // 打开文件时可能出现异常,如文件不存在等,所以都需要用try-catch检测异常。
              try{
                  InputStream fis = new FileInputStream("file.csv");
      
              }
              catch (IOException e){
                  System.out.println(e);
              }
      
      
    • FileInputStream(File file);

      file是File类对象

      例子

      File f = new File("file.csv");
      try{
                  InputStream fis = new FileInputStream(f);
      
              }
      catch (IOException e){
                  System.out.println(e);
              }
      
      
      

      2.读取文件内容

      当打开文件获得FileInputStream对象之后,我们就可以使用对象里的read方法读取文件内容

      常用方法:

      • int read():

        调用read(),读取单字节的数据,返回字节值(0-255),未读出字节返回-1

      • int read(byte b[])

        调用read(byte b[]),读取b.length个字节到字节数组b中,返回实际读取的数目。如果达到文件末尾,返回-1

      • int read(byte b[],int off,int len)

        调用read(byte b[],int off,int len),读取len个字节到字节数组b中,返回实际读取的数目。如果达到文件末尾,返回-1,参数off指定从字节数组中的某个位置开始存放读取的数据。

        tips: FileInputStream顺序读取文件内容,只要不关闭文件,每次调用read方法就顺序读取文件内容直到末尾

      3.关闭文件

      虽然程序在结束时自动关闭所有文件,但是显式关闭文件是良好的习惯。

      调用close()方法关闭文件。

      案例

      File.csv文件内容:123

       try{
                // 1. 打开文件
                  InputStream fis = new FileInputStream("file.csv");
      					// 2. 调用read方法读取内容
                  int n;
                  byte[] a = new byte[100];
                  while((n = fis.read(a,0,100))!=-1){
                      String s = new String(a,0,n);
                      System.out.println(s);
                  }
      					// 3. 关闭文件
                  fis.close();
              }
        catch (IOException e){
                  System.out.println(e);
              }
      
  • 字节输出流(FileOutputStream)

    字节输出流作用:写入文件内容。

    写入文件内容步骤:

    1. 打开文件
    2. 写入文件内容
    3. 关闭文件

​ 1. 打开文件

​ 使用2个构造方法打开文件:

  • FileOutputStream(String name,boolean append);

    name是文件名,append参数指定是否添加内容到文件末尾,取值true表示从文件末尾开始追加写入的内容,不指定append参数默认取值false表示清除文件内容再写入数据

    文件不存在,就会创建文件。

    例子

    // 打开文件时可能出现异常,如文件不存在等,所以都需要用try-catch检测异常。
            try{
                FileOutputStream out = new FileOutputStream("file.csv");
    
            }
            catch (IOException e){
                System.out.println(e);
            }
    
    
  • FileOutputStream(File file,boolean append);

    file是File类对象,append参数指定是否添加内容到文件末尾,取值true表示从文件末尾开始追加写入的内容,不指定append参数默认取值false表示清除文件内容再写入数据

    文件不存在,就会创建文件。

    例子

    File f = new File("file.csv");
    try{
                FileOutputStream out = new FileOutputStream(f,false);
    
            }
    catch (IOException e){
                System.out.println(e);
            }
    
    
    
  1. 写入文件内容

    当打开文件获得FileOutputStream对象之后,我们就可以使用对象里的write方法写入文件内容

    常用方法:

    • void write(int a):

      调用write(int a),写入单字节的数据a

    • void write(byte b[])

      调用write(byte b[]),写入字节数组的数据

    • void write(byte b[],int off,ing len)

      调用write(byte b[],int off,int len),写入从字节数组b的第off位置处往后的len个字节

      tips: FileOutputStream顺序写入文件内容,只要不关闭文件,每次调用write方法就顺序写入文件内容直到文件关闭

  2. 关闭文件

    在操作系统把所有写入的字节保存到磁盘上之前,有时被保存在内存缓冲区中,通过调用close方法关闭文件可以保证缓冲区

    内容写入磁盘。

案例

File.csv文件内容:123

      try{
//           1. 打开文件,如果文件存在,会清除文件内容,文件不存在,就会创建文件
            OutputStream fos = new FileOutputStream("file.csv",true);

//           2. 使用wirte方法写入内容,字符串调用getBytes()方法可以得到字符串对应的字节数组
            fos.write("happy".getBytes());
//           3. 关闭文件
            fos.close();
        }
        catch(IOException e){
            System.out.println(e);
        }

运行结束,发现file.csv文件内容变成:123happy

9.2 字符流

上面的字节流是以字节为单位读写文件数据,但是对unicode字符来说,中文字符占了两个字节,处理不当会出现“乱码”现象。

这时候,我们如果要以字符为单位读写文件数据,就得使用到字符流

java提供:字符输入流:FileReader(Reader子类),字符输出流:FileWriter(Writer子类)

  • 字符输入流(FileReader)

    字符输入流作用:读取文件内容。

    读取文件步骤:

    1. 打开文件
    2. 读取文件内容
    3. 关闭文件
    1. 打开文件

      用构造方法打开文件:

      • FileReader(String filename)

        filename参数是文件名

      • FileReader(File file)

        file参数是File类的对象,也就是先用File类确定文件,在把文件传给FileReader类来构造对象。

    2. 读取文件内容

      • int read():

        调用read(),读取单个字符的数据,返回字符的unicode值,未读出字节返回-1

      • int read(char b[])

        调用read(char b[]),读取b.length个字符到字符数组b中,返回实际读取的数目。如果达到文件末尾,返回-1

      • int read(char b[],int off,int len)

        调用read(char b[],int off,int len),读取len个字节到字符数组b中,返回实际读取的数目。如果达到文件末尾,返回-1,参数off指定从字节数组b中的某个位置开始存放读取的数据。

    3. 关闭文件

      • close()

        调用close(),关闭文件

    案例:

    File.txt内容:哈123乐乐happyhappy

            try{
    //            1.打开文件
                FileReader reader = new FileReader("file/file.csv");
                char[] a=new char[100];
                int n;
    //            2.读取文件内容
                while((n=reader.read(a,0,100))!=-1){
                    System.out.println(a);
                }
    
    //            3.关闭文件
                reader.close();
            }
            catch (IOException e){
                System.out.println(e);
            }
    

    输出:哈123乐乐happyhappy

  • 字符输出流(FileWriter)

    字符输出流作用:写入文件内容。

    写入文件内容步骤:

    1. 打开文件
    2. 写入文件内容
    3. 关闭文件
    1. 打开文件

      用构造方法打开文件:

      • FileWriter(String filename)

        filename参数是文件名

      • FileWriter(String filename, boolean append)

        filename参数是文件名

        append参数指定是否以从文件末尾追加内容的方式写入

      • FileWriter(File file)

        file参数是File类的对象,也就是先用File类确定文件,在把文件传给FileReader类来构造对象

      • FileWriter(File file,boolean append)

        file参数是File类的对象,也就是先用File类确定文件,在把文件传给FileReader类来构造对象

        append参数指定是否以从文件末尾追加内容的方式写入

    2. 写入文件内容

      • void write(char c)

        调用write(char c),写入单个字符c

      • void write(char b[])

        调用write(char b[]),把字符数组b数据写入

      • void write(char b[],int off,int len)

        调用write(char b[],int off,int len),写入字符数组的len个字节到文件中,参数off指定从字符数组b中的某个位置开始写入读取的数据

      • void write(String s)

        调用write(String s),把字符串s写入

    3. 关闭文件

      • close()

        调用close(),关闭文件

案例

​ test.txt无内容

   try{
//            1.打开文件
            FileWriter writer = new FileWriter("file/test.txt");
//            2.写入字符串
            writer.write("今天天气真good!\n");
//            3.关闭文件
            writer.close();

        }
   catch (IOException e){
            System.out.println("file error:"+e);
        }

输出:test.txt文件多了字符串“今天天气真good!”。

9.3 随机流

上面学习了字节流和字符流,我们发现读和写文件是分开的,这时候,我们想,能不能像python那样,读写是可以一起的呢?

当然是可以的啦

java提供了随机流类(RandomAccessFile),使得我们可以既能读也能写~

  • RandomAccessFile

    操作文件过程:

    1. 指定模式打开文件
    2. 读写文件
    3. 关闭文件
    1. 指定模式打开文件

      两个构造方法:

      • RandomAccessFile(String name,String mode)

        name 打开文件名

        mode 指定以r(只读)或rw(可读写)模式打开

      • RandomAccessFile(File file,String mode)

        file 打开的文件

        mode 指定以r(只读)或rw(可读写)模式打开

    2. 读写文件

      常用方法:

      方法功能
      close()关闭文件
      getFilePoint()获取当前读写的位置
      length()获取文件的长度
      read()从文件中读取一个字节的数据
      readBoolean()从文件中读取一个布尔值,0代表false,其他代表true
      readByte()从文件中读取一个字节
      readChar()从文件中读取一个字符(2个字节)
      readDouble()从文件中读取一个双精度浮点值(8个字节)
      readFloat()从文件中读取一个单精度浮点值(4个字节)
      readFully(byte b[])读b.length字节放入数组b,完全填满该数组
      readInt()从文件中读取一个int值(4个字节)
      readLine()从文件中读取一个文本行
      readLong()从文件中读取一个长整形(8个字节)
      readShort()从文件中读取一个短整形(2个字节)
      readUnsignedByte()从文件中读取一个无符号字节(1个字节)
      readUnsignedShort()从文件中读取一个无符号短整形(2个字节)
      readUTF()从文件中读取一个UTF字符串
      seek(long position)定位读写位置
      setLength(long newlength)设置文件的长度
      skipBytes(int n)在文件中跳过给定数量的字节
      write(byte b[])写入b.length个字节到文件
      writeBoolean(boolean v)把一个布尔值作为单字节值写入文件
      writeByte(int v)向文件写入一个字节
      writeBytes(String s)向文件写入一个字符串
      writeDouble(double v)向文件写入一个双精度浮点值
      writeFloat(float v)向文件写入一个单精度浮点值
      writeInt(int v)向文件写入一个int值
      writeLong(long v)向文件写入一个long值
      writeShort(int v)向文件写入一个short值
      writeUTF(String s)向文件写入一个UTF字符串
      writeChar(char c)向文件写入一个字符
      writeChars(String s)向文件写入一个作为字符数据的字符串
      注意:调用readLine()方法在读取非ASCII字符的文件(比如含有中文字符的文件)会出现“乱码”,因此需要把readLine()读取的字符串用“iso-8859-1”编码重新编码存入byte数组中,然后用当前机器的默认编码将该数组转为字符串。操作如下:
      • 1.读取

        String str = in.readLine();
        
      • 2.“iso-8859-1”重新编码

        byte b[] = str.getBytes("iso-8859-1");
        
      • 3.使用当前机器的默认编码将字节数组转为字符串

        String content = new String(b)
        

    案例

      		try{
                RandomAccessFile inAndOut = new RandomAccessFile("english.txt","rw");
                long length = inAndOut.length(); // 获取文件长度
                long position = 0;
                inAndOut.seek(position); // 设置文件起始位置
                while(position<length){
                    String str = inAndOut.readLine();
                    byte[] b = str.getBytes("iso-8859-1");
                    String content = new String(b);
                    position = inAndOut.getFilePointer();
                    System.out.println(content);
                }
                inAndOut.close();
            }
            catch (IOException e){
                System.out.println(e);
            }
    
9.4 数组流

上面学的是从文件中读写数据,java还可以从计算机内存中读写数据。

字节数组流:字节数组输入流(ByteArrayInputStream), 字节数组输出流(ByteArrayOutputStream)

字符数组流:

  • 字节数组输入流(ByteArrayInputStream):

    1. 指定读取源:

      使用构造方法指定读取源:

      • ByteArrayInputStream(byte[] buf);

        @param buf 要从内存中读取的字节数组的全部字节单元

      • ByteArrayInputStream(byte[] buf,int offset,int length);

        @param buf 要从内存中读取的字节数组

        @param offset 指定从offset处开始读取

        @param length 指定读取几个字节单元

    2. 读取数据

      • public int read()

        调用read()方法,顺序读出一个字节,返回读取的字节值

      • public int read(byte[] b, int off,int len)

        @param b 指定读取的内容存入的数组

        @param off 指定读取起始位置

        @param len 指定读取的字节数

        调用 read(byte[] b, int offing len)方法,从读取源汇中第 off 个字节开始顺序读取 len 个字节的数据,存入b数组中,返回实际读取的字节个数,如果没有读取字节返回-1.

    3. 关闭读取源

      • close()
  • 字节数组输出流(ByteArrayOutputStream)

    1. 指定输出源:

      使用构造方法指定输出源:

      • ByteArrayOutputStream();

        向一个默认大小而32字节的缓冲区写入内容,如果输出内容字节个数大于缓冲区,缓冲区容量自动增加

      • ByteArrayOutputStream(int size);

        @param size 指定写入到的缓冲区初始大小

        向初始大小为size的缓冲区写入内容,如果输出内容字节个数大于缓冲区,缓冲区容量自动增加

    2. 输出数据

      • public void write(int b)

        调用write(int b)方法,顺序地向缓冲区写入一个字节

      • public void write(byte[] b, int off,int len)

        @param b 指定把数组b内容写入缓冲区

        @param off 指定写入起始位置

        @param len 指定写入的字节数

        调用 write(byte[] b, int off,int len)方法,

      • public byte[] to ByteArray()

        调用byteArray(),可以返回输出流写入到缓冲区的全部字节

    3. 关闭读取源

      • close()

案例

   			try{
					//指定写入源:
            ByteArrayOutputStream outByte = new ByteArrayOutputStream();
          //生成输入内容
            byte [] byteContent = "mid-autumn festival ".getBytes();
          //把byteContent写入缓冲区
            outByte.write(byteContent);
          //指定读取源
            ByteArrayInputStream inByte = new ByteArrayInputStream(outByte.toByteArray());
            byte backByte[] = new byte[outByte.toByteArray().length];
        	//读取缓冲区内容存入backByte  
            inByte.read(backByte);
        	//打印读取的内容  
            System.out.println(new String(backByte));
          //关闭
            inByte.close();
            outByte.close();

        }
        catch (IOException e){
            System.out.println(e);
        }
    
  • 字符数组流CharArrayReader和CharArrayWriterlei ,与字节数组流对应,字节数组流是把字节数组作为流的源和目标,字符数组流是把字符数组作为流的源和目标。

    案例

       			try{
    
    //           字符数组流
                CharArrayWriter outChar = new CharArrayWriter();
                char[] charContent = "中秋快乐".toCharArray();
                outChar.write(charContent);
                CharArrayReader inChar = new CharArrayReader(outChar.toCharArray());
                char backChar[] = new char[outChar.toCharArray().length];
                inChar.read(backChar);
                System.out.println(new String(backChar));
    
            }
            catch (IOException e){
                System.out.println(e);
            }
    
9.5 数据流

数据输入流(DataInputStream

数据输出流(DataOutputStream

使用数据流,允许按着机器无关的风格读取Java原始数据,也就是说,当读取一个数值时,不必再关心这个数值应当是多少个字节。

  • DataInputStream构造方法:DataInputStream(InputStream in)

  • DataOutputStream构造方法:DataOutputStream(OutputStream in)

  • 数据流常用方法:

    方法描述
    close()关闭流
    readBoolean()读取一个布尔值
    readByte()读取一个字节
    readChar()读取一个字符
    readDouble()读取一个double型数据
    readFloat()读取一个float型数据
    readInt()读取一个int型数据
    readLong()读取一个long型数据
    readShort()读取一个short型数据
    readUnsignedByte()读取一个无符号字节
    readUnsignedShort()读取一个无符号短型
    readUTF()读取一个UTF字符串
    skipBytes(int n)跳过给定的字节数
    writeBoolean(boolean v)写入一个布尔值
    writeBytes(String s)写入一个字符串
    writeChars(String s)写入字符串
    writeDouble(double v)写入一个double型数据
    writeFloat(float v)写入一个float型数据
    writeInt(int v)写入一个int型数据
    writeLong(long v)写入一个long型数据
    writeShort(int v)写入一个short型数据
    writeUTF(String s)写入一个UTF字符串

案例

        File file = new File("appl.txt");
//      数据输出流
        try{
            FileOutputStream fos = new FileOutputStream(file);
            DataOutputStream outData = new DataOutputStream(fos);
            outData.writeBytes("hehlo");
        }
        catch(IOException e){
            System.out.println(e);
        }
//       数据输入流
        try{
            FileInputStream in = new FileInputStream(file);
            DataInputStream inData = new DataInputStream(in);
            byte c;
            while((c=inData.readByte())!='\0'){
                System.out.print((char)c);
            }

        }
        catch (IOException e){
        }
9.6 对象流

对象输出流(ObjectOutputStream

对象输入流(ObjectInputStream

使用对象流,可以把对象读写到文件。

读写对象时,必须保证对象是序列化的,什么是序列化呢,一个类如果实现了Serializable接口,这个类创建的对象就是序列化对象,java类库提供的绝大多数对象都是序列化的。但是Serializable接口中没有方法,因此实现该接口的类不需要实现额外的方法,用implements Serializable表明这个类实现Serializable接口即可。

  • ObjectOutputStream构造方法:ObjectOutputStream(OutputStream out)

  • ObjectInputStream构造方法:ObjectInputStream(InputStream in)

  • 写入方法:writeObject(object)

  • 读入方法: readObject(object)

案例:

TV.java:

import java.io.*;
public class TV implements Serializable{
    String name;
    int price;
    public void setName(String s){
        name =s;
    }
    public void setPrice(int n){
        price=n;
    }
    public String getName(){
        return name;
    }
    public int getPrice(){
        return price;
    }
}

Example.java:

import java.io.*;
public class Example {
    public static void main(String[] args) {
        TV  changhong = new TV();
        changhong.setName("长虹电视");
        changhong.setPrice(5678);
        File file = new File("telecision.txt");
        try {
            FileOutputStream fileout = new FileOutputStream(file);
            ObjectOutputStream objectOut = new ObjectOutputStream(fileout);
            objectOut.writeObject(changhong);
            objectOut.close();

            FileInputStream fileIn = new FileInputStream(file);
            ObjectInputStream objectIn = new ObjectInputStream(fileIn);
            TV xinfei = (TV) objectIn.readObject();
            objectIn.close();

            System.out.println("xinfei name "+xinfei.getName());
            System.out.println("xinfei price "+xinfei.getPrice());

            xinfei.setName("新飞电视");
            xinfei.setPrice(10);
            System.out.println("xinfei name "+xinfei.getName());
            System.out.println("xinfei price "+xinfei.getPrice());

        }
        catch (ClassNotFoundException event){
            System.out.println("不能读出对象");

        }
        catch (IOException event){
            System.out.println(event);
        }
    }
}
9.7 序列化与对象克隆

一个类的两个对象如果具有相同的引用,那么他们就拥有相同的实体和功能,即他们指向的内存空间一样,修改其中一个,另一个也随之改变。

如:

A one  = new A()
A two = one;

假设A类中有int型成员变量x,当进行下面操作:

one.x = 200;

那么two.x也是200。

那么问题来了,有时候,我们想得到的是一个“复制品”,修改其中一个,另一个不改变,这样的对象就称为原对象的一个克隆对象

使用对象流很容易获得一个对象的克隆,比如上一小节的案例中,xinfei就是changhong的一个克隆。

那么如何快速获得一个对象的克隆呢?之前是通过对象流读写文件获取,我们还可以通过数组流读写入内存快速获得一个对象的克隆。

案例:单击“写出对象”按钮将标签写入内存,单击“读入对象”按钮读入标签的克隆对象,并改变该克隆对象的文字。

import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
public class demo {
    public static void main(String[] args) {
       MyWin win = new MyWin();
    }
}

class MyWin extends JFrame implements ActionListener{
    JLabel label = null;
    int i=0;
    JButton 读入 = null,写出= null;
    ByteArrayOutputStream out = null;
    MyWin(){
        setLayout(new FlowLayout());
        label = new JLabel("How are you");
        读入=new JButton("读入对象");
        写出=new JButton("写出对象");
        读入.addActionListener(this);
        写出.addActionListener(this);
        setVisible(true);
        add(label);
        add(写出);
        add(读入);
        setSize(500,400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        validate();


    }
    public void actionPerformed(ActionEvent e){

        if(e.getSource()==写出){
            try{
                out = new ByteArrayOutputStream();
                ObjectOutputStream objectOut = new ObjectOutputStream(out);
                objectOut.writeObject(label);
                objectOut.close();
            }
            catch (IOException ev){
                System.out.println(ev);
            }

        }
        else if(e.getSource()==读入){
            try{

                ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
                ObjectInputStream objectIn = new ObjectInputStream(in);
                JLabel temp = (JLabel) objectIn.readObject();
                temp.setText("第"+i+"次读入");
                this.add(temp);
                this.validate();
                objectIn.close();
                i++;
            }
            catch (Exception event){
                System.out.println(event);
            }
        }
    }
}

9.8 使用Scanner解析文件

对于Scanner类,我们可以用来获取键盘的输入,可以解析字符串,也可以解析文件

  • 使用默认分割标记空格解析文件

     File file = new File("student.txt");
     Scanner sc  = new Scanner(file);
    
    

    sc就会把空格作为分割标记,调用next()方法依次返回file中的单词,如果file中最后一个单词已被next()返回,sc调用hasNext()就返回false,否则返回true;对于数字型单词,还可以调用nextInt()、nextDoule()等返回数字。

  • 使用正则表达式作为分割标记解析文件

    File file = new File("student.txt");
    Scanner sc  = new Scanner(file);
    //设置匹配的正则表达式
    sc.useDelimiter("[^0-9.]+");
    

    设置正则表达式后,就以此来分割文件内容,调用next()依次返回分割的单词。

案例:提取文件student.txt中的分数数字

student.txt 内容:小明的成绩是72分,张三的成绩是90分,赵四的成绩是100分。

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class Example {
    public static void main(String[] args) {
        try{
            File file = new File("student.txt");
            Scanner sc  = new Scanner(file);
//          设置匹配的正则表达式
            sc.useDelimiter("[^0-9.]+");
            while(sc.hasNext()){
                System.out.print(sc.next()+" ");
            }
        }
        catch (IOException e){
            System.out.println(e);
        }

    }
}

输出:72 90 100

9.9 文件锁

有时候,遇到好几个程序处理同一个文件的情况,处理不当就可能发生混乱。这时候,保险起见,一个文件在某个时间段内应该只能被一个程序操作,把文件锁住,等处理完了,解锁文件,文件就可以被其他程序操作了。

如何实现呢?java提供了FileLockFileChannel类来实现文件锁功能。

  • 步骤:

    • 使用RandomAccessFile流以“rw”模式打开文件:

      RandomAccessFile input = new RandomAccessFile("Example.java","rw");
      
    • input调用方法getChannel()获得一个连接到底层文件的FileChannel对象(信道):

      FileChannel channel = input.getChannel();
      
    • 信道调用tryLock()或lock()方法获得一个FileLock(文件锁)对象,给文件加锁:

      FileLock = channel.tryLock();
      
    • 文件加锁后,禁止任何程序对文件操作或再加锁。对于加锁后的文件,如果想读写文件,就必须让FileLock对象调用release()方法释放文件锁:

      lock.release();
      

案例:java程序通过单击按钮释放文件锁,并读取文件中的一行并马上加锁。其他因此程序无法操作文件,比如用windows记事本程序去改当前文件,但是无法保存。

example.txt 内容

123
hello
test

WindowFileLock.java:

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class WindowFileLock extends  JFrame implements ActionListener{
    JTextArea text;
    JButton button;
    File file;
    RandomAccessFile input;
    FileChannel channel;
    FileLock lock;
    WindowFileLock(File f){
        file =f;
        try{
            input = new RandomAccessFile(file,"rw");
            channel = input.getChannel();
            lock = channel.tryLock();

        }
        catch (Exception exp){}
        text = new JTextArea();
        button = new JButton("读取一行");
        button.addActionListener(this);
        add(new JScrollPane(text),BorderLayout.CENTER);
        add(button,BorderLayout.SOUTH);
        setSize(300,400);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }
    public void actionPerformed(ActionEvent e){
        try{
            lock.release();
            String lineString = input.readLine();
            text.append("\n"+lineString);
            lock = channel.tryLock();
            if(lineString==null){
                input.close();
            }
        }
        catch (Exception ee){}
    }
}

MainClass.java:

import java.io.*;
public class MainClass {
    public static void main(String[] args) {
        File file = new File("example.txt");
        WindowFileLock win = new WindowFileLock(file);
        win.setTitle("使用文件锁");
    }
}

公粽号:为你作画

  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值