用Java创建和写入(文本)文件的最简单方法是什么?


当前回答

您甚至可以使用系统属性创建临时文件,该属性与您使用的操作系统无关。

File file = new File(System.*getProperty*("java.io.tmpdir") +
                     System.*getProperty*("file.separator") +
                     "YourFileName.txt");

其他回答

请注意,下面的每个代码示例都可能引发IOException。为了简洁起见,省略了Try/catch/finally块。有关异常处理的信息,请参阅本教程。

请注意,如果文件已经存在,下面的每个代码示例都将覆盖该文件

创建文本文件:

PrintWriter writer = new PrintWriter("the-file-name.txt", "UTF-8");
writer.println("The first line");
writer.println("The second line");
writer.close();

创建二进制文件:

byte data[] = ...
FileOutputStream out = new FileOutputStream("the-file-name");
out.write(data);
out.close();

Java 7+用户可以使用Files类写入文件:

创建文本文件:

List<String> lines = Arrays.asList("The first line", "The second line");
Path file = Paths.get("the-file-name.txt");
Files.write(file, lines, StandardCharsets.UTF_8);
//Files.write(file, lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);

创建二进制文件:

byte data[] = ...
Path file = Paths.get("the-file-name");
Files.write(file, data);
//Files.write(file, data, StandardOpenOption.APPEND);

有许多方法可以写入文件。每种方法都有其优点,而且在给定的场景中,每种方法可能都是最简单的。

这个答案以Java 8为中心,并试图涵盖Java专业考试所需的所有细节。涉及的课程包括:

.
├── OutputStream
│   └── FileOutputStream
├── Writer
│   ├── OutputStreamWriter
│   │   └── FileWriter
│   ├── BufferedWriter
│   └── PrintWriter (Java 5+)
└── Files (Java 7+)

写入文件有5种主要方式:

┌───────────────────────────┬────────────────────────┬─────────────┬──────────────┐
│                           │       Buffer for       │ Can specify │   Throws     │
│                           │      large files?      │  encoding?  │ IOException? │
├───────────────────────────┼────────────────────────┼─────────────┼──────────────┤
│ OutputStreamWriter        │ Wrap in BufferedWriter │ Y           │ Y            │
│ FileWriter                │ Wrap in BufferedWriter │             │ Y            │
│ PrintWriter               │ Y                      │ Y           │              │
│ Files.write()             │                        │ Y           │ Y            │
│ Files.newBufferedWriter() │ Y                      │ Y           │ Y            │
└───────────────────────────┴────────────────────────┴─────────────┴──────────────┘

每个都有其独特的优势:

OutputStreamWriter-Java 5之前最基本的方法FileWriter–可选附加构造函数参数PrintWriter–多种方法Files.write()–在一次调用中创建并写入文件Files.newBufferedWriter()–便于编写大型文件

以下是每一项的详细信息。

文件输出流

此类用于写入原始字节流。下面的所有Writer方法都依赖于这个类,无论是显式的还是隐藏式的。

try (FileOutputStream stream = new FileOutputStream("file.txt");) {
    byte data[] = "foo".getBytes();
    stream.write(data);
} catch (IOException e) {}

注意,trywithresources语句负责stream.close(),关闭流会刷新它,就像stream.flush()一样。

输出StreamWriter

此类是从字符流到字节流的桥梁。它可以包装FileOutputStream,并写入字符串:

Charset utf8 = StandardCharsets.UTF_8;
try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File("file.txt")), utf8)) {
    writer.write("foo");
} catch (IOException e) {}

缓冲写入程序

此类将文本写入字符输出流,缓冲字符,以便有效地写入单个字符、数组和字符串。

它可以包装OutputStreamWriter:

try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("file.txt"))))) {
    writer.write("foo");
    writer.newLine();  // method provided by BufferedWriter
} catch (IOException e) {}

在Java5之前,这是处理大型文件的最佳方法(具有常规的try/catch块)。

字符输出流

这是OutputStreamWriter的子类,是编写字符文件的便利类:

boolean append = false;
try(FileWriter writer = new FileWriter("file.txt", append) ){
    writer.write("foo");
    writer.append("bar");
} catch (IOException e) {}

关键的好处是它有一个可选的附加构造函数参数,该参数决定它是附加到现有文件还是覆盖现有文件。注意,append/overwrite行为不受write()和append()方法的控制,它们的行为方式几乎相同。

注意:

没有缓冲,但为了处理大型文件,可以将其包装在BufferedWriter中。FileWriter使用默认编码。通常最好明确指定编码

字符打印流

