9

I tried to overwrite a current file in UWP using FileSavePicker. I refered to this: https://msdn.microsoft.com/zh-cn/windows/uwp/files/quickstart-reading-and-writing-files But when I use a shorter file to overwrite a longer file, there comes a problem: the extra part of the old file(longer) isn't deleted, like this:

The old file:

abcdefg

And the file I want to save:

hij

But after saving operations, I get this:

hijdefg

My code is here:

        private async void Save_Click(object sender, RoutedEventArgs e)
    {
        XmlDocument Line = SaveToXml();

        //Save it
        FileSavePicker fileSaving = new FileSavePicker();
        fileSaving.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
        fileSaving.SuggestedFileName = "NewLine";
        fileSaving.FileTypeChoices.Add("Simple Line Files", new List<string>() { ".Line" });
        StorageFile file = await fileSaving.PickSaveFileAsync();

        if (file != null)
        {
            CachedFileManager.DeferUpdates(file);
            var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
            //var stream = await file.OpenStreamForWriteAsync();
            using (var outputStream = stream.GetOutputStreamAt(0))
            {
                using (var dataWriter = new Windows.Storage.Streams.DataWriter(outputStream))
                {
                    string xmlDoc = Line.OuterXml;
                    Debug.WriteLine(Line.OuterXml);
                    dataWriter.WriteString(xmlDoc);
                    await dataWriter.StoreAsync();
                    await outputStream.FlushAsync();
                }
            }
            stream.Dispose();
        }
    }

Thanks for helping me!

huangbiubiu
  • 1,252
  • 20
  • 37
  • 1
    Seems to be a normal behavior. If you want to overwrite file with completely new data, why not just to create file with *ReplaceExisting* option instead of opening an old one? – Romasz Mar 07 '16 at 11:23
  • 2
    Wrong method, you want to Create instead of Open. – Hans Passant Mar 07 '16 at 11:25

4 Answers4

10

You can also call Stream.SetLength(0) immediately after opening the stream to clear it before you start writing.

var streamToWrite = await file.OpenStreamForWriteAsync().ConfigureAwait(false);
streamToWrite.SetLength(0);
using (var streamWriter = new StreamWriter(streamToWrite))
{
    streamWriter.Write(data);
    streamWriter.Flush();                        
}
Tim Greenfield
  • 567
  • 5
  • 9
1

Your code var outputStream = stream.GetOutputStreamAt(0) returns an output stream at the begin location in your file stream. Now when you write to the file, it will replace the file from the location you set. When the new string you want to write is less than the old string in the file, it can not replace all the old string. So using this method, you can't ensure that every letters can be replaced in the old file.

You can use FileIO.WriteTextAsync(IStorageFile, String) method to write text to the specified file. It can overwrite the old file.

For example:

private async void Save_Click(object sender, RoutedEventArgs e)
{
    FileSavePicker savePicker = new FileSavePicker();
    savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
    savePicker.FileTypeChoices.Add("Simple Line Files", new List<string>() { ".line" });
    savePicker.SuggestedFileName = "NewLine";
    StorageFile file = await savePicker.PickSaveFileAsync();
    if (file != null)
    {
        CachedFileManager.DeferUpdates(file);
        await FileIO.WriteTextAsync(file, "hello");
        FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
    }
}
Jayden
  • 3,276
  • 1
  • 10
  • 14
0

Before calling OpenStreamForWriteAsync() use FileIO.WriteBytesAsync and write a zero byte array. This will clear the file.

public async Task<Stream> ClearAndGetStream(StorageFile storageFile)
{
    await FileIO.WriteBytesAsync(storageFile, new byte[0]);
    return await storageFile.OpenStreamForWriteAsync();
}
0

While still using DataWriter, there is a solution. I had the same exact problem as you and solved it by doing this.

Replace:

await dataWriter.StoreAsync();

With:

stream.size = await dataWriter.StoreAsync();