java io 操作_Java IO常用操作(一)写文件

在Java中对系统文件进行写入是一种很常见的操作,本文总结了写文件的一些常用实现,并对其进行对比。

BufferedWriter

首先使用BufferedWriter向新文件中写入简单的字符串:

@Test

public void writeStringsWithBufferedWriter() throws IOException{

String str = "test";

BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));

writer.write(str);

writer.close()

}

复制代码

执行程序后,文件中的内容为:

test

复制代码

我们同样可以在已有的文件中追加字符串:

@Test

public void appendStringsWithBufferedWriter() throws IOException{

String str = " Hello,World";

BufferedWriter writer = new BufferedWriter(new FileWriter(fileName true));

writer.append(str);

writer.close();

}

复制代码

执行之后,文件内容变为:

test Hello,World

复制代码

PrintWriter

使用PrintWriter可以向文件中写入格式化的文本:

@Test

public void writeStringWithPrintWriter() throws IOException{

FileWriter writer = new FileWriter(fileName);

PrintWriter printWriter = new PrintWriter(fileWriter);

printWriter.print("test1");

printWriter.printf("string %s, num %d", "formatString", 10);

printWriter.close();

}

复制代码

文件内容为

test1

string formatString,num 10

复制代码

我们可以利用FileWriter、BufferedWriter甚至是System.out来构造PrintWriter,通过PrintWriter不仅可以向文件中写入原生字符串,而且可以利用printf方法写入格式化的文本。

FileOutputStream

使用FileOutputStream可以向文本中写入二进制数据,示例如下:

@Test

public void writeFileWithFileOutputStream() throws IOException{

String str = "test";

FileOutputStream stream = new FileOutputStream(fileName);

byte[] bytes = str.getBytes();

stream.write(bytes);

stream.close();

}

复制代码

DataOutputStream

@Test

public void writeFileWithDataOutputStream() throws IOExeption{

String str = "test";

FileOutputStream fos = new FileOutputStream(fileName);

DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(fos));

dos.write(str);

dos.close();

}

复制代码

RandomAccessFile

目前为止,我们都只是写全新的文件或者是在已有文件中追加新的内容,但是很多时候我们需要在已有文件中写入内容或者编辑内容,也就是要对文件进行随机访问。RandomAccessFile在给定偏移值后,就可以向文件中的特定位置写入二进制内容,下例中的代码可以在文件的特定位置写入一个数字:

void writeIntOnPosition(String fileName, int data, long position) throws IOException{

RandomAccessFile writer = new RandomAccessFile(fileName, "rw");

writer.seek(position);

writer.writeInt(data);

writer.close();

}

复制代码

可以使用类似的方式实现从特定位置读取数字:

int readIntOnPosition(String fileName, long position) throws IOException{

int result = 0;

RandomAccessFile reader = new RandomAccessFile(fileName, "r");

reader.seek(position);

result = reader.readInt();

reader.close();

return result;

}

复制代码

可以通过下面的方法进行简单的测试:

@Test

public void writeFileWithRandomAccessFile() throws IOException{

int origin_int = 1;

int change_int = 2;

long position = 12;

writeIntOnPosition(fileName, origin_int, position);

assertEquals(origin_int, readIntOnPosition(fileName, position));

writeIntOnPosition(fileName, change_int, position);

assertEquals(change_int, readIntOnPosition(fileName, position));

}

复制代码

FileChannel

对于大文件的操作,FileChannel比标准IO接口更高效。使用示例如下:

@Test

public void writeFileWithFileChannel() throws IOException{

RandomAccessFile stream = new RandomAccessFile(fileName, "rw");

FileChannel channel = stream.getChannel();

String str = "test";

byte[] bytes = str.getBytes();

ByteBuffer buffer = ByteBuffer.allocate(bytes.length);

buffer.put(bytes);

buffer.flip();

channel.write(buffer);

stream.close();

channel.close();

RandomAccessFile reader = new RandomAccessFile(fileName, "r");

assertEquals(str, reader.readLine());

reader.close()

}

复制代码

使用Java 7

在Java 7中,引入了新的工具类Files,提供了一种操作文件系统的新方式。通过该工具类,可以对文件和目录进行新增、复制、删除、移动等操作,同样也可以用来读写文件内容:

@Test

public void writeFileWithJava7() throws IOException{

String str = "test";

Path path = Paths.get(fileName);

byte[] bytes = str.getBytes();

Files.write(path, bytes);

String read = Files.readAllLines(path).get(0);

asserEquals(str, read);

}

复制代码

写入临时文件

接下来,我们尝试对临时文件进行写操作:

@Test

public void writeToTmpFile() throws IOException{

String str = "Hello";

File tmpFile = File.createTempFile("test", ".tmp");

FileWriter writer = new FileWriter(tmpFile);

writer.write(str);

writer.close();

BufferedReader reader = new BufferedReader(new FileReader(tmpFile));

assertEquals(str, reader.readLine());

reader.close();

}

复制代码

可以看出,除了临时文件的创建之外,其余操作都是大同小异的。

写操作之前对文件加锁

有时候,我们在对文件进行写操作之前,需要保证其他人不会同时对该文件进行修改,也就是说我们需要在写文件时对其进行加锁。

在对文件写入之前,我们可以使用FileChannel尝试对文件进行加锁:

@Test

public void tryLockFileBeforeWrite() throws IOException{

RandomAccessFile stream = new RandomAccessFile(fileName, "rw");

FileChannel channel = stream.getChannel();

FileLock lock = null;

try{

lock = channel.tryLock();

}catch(final OverlappingFileLockException e){

stream.close();

channel.close();

}

stream.writeChars("test");

lock.release();

stream.close();

channel.close();

}

复制代码

注意,如果我们尝试获取锁时,文件处于已加锁状态,则会抛出OverlappingFileLockException。

总结

以上的方法都能实现写文件的目的,但是仍有一些需要注意的地方:

如果尝试读一个不存在的文件,会抛出FileNotFoundException。

如果尝试写一个不存在的文件,会先创建该文件,不会抛出异常。

在使用完流对象之后,一定要及时关闭以释放相关系统资源,这一点非常重要,因为流对象不会隐式自动关闭。

在输出流中,close()方法在释放系统资源之前会首先调用flush()方法,强制将缓存的数据写入流中。

通常来说,PrintWriter用于编写格式化文本,FileOutputStream用于写二进制数据,DataOutputStream用于写基本数据类型,RandomAccessFile用于在特定位置对文件进行操作,FileChannel对于大型文件的操作更加高效。虽然这些API都可以提供很多功能,但是根据不同的使用场景选择合适的方案会更加便利。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值