繁体   English   中英

以追加模式打开文件但如果在 JAVA 11 中不为空则截断文件

[英]Opening a file in append mode but truncating the file if not empty in JAVA 11

如果它不存在,我想创建一个 result.csv 文件,然后我多次调用write并通过调用附加相应的消息。

但是如果文件在程序运行之前已经存在并且包含一些东西,我想删除它的内容,然后开始附加相应的消息。

我尝试了以下方法:

public final class Writer {
    public static void write(String message, String destinationPath) {
        try (FileWriter fw = new FileWriter(destinationPath, true);
             BufferedWriter bw = new BufferedWriter(fw)
        ) {
            bw.write(message);
            bw.newLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

但是,正如您可能猜到的那样,当我一遍又一遍地运行程序时,它只是在现有行上添加新行,而不是在程序运行之前擦除里面的内容。

write的调用是这样完成的:

studentNamesAndIds.values().forEach(id -> Writer.write(id+","+ DecideGrade.softLookUp(id, studentIdsAndGrades),writeFilePath));

我应该改变什么才能得到我一开始提到的结果?

PS 如果我在没有第二个参数的情况下声明new FileWriter(destinationPath)true ,那么每次调用write都会删除我文件的内容,我会删除里面的最后一行。

这段代码应该根据您对问题的描述来完成这项工作:

public final class Writer 
{
  private static final Set<String> m_AppendMarkers = new HashMap<>();

  public static void write( final String message, final String destinationPath ) 
  {
    final var append = m_AppendMarkers.contains( destinationPath );
    try( final var fw = new FileWriter( destinationPath, append );
      final var bw = new BufferedWriter( fw ) )
    {
      bw.write( message );
      bw.newLine();
      m_AppendMarkers.add( destinationPath );
    } 
    catch( final IOException e ) 
    {
      e.printStackTrace();
    }
  }
}

每次重新启动程序时,集合都是空的,因此Set::contains将在第一次尝试写入给定文件时返回false 为了进一步尝试,文件的路径已添加到集合中,包含检查将为您提供true ,因此将附加更多行。

但老实说,虽然这可行,但您应该考虑不同的设计! 因此,为您写入的每一行新行打开和关闭文件并不是一个好主意。

使用静态方法也不是好的设计(这就是为什么需要Set而不是简单的boolean标志的原因)。

要做到正确(或至少更好一点)试试这个:

public class YourProgram
{
  private static class Writer implements AutoClosable
  {
    private final String m_DestinationPath;
    private final StringJoiner m_Buffer ) = new StringJoiner( "\n", "", "\n" );

    public Writer( final String destinationPath )
    {
      m_DestinationPath = destinationPath;
    }

    @Overwrite
    public final void close() throws IOException
    {
      try( final var writer = new BufferedWriter( new FileWriter( m_DestinationPath, false ) ) )
      {
        writer.write( m_Buffer.toString() );
      }
    } 

    public static void write( final String message )
    {
      m_Buffer.add( message );
    }
  }
  //  class Writer

  private static Writer m_Writer;

  public static final void main( final String... args )
  {
    try( var w = new Writer( "TheNameOfYourOutputFile" ) )
    {
      m_Writer = w;

      // Your code goes here …
      …
    }
    catch( final IOException e )
    {
      err.println( "Failed to write the output file" );
      e.printStackTrace( err );
    }
    catch( final Throwable t )
    {
      err.println( "Unhandled exception" );
      t.printStackTrace( err );
    }
  }
}
// class YourProgram

省略了错误处理以保持可读性。

只要您不尝试写入几千兆字节的数据,这应该比其他设计更顺畅。 好的,它不是崩溃保存,如果程序将被外部终止,则不会将任何内容写入输出文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM