
admin
2025-07-18 01:02:57
文件IO流
文件流框架:
9.0 File类
File类,即文件类。
我们如果需要获取文件的信息,或者在磁盘上创建新的文件,就需要用到File类。
File类的对象可以获取文件信息,不涉及文件的读写。文件读写需要用到下面的各种输入输出流。
File类3个构造方法:
File (String filename) (以此创建文件,文件与当前应用程序在同一目录)File(String directoryPath,String filename)File(File dir,String filename)
注:filename是文件名字,directoryPath是文件的路径,dir是目录。
File类常用方法:
public String getName()
调用getName(),获取文件名字
例子:
File f = new File("test.txt");
System.out.println(f.getName()); //=>test.txt
public boolean canRead()
调用canRead(),判断文件是否可读,可读返回true,否则false
例子:
File f = new File("test.txt");
System.out.println(f.canRead()); //=>true
public boolean canWrite()
调用canWrite(),判断文件是否可写,可写返回true,否则false
例子:
File f = new File("test.txt");
System.out.println(f.canWrite()); //=>true
public boolean exists()
调用exists(),判断文件是否存在,存在返回true,否则false
例子:
File f = new File("test.txt");
System.out.println(f.exists()); //=>true
public long length()
调用length(),获取文件长度(单位是字节)
例子:
File f = new File("test.txt");
System.out.println(f.length()); //=>0
public String getAbsolutePath()
调用getAbsolutePath(),获取文件的绝对路径
例子:
File f = new File("test.txt");
System.out.println(f.length()); //=>/Users/console/IdeaProjects/firstTime/test.txt
public String getParent()
调用getParent(),获取文件的父目录
例子:
File f = new File("test.txt");
System.out.println(f.getParent()); //=>null
public boolean isFile()
调用isFile(),判断文件是否是一个普通文件,而不是目录
例子:
File f = new File("test.txt");
System.out.println(f.isFile());//=>true
public boolean isDirectory()
调用isDirectory(),判断文件是否是一个目录。
例子:
File f = new File("test.txt");
System.out.println(f.isDirectory());//=>false
public boolean isHidden()
调用isHidden(),判断文件是否隐藏
例子:
File f = new File("test.txt");
System.out.println(f.isHidden());//=>false
public long lastModified()
调用lastModified(),获取文件最后修改时间(时间戳)
例子:
File f = new File("test.txt");
System.out.println(f.lastModified());//=>1666171192322
public boolean createNewFile()
调用createNewFile(),创建一个新文件,成功返回true,否则false
例子:
File f = new File("test.txt");
f.createNewFile();//创建一个新文件test.txt
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个构造方法打开文件:
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个构造方法打开文件:
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);
}
写入文件内容
当打开文件获得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方法就顺序写入文件内容直到文件关闭
关闭文件
在操作系统把所有写入的字节保存到磁盘上之前,有时被保存在内存缓冲区中,通过调用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)
字符输入流作用:读取文件内容。
读取文件步骤:
打开文件读取文件内容关闭文件
打开文件
用构造方法打开文件:
FileReader(String filename)
filename参数是文件名
FileReader(File file)
file参数是File类的对象,也就是先用File类确定文件,在把文件传给FileReader类来构造对象。
读取文件内容
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中的某个位置开始存放读取的数据。
关闭文件
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)
字符输出流作用:写入文件内容。
写入文件内容步骤:
打开文件写入文件内容关闭文件
打开文件
用构造方法打开文件:
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参数指定是否以从文件末尾追加内容的方式写入
写入文件内容
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写入
关闭文件
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
操作文件过程:
指定模式打开文件读写文件关闭文件
指定模式打开文件
两个构造方法:
RandomAccessFile(String name,String mode)
name 打开文件名
mode 指定以r(只读)或rw(可读写)模式打开
RandomAccessFile(File file,String mode)
file 打开的文件
mode 指定以r(只读)或rw(可读写)模式打开
读写文件
常用方法:
方法功能close()关闭文件getFilePoint()获取当前读写的位置length()获取文件的长度read()从文件中读取一个字节的数据readBoolean()从文件中读取一个布尔值,0代表false,其他代表truereadByte()从文件中读取一个字节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 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): 指定读取源: 使用构造方法指定读取源: ByteArrayInputStream(byte[] buf); @param buf 要从内存中读取的字节数组的全部字节单元 ByteArrayInputStream(byte[] buf,int offset,int length); @param buf 要从内存中读取的字节数组 @param offset 指定从offset处开始读取 @param length 指定读取几个字节单元 读取数据 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. 关闭读取源 close() 字节数组输出流(ByteArrayOutputStream) 指定输出源: 使用构造方法指定输出源: ByteArrayOutputStream(); 向一个默认大小而32字节的缓冲区写入内容,如果输出内容字节个数大于缓冲区,缓冲区容量自动增加 ByteArrayOutputStream(int size); @param size 指定写入到的缓冲区初始大小 向初始大小为size的缓冲区写入内容,如果输出内容字节个数大于缓冲区,缓冲区容量自动增加 输出数据 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(),可以返回输出流写入到缓冲区的全部字节 关闭读取源 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提供了FileLock和FileChannel类来实现文件锁功能。 步骤: 使用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("使用文件锁"); } } 公粽号:为你作画