Java - 写入文件

1.概述

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

2.使用BufferedWriter编写

让我们开始简单 - 并使用BufferedWriterString 写入新文件

1

2

3

4

5

6

7

8

public void whenWriteStringUsingBufferedWritter_thenCorrect()

  throws IOException {

    String str = "Hello";

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

    writer.write(str);

     

    writer.close();

}

文件中的输出将是:

Hello

然后我们可以String附加到现有文件

1

2

3

4

5

6

7

8

9

10

@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();

}

该文件将是:

1

Hello World

3.使用PrintWriter写入

接下来 - 让我们看看如何使用PrintWriter将格式化文本写入文件:

1

2

3

4

5

6

7

8

9

@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();

}

生成的文件将包含:

1

2

Some String

Product name is iPhone and its price is 1000$

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

我们可以使用FileWriterBufferedWriter甚至System.out创建编写器

4.使用FileOutputStream写入

现在,让我们看看我们如何能够利用FileOutputStream中,以二进制数据写入一个文件。以下代码转换String int bytes并使用FileOutputStream将字节写入文件:

1

2

3

4

5

6

7

8

9

10

@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();

}

文件中的输出当然是:

1

Hello

5.使用DataOutputStream编写

接下来 - 让我们看一下如何使用DataOutputStream将String写入文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

@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.使用RandomAccessFile写入

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

RandomAccessFile使我们能够在给定偏移量的文件中的特定位置写入 - 从文件的开头 - 以字节为单位。以下代码写入一个整数值,其中包含从文件开头给出的偏移量:

1

2

3

4

5

6

7

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();

}

如果我们想要读取存储在特定位置的int,我们可以使用以下方法:

1

2

3

4

5

6

7

8

9

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;

}

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

1

2

3

4

5

6

7

8

9

10

11

12

@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.使用FileChannel写入

如果您正在处理大文件,FileChannel可能比标准IO更快。以下代码使用FileChannelString写入文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@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.使用Java 7写入文件

Java 7引入了一种使用文件系统的新方法,以及一个新的实用程序类 - Files。使用Files类,我们也可以创建,移动,复制,删除文件和目录; 它还可用于读取和写入文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

@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.写入临时文件

现在,让我们尝试写入临时文件。以下代码创建一个临时文件并将String写入其中:

1

2

3

4

5

6

7

8

9

10

11

12

@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();

}

因此,正如您所看到的 - 它只是创建了有趣且不同的临时文件 - 在此之后,写入文件是相同的。

10.写入前锁定文件

最后,在写入文件时,有时需要确保没有其他人同时写入该文件。基本上 - 您需要能够在写入时锁定该文件。

让我们使用FileChannel在写入之前尝试锁定文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@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();

}

请注意,如果在我们尝试获取锁时文件已被锁定,则将抛出OverlappingFileLockException

11.备注

在探索了很多写入文件的方法之后,让我们讨论一些重要的注意事项:

  • 如果我们尝试从不存在的文件中读取,则会抛出FileNotFoundException
  • 如果我们尝试写入不存在的文件,将首先创建该文件,不会抛出任何异常
  • 在使用它之后关闭流是非常重要的,因为它没有隐式关闭,以释放与之关联的任何资源
  • 在输出流中,close()方法在释放资源之前调用flush(),这会强制将任何缓冲的字节写入流中

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

12.结论

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

所有这些示例和代码片段的实现都可以在GitHub项目中找到 - 这是一个基于Maven的项目,因此它应该很容易导入和运行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值