2017-09-30 6 views
1

lorsque j'ai utilisé FileSavePicker pour sélectionner (ou créer) un fichier de stockage, si je sélectionne un fichier existant, il demandera le remplacement. quand j'appuie sur oui, je m'attends à ce que le fichier soit remplacé plus tard mais ce n'est pas le cas.Pourquoi FileSavePicker ne remplace pas le fichier?

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

donc avec le code ci-dessus, le fichier existant est choisi par FileSavePicker, je m'y attendais file est maintenant remplacé, mais ce ne est pas.

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

Ceci ouvrira seulement le fichier pour l'écrire, il ne le remplacera pas, mais je veux qu'il soit remplacé. mon problème est le même que this question, mais je n'écris pas de fichier texte, j'écris des données binaires.

Comment remplacer file par un neuf? J'ai essayé de suivre mais il renvoie NRE, car GetParentAsync renvoie null. Retour au début |

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

Je ne veux pas que l'utilisateur crée explicitement un nouveau fichier en supprimant l'ancien et en en créant un nouveau. Ce que je veux, c'est que si l'utilisateur sélectionne un fichier existant et accepte la demande de remplacement de FileSavePicker, le fichier doit être remplacé.


Ok, voici le code que vous pouvez tester sur votre 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(); 
    } 
} 

Exécutez cette opération deux fois, lors de la première exécution, créez un fichier. dans la deuxième exécution, sélectionnez le fichier existant, et changez également Repeat<byte>(10, 10000) pour quelque chose de plus petit et différent, comme Repeat<byte>(80, 50) et vérifiez le contenu du fichier.

+0

FileSavePicker fait pas remplacer les fichiers, il vous fournit simplement un nom. Ce que vous faites * suivant * avec ce nom est important. Les opérations de fichiers dans WinRT sont transactionnelles, vous ne pouvez pas écraser accidentellement un fichier. Ce n'est que lorsque le fichier est correctement fermé qu'il remplacera un fichier existant. Le code le plus important est donc absent des extraits. –

+0

à droite, comment puis-je créer un fichier avec StorageFile qu'il me donne? (alors FileSavePicker ment quand il demande "remplacer par existant") @HansPassant –

+0

Je n'ai aucune idée de ce que vous dites. Code postal que les utilisateurs SO peuvent effectivement exécuter eux-mêmes pour vérifier vos revendications. –

Répondre

1

Vous pouvez toujours SetLength de votre flux ouvert à 0 premier - qui effacera tout l'ancien contenu et la position de flux à 0. Ensuite, vous pouvez simplement écrire dans le flux de votre nouveau contenu:

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(); 
} 
+0

Génial, je me demande pourquoi cela n'a pas encore posé problème à qui que ce soit? il m'a fallu un jour pour réaliser que mon application fonctionne sans bug mais c'est l'ancien contenu qui gâche le lecteur de données. –

+0

Je pourrais aussi SetLength à la fin de l'écriture, 'SetLength (bytesWritten)' de sorte que dans le cas où l'auteur rencontre un problème, les anciennes données ne seront pas perdues. –

+0

@ M.kazemAkhgary Oui, * SetLength * tronquera ou développera le flux si nécessaire. – Romasz