此类将对象的格式化表示打印到文本输出流。实际上,它与上面的BufferedWriter方法(新的BufferedWriter(新的OutputStreamWriter(新的FileOutputStream(…)))相同。PrintWriter是在Java5中引入的,作为调用此习惯用法的方便方法,并添加了printf()和println()等其他方法。

此类中的方法不会引发I/O异常。您可以通过调用checkError()来检查错误。PrintWriter实例的目标可以是File、OutputStream或Writer。以下是写入文件的示例:

try (PrintWriter writer = new PrintWriter("file.txt", "UTF-8")) {
    writer.print("foo");
    writer.printf("bar %d $", "a", 1);
    writer.println("baz");
} catch (FileNotFoundException e) {
} catch (UnsupportedEncodingException e) {}

当写入OutputStream或Writer时,有一个可选的autoFlush构造函数参数,默认为false。与FileWriter不同,它将覆盖任何现有文件。

文件.write()

Java7引入了Java.nio.file.Files.Files.write(),它允许您在一次调用中创建和写入文件。

@icza的答案显示了如何使用这种方法。几个例子:

Charset utf8 = StandardCharsets.UTF_8;
List<String> lines = Arrays.asList("foo", "bar");

try {
    Files.write(Paths.get("file.txt"), "foo".getBytes(utf8));
    Files.write(Paths.get("file2.txt"), lines, utf8);
} catch (IOException e) {}

这不涉及缓冲区,因此不适用于大型文件。

文件.newBufferedWriter()

Java 7还引入了Files.newBufferedWriter(),这使得获取BufferedWriter变得容易:

Charset utf8 = StandardCharsets.UTF_8;
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("file.txt"), utf8)) {
    writer.write("foo");
} catch (IOException e) {}

这与PrintWriter类似,缺点是没有PrintWriter的方法,好处是它不会吞下异常。

Use:

JFileChooser c = new JFileChooser();
c.showOpenDialog(c);
File writeFile = c.getSelectedFile();
String content = "Input the data here to be written to your file";

try {
    FileWriter fw = new FileWriter(writeFile);
    BufferedWriter bw = new BufferedWriter(fw);
    bw.append(content);
    bw.append("hiiiii");
    bw.close();
    fw.close();
}
catch (Exception exc) {
   System.out.println(exc);
}

如果出于某种原因想要将创建和编写行为分开,那么Java中的touch等价物是

try {
   //create a file named "testfile.txt" in the current working directory
   File myFile = new File("testfile.txt");
   if ( myFile.createNewFile() ) {
      System.out.println("Success!");
   } else {
      System.out.println("Failure!");
   }
} catch ( IOException ioe ) { ioe.printStackTrace(); }

createNewFile()执行存在性检查,并自动创建文件。例如,如果您希望在写入文件之前确保自己是文件的创建者,这可能很有用。

由于作者没有说明他们是否需要针对已经EoL的Java版本的解决方案(Sun和IBM都提供了,从技术上讲,这些版本是最广泛的JVM),并且由于大多数人似乎在作者的问题被指定为文本(非二进制)文件之前就已经回答了这个问题,所以我决定提供我的答案。


首先,Java 6通常已经到了生命的尽头,由于作者没有指定他需要遗留兼容性,我想这自动意味着Java 7或更高版本(Java 7尚未被IBM EoL)。因此,我们可以看看文件I/O教程:https://docs.oracle.com/javase/tutorial/essential/io/legacy.html

在Java SE 7发布之前,Java.io.File类是用于文件I/O的机制,但它有几个缺点。许多方法在失败时不会抛出异常,所以无法获得有用的错误消息。例如,如果文件删除失败,程序将收到“删除失败”,但不知道是否是因为文件不存在,用户不存在具有权限,或者存在其他问题。重命名方法跨平台工作不一致。没有真正的支持用于符号链接。需要对元数据提供更多支持,例如文件权限、文件所有者和其他安全属性。访问文件元数据效率低下。许多File方法都无法扩展。通过服务器请求大型目录列表可能会导致悬挂大目录还可能导致内存资源问题,导致拒绝服务。无法写入可以递归遍历文件树并做出响应的可靠代码如果存在循环符号链接,则可以适当。

哦,好吧,这排除了java.io.File。如果无法写入/附加文件,您可能甚至无法知道原因。


我们可以继续查看教程:https://docs.oracle.com/javase/tutorial/essential/io/file.html#common

如果您有所有要提前写入(附加)到文本文件的行,建议的方法是https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#write-java.nio.file.Path java.lang.Iterable-java.nio.charset.charset java.nio.file OpenOption-

下面是一个示例(简化):

Path file = ...;
List<String> linesInMemory = ...;
Files.write(file, linesInMemory, StandardCharsets.UTF_8);

另一个示例(附加):

Path file = ...;
List<String> linesInMemory = ...;
Files.write(file, linesInMemory, Charset.forName("desired charset"), StandardOpenOption.CREATE, StandardOpenOption.APPEND, StandardOpenOption.WRITE);

如果您想按原样写入文件内容:https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#newBufferedWriter-java.nio.file.Path java.nio.charset.charset java.nio.file OpenOption-

简化示例(Java 8或更高版本):

Path file = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file)) {
    writer.append("Zero header: ").append('0').write("\r\n");
    [...]
}

另一个示例(附加):

Path file = ...;
try (BufferedWriter writer = Files.newBufferedWriter(file, Charset.forName("desired charset"), StandardOpenOption.CREATE, StandardOpenOption.APPEND, StandardOpenOption.WRITE)) {
    writer.write("----------");
    [...]
}

这些方法需要作者尽可能少的努力,并且在写入[文本]文件时应优先于其他所有方法。