M.kazem Akhgary M.kazem Akhgary - 3 years ago 184
C# Question

Why FileSavePicker is not replacing file?

when I used FileSavePicker to select (or create) storage file, if I select existing file, it will prompt for replace. when I press yes, I expect the file to be replaced later but it doesn't.

// existing file is picked, I pressed yes when replace was requested.
file = await picker.PickSaveFileAsync();


so with above code, existing file is picked by FileSavePicker, I expected that
file
is now replaced but its not.

await file.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.AllowOnlyReaders)


This will only open file for write, it does not replace it, but I want it to be replaced. my issue is same as this question, but I'm not writing text file, I'm writing binary data.

How can I replace
file
with new one?

Ive tried following but it throws NRE, because GetParentAsync is returning null.

var file = await (await file.GetParentAsync()).CreateFileAsync(file.Name,
CreationCollisionOption.ReplaceExisting);


I don't want user to explicitly create a new file by deleting old one and creating a new one. What I want is that if user selects existing file and accepts replace request from FileSavePicker, the file should be replaced.




Ok, here is code that you can test on your machine.

var picker = new FileSavePicker
{
SuggestedStartLocation = PickerLocationId.Desktop,
DefaultFileExtension = ".bin",
SuggestedFileName = "Binary file"
};
picker.FileTypeChoices.Add("Binary File", new List<string> {".bin"});

// in second run, choose existing file.
var file = await picker.PickSaveFileAsync();

using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite, StorageOpenOptions.AllowOnlyReaders))
{
using (var output = stream.GetOutputStreamAt(0))
{
using (var writer = new DataWriter(output))
{
writer.WriteBytes(Enumerable.Repeat<byte>(10, 10000).ToArray());
await writer.StoreAsync();
writer.DetachStream();
}
await output.FlushAsync();
}
}


Run this two times, in first run, create file. in second run select existing file, and also change
Repeat<byte>(10, 10000)
to something smaller and different, like
Repeat<byte>(80, 50)
and check content of file.

Answer Source

You can always SetLength of your opened stream to 0 first - which will clear all the old content and set stream's position to 0. Afterwards you can just write to the stream your new content:

var picker = new FileSavePicker
{
    SuggestedStartLocation = PickerLocationId.Desktop,
    DefaultFileExtension = ".bin",
    SuggestedFileName = "Binary file"
};
picker.FileTypeChoices.Add("Binary File", new List<string> { ".bin" });
var file = await picker.PickSaveFileAsync();

using (var stream = await file.OpenStreamForWriteAsync())
{
    stream.SetLength(0);
    var bytes = Encoding.ASCII.GetBytes("Content");
    await stream.WriteAsync(bytes, 0, bytes.Length);
    await stream.FlushAsync();
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download