0

I am using a third-party library to convert a document into a PDF. The output file name will be arbitrary -- provided by the client. If a file with that name already exists, my code will modify the file name in a fashion similar to the way MS Windows does, e.g. "myname.txt" becomes "myname (1).txt". I would like to reserve the output file name somehow so that my code is not only thread-safe but also "process safe", meaning that another application's process won't create the file after my code has determined the unique file name it wants to use but before it actually creates the file.

The usual or simple approach, it would seem, is to make use of exception handling and a loop structure when writing the file to create a unique file name when the previous write attempt failed because a file with that name already exists. However, since the third-party implementation for writing the file undoubtedly has side effects which I don't want to incur multiple times in my loop, I would like to find a way to guarantee that the file name will be available the first time I call the third-party code to write the file.

Is there a way to do this?

rory.ap
  • 34,009
  • 10
  • 83
  • 174
  • Dupe? http://stackoverflow.com/questions/581570/how-can-i-create-a-temp-file-with-a-specific-extension-with-net – Marc B Nov 21 '14 at 16:08
  • @MarcB -- No, because the file name can be anything, not a GUID. That is provided by the code that calls my code. I just want to make a file write that uses the provided file name, if available, and only calls the third-party write once. – rory.ap Nov 21 '14 at 16:20
  • Why does the linked question not answer this? It shows you how to make the write succeed, simply by using a name that is guaranteed not to be taken. – usr Nov 21 '14 at 16:31
  • So create a unique filename as per the linked question. You can then serve up that file using any name you want, regardless of what's on-disk. – Marc B Nov 21 '14 at 16:35
  • @MarcB -- because the code returns a `System.IO.FileInfo` pointing to the file on disk. I'm not serving it anywhere, the client using my code will receive the `FileInfo` and do with it what they please. – rory.ap Nov 21 '14 at 16:41
  • @usr -- I understand what the linked question shows. It doesn't answer this because my code receives an arbitrary file name from the client, writes the file using that name, and returns the `System.IO.FileInfo`. If the file exists, it should will modify the provided file name slightly (like MS Windows does, e.g. "Test.txt" becomes "Test (1).txt") and write to that instead. I'd like to do this, as I said, in a thread and process-safe manner. – rory.ap Nov 21 '14 at 16:44
  • Then you are doing it wrong, nothing is going to prevent that file from getting overwritten. You'll need to return a stream so you can keep the file locked with FileShare.None – Hans Passant Nov 21 '14 at 16:46
  • @HansPassant -- I'm not trying to guarantee that the file doesn't get overwritten after I create it. That might be an acceptable or desired behavior. I'm only trying to guarantee that I can write the file to begin with without having to call the third-party code more than once and without letting an exception bubble up to the client. – rory.ap Nov 21 '14 at 16:49
  • Then what on Earth is "How to reserve a file name" supposed to mean? – Hans Passant Nov 21 '14 at 16:51
  • @HansPassant -- Okay for the overly-pedantic: it's a succinct way of saying "how to reserve a file name during the life of a method call within which the file name is needed so that it can be used without incurring unnecessary side effects and without resulting in an unhanded exception". Why "on Earth" is it so hard to ask a question on Stack Overflow?! Bottom line: I have a question and need guidance. I try my very best to ask it correctly, but there's always the rush of dogmatists waiting to assert their knowledge and make people look stupid. – rory.ap Nov 21 '14 at 17:01
  • Thanks for the compliment. – Hans Passant Nov 21 '14 at 17:04

1 Answers1

1

Write the PDF to a temporary file that is guaranteed no to be taken (e.g. using Guid.NewGuid()). Then, rename the file to the desired file name. This rename is atomic. If it fails you can decide what to do. The PDF component only needs to be called once. The rename can be executed multiple times, possibly with different target names.

usr
  • 168,620
  • 35
  • 240
  • 369