Java – Write to File – Java – 写入文件

最后修改: 2014年 10月 1日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll explore different ways to write to a file using Java. We’ll make use of BufferedWriter, PrintWriter, FileOutputStream, DataOutputStream, RandomAccessFile, FileChannel, and the Java 7 Files utility class.

在本教程中,我们将探索使用Java向文件写入的不同方法。我们将利用BufferedWriterPrintWriterFileOutputStreamDataOutputStreamRandomAccessFileFileChannel和Java 7Files实用类。

We’ll also look at locking the file while writing and discuss some final takeaways on writing to file.

我们还将研究在写作时锁定文件的问题,并讨论向文件写作的一些最终收获。

This tutorial is part of the Java “Back to Basics” series here on Baeldung.

本教程是Baeldung网站上Java “回到基础知识 “系列的一部分。

2. Write With BufferedWriter

2.用BufferedWriter编写

Let’s start simple and use BufferedWriter to write a String to a new file:

让我们从简单的开始,使用BufferedWriter来写一个String到一个新的文件

public void whenWriteStringUsingBufferedWritter_thenCorrect() 
  throws IOException {
    String str = "Hello";
    BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
    writer.write(str);
    
    writer.close();
}

The output in the file will be:

文件中的输出将是。

Hello

We can then append a String to the existing file:

然后我们可以将一个字符串附加到现有的文件

@Test
public void whenAppendStringUsingBufferedWritter_thenOldContentShouldExistToo() 
  throws IOException {
    String str = "World";
    BufferedWriter writer = new BufferedWriter(new FileWriter(fileName, true));
    writer.append(' ');
    writer.append(str);
    
    writer.close();
}

The file will then be:

然后,该文件将是。

Hello World

3. Write With PrintWriter

3.用PrintWriter编写

Next, let’s see how we can use PrintWriter to write formatted text to a file:

接下来,让我们看看我们如何使用PrintWriter向文件写入格式化的文本

@Test
public void givenWritingStringToFile_whenUsingPrintWriter_thenCorrect() 
  throws IOException {
    FileWriter fileWriter = new FileWriter(fileName);
    PrintWriter printWriter = new PrintWriter(fileWriter);
    printWriter.print("Some String");
    printWriter.printf("Product name is %s and its price is %d $", "iPhone", 1000);
    printWriter.close();
}

The resulting file will contain:

由此产生的文件将包含。

Some String
Product name is iPhone and its price is 1000$

Note how we’re not only writing a raw String to a file, but also some formatted text with the printf method.

请注意,我们不仅要向文件写入一个原始的String,还要用printf方法写入一些格式化的文本。

We can create the writer using FileWriter, BufferedWriter, or even System.out.

我们可以使用FileWriterBufferedWriter,甚至System.out来创建写入器。

4. Write With FileOutputStream

4.用FileOutputStream

Let’s now see how we can use FileOutputStream to write binary data to a file.

现在让我们看看如何使用FileOutputStream向文件写入二进制数据。

The following code converts a String into bytes and writes the bytes to a file using FileOutputStream:

下面的代码将一个字符串转换为字节,并使用FileOutputStream将字节写入文件。

@Test
public void givenWritingStringToFile_whenUsingFileOutputStream_thenCorrect() 
  throws IOException {
    String str = "Hello";
    FileOutputStream outputStream = new FileOutputStream(fileName);
    byte[] strToBytes = str.getBytes();
    outputStream.write(strToBytes);

    outputStream.close();
}

The output in the file will of course be:

文件中的输出当然会是。

Hello

5. Write With DataOutputStream

5.用DataOutputStream

Next, let’s take a look at how we can use DataOutputStream to write a String to a file:

接下来,让我们看看如何使用DataOutputStream向文件写入String

@Test
public void givenWritingToFile_whenUsingDataOutputStream_thenCorrect() 
  throws IOException {
    String value = "Hello";
    FileOutputStream fos = new FileOutputStream(fileName);
    DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(fos));
    outStream.writeUTF(value);
    outStream.close();

    // verify the results
    String result;
    FileInputStream fis = new FileInputStream(fileName);
    DataInputStream reader = new DataInputStream(fis);
    result = reader.readUTF();
    reader.close();

    assertEquals(value, result);
}

6. Write With RandomAccessFile

6.用RandomAccessFile

Let’s now illustrate how to write and edit inside an existing file rather than just writing to a completely new file or appending to an existing one. Simply put: We need random access.

现在让我们来说明一下如何在一个现有的文件内进行写入和编辑,而不是仅仅写入一个全新的文件或追加到一个现有的文件中。简单地说:我们需要随机访问。

RandomAccessFile enables us to write at a specific position in the file given the offset — from the beginning of the file — in bytes.

RandomAccessFile使我们能够在文件中的一个特定位置写入,给定的偏移量–从文件的开始–以字节为单位。

This code writes an integer value with offset given from the beginning of the file:

这段代码写了一个整数值,其偏移量从文件的开头开始给定:

private void writeToPosition(String filename, int data, long position) 
  throws IOException {
    RandomAccessFile writer = new RandomAccessFile(filename, "rw");
    writer.seek(position);
    writer.writeInt(data);
    writer.close();
}

If we want to read the int stored at a specific location, we can use this method:

如果我们想读取存储在特定位置的int,我们可以使用这个方法。

private int readFromPosition(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;
}

To test our functions, let’s write an integer, edit it, and finally read it back:

为了测试我们的函数,让我们写一个整数,编辑它,最后读回它。

@Test
public void whenWritingToSpecificPositionInFile_thenCorrect() 
  throws IOException {
    int data1 = 2014;
    int data2 = 1500;
    
    writeToPosition(fileName, data1, 4);
    assertEquals(data1, readFromPosition(fileName, 4));
    
    writeToPosition(fileName2, data2, 4);
    assertEquals(data2, readFromPosition(fileName, 4));
}

7. Write With FileChannel

7.用FileChannel

If we are dealing with large files, FileChannel can be faster than standard IO. The following code writes String to a file using FileChannel:

如果我们处理大文件,FileChannel可能比标准IO更快。下面的代码使用FileChannelString写到一个文件。

@Test
public void givenWritingToFile_whenUsingFileChannel_thenCorrect() 
  throws IOException {
    RandomAccessFile stream = new RandomAccessFile(fileName, "rw");
    FileChannel channel = stream.getChannel();
    String value = "Hello";
    byte[] strBytes = value.getBytes();
    ByteBuffer buffer = ByteBuffer.allocate(strBytes.length);
    buffer.put(strBytes);
    buffer.flip();
    channel.write(buffer);
    stream.close();
    channel.close();

    // verify
    RandomAccessFile reader = new RandomAccessFile(fileName, "r");
    assertEquals(value, reader.readLine());
    reader.close();
}

8. Write With Files Class

8.用Files类写

Java 7 introduces a new way of working with the filesystem, along with a new utility class: Files.

Java 7引入了一种与文件系统打交道的新方法,以及一个新的实用类。Files

Using the Files class, we can create, move, copy, and delete files and directories. It can also be used to read and write to a file:

使用Files类,我们可以创建、移动、复制和删除文件和目录。它还可以用来读取和写入一个文件。

@Test
public void givenUsingJava7_whenWritingToFile_thenCorrect() 
  throws IOException {
    String str = "Hello";

    Path path = Paths.get(fileName);
    byte[] strToBytes = str.getBytes();

    Files.write(path, strToBytes);

    String read = Files.readAllLines(path).get(0);
    assertEquals(str, read);
}

9. Write to a Temporary File

9.写入临时文件

Now let’s try to write to a temporary file. The following code creates a temporary file and writes a String to it:

现在让我们试着向一个临时文件写入。下面的代码创建了一个临时文件,并将一个String写入其中。

@Test
public void whenWriteToTmpFile_thenCorrect() throws IOException {
    String toWrite = "Hello";
    File tmpFile = File.createTempFile("test", ".tmp");
    FileWriter writer = new FileWriter(tmpFile);
    writer.write(toWrite);
    writer.close();

    BufferedReader reader = new BufferedReader(new FileReader(tmpFile));
    assertEquals(toWrite, reader.readLine());
    reader.close();
}

As we can see, it’s just the creation of the temporary file that is interesting and different. After that point, writing to the file is the same.

正如我们所看到的,只是创建临时文件的过程比较有趣和不同。在那之后,向文件的写入是一样的。

10. Lock File Before Writing

10.写入前锁定文件

Finally, when writing to a file, we sometimes need to make extra sure that no one else is writing to that file at the same time. Basically, we need to be able to lock that file while writing.

最后,当向一个文件写入时,我们有时需要特别确保没有其他人在同一时间向该文件写入。基本上,我们需要在写的时候能够锁定该文件。

Let’s make use of FileChannel to try locking the file before writing to it:

让我们利用FileChannel 来尝试在写入文件之前锁定该文件。

@Test
public void whenTryToLockFile_thenItShouldBeLocked() 
  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");
    lock.release();

    stream.close();
    channel.close();
}

Note that if the file is already locked when we try to acquire the lock, an OverlappingFileLockException will be thrown.

请注意,如果我们试图获取锁的时候,文件已经被锁定,将抛出OverlappingFileLockException

11. Notes

11.注释

After exploring so many methods of writing to a file, let’s discuss some important notes:

在探索了这么多向文件写入的方法后,我们来讨论一些重要的注意事项。

  • If we try to read from a file that doesn’t exist, a FileNotFoundException will be thrown.
  • If we try to write to a file that doesn’t exist, the file will be created first and no exception will be thrown.
  • It is very important to close the stream after using it, as it is not closed implicitly, to release any resources associated with it.
  • In output stream, the close() method calls flush() before releasing the resources, which forces any buffered bytes to be written to the stream.

Looking at the common usage practices, we can see, for example, that PrintWriter is used to write formatted text, FileOutputStream to write binary data, DataOutputStream to write primitive data types, RandomAccessFile to write to a specific position, and FileChannel to write faster in larger files. Some of the APIs of these classes do allow more, but this is a good place to start.

查看常见的使用实践,我们可以看到,例如,PrintWriter用于写入格式化的文本,FileOutputStream用于写入二进制数据,DataOutputStream用于写入原始数据类型,RandomAccessFile用于写入特定位置,以及FileChannel用于在较大的文件中快速写入。这些类的一些API确实允许更多,但这是一个好的开始。

12. Conclusion

12.结论

This article illustrated the many options of writing data to a file using Java.

这篇文章说明了使用Java将数据写入文件的许多选项。

The implementation of all these examples and code snippets can be found over on GitHub.

所有这些例子和代码片段的实现都可以在GitHub上找到over on GitHub