Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Lorsque vous ouvrez un élément avec System.IO.FileAccess.ReadWrite ?displayProperty=nameWithType>, puis ouvrez une partie compressée pour la lecture qui n’a pas été modifiée dans la session active, PackagePart.GetStream retourne maintenant un flux de transfert uniquement au lieu d’un flux pouvant être recherchéMemoryStream.<Package
Version introduite
.NET 11 Preview 7
Comportement antérieur
Auparavant, lorsque vous ouvrez un Package avec FileAccess.ReadWrite (qui est mappé en interne à ZipArchiveMode.Update), l’ouverture d’une partie compressée pour la lecture a retourné une recherche MemoryStream qui contenait le contenu d’entrée entièrement compressé.
using Package package = Package.Open("file.docx", FileMode.Open, FileAccess.ReadWrite);
PackagePart part = package.GetPart(new Uri("/word/document.xml", UriKind.Relative));
// Returned a seekable MemoryStream.
using Stream stream = part.GetStream(FileMode.Open, FileAccess.Read);
Console.WriteLine(stream.CanSeek); // true
stream.Seek(0, SeekOrigin.Begin); // succeeded
Console.WriteLine(stream.Position); // 0
Nouveau comportement
À compter de .NET 11, le même appel retourne un flux de transfert uniquement (non recherché) pour les parties compressées qui n'ont pas été modifiées dans la session active.
using Package package = Package.Open("file.docx", FileMode.Open, FileAccess.ReadWrite);
PackagePart part = package.GetPart(new Uri("/word/document.xml", UriKind.Relative));
// Returns a forward-only (non-seekable) stream.
using Stream stream = part.GetStream(FileMode.Open, FileAccess.Read);
Console.WriteLine(stream.CanSeek); // false
stream.Seek(0, SeekOrigin.Begin); // throws NotSupportedException
stream.Position = 0; // throws NotSupportedException
Console.WriteLine(stream.Length); // still works (reported from entry metadata)
Toutes les conditions suivantes doivent être remplies simultanément pour que vous observiez cette modification :
- Le package est ouvert avec
FileAccess.ReadWrite(Package.Open(..., FileAccess.ReadWrite)). - La partie est ouverte uniquement pour la lecture (
GetStream(FileMode.Open, FileAccess.Read)). - La partie est compressée (
CompressionOptionautre queNotCompressed). - La partie n’a pas été écrite ou modifiée plus tôt dans la même session.
- Le consommateur cherche inconditionnellement le flux ou les
Positionlectures .
Les scénarios suivants ne sont pas affectés :
- Packages en lecture seule (
FileAccess.Read) : leurs flux de parties compressées étaient déjà transférés uniquement. - Parties non compressées
Stored: elles restent recherchés. - Parties modifiées précédemment dans la session active : elles sont servies à partir d’un instantané en mémoire, de sorte qu’elles restent recherchés.
- Accès
Stream.Length. - Consommateurs transférés uniquement (cas courant, tels que
XmlReader,XDocument.Load, le Kit de développement logiciel (SDK) Open XML etCopyTo). - Infrastructures cibles antérieures à .NET 11 : l’optimisation est contrôlée derrière
NET11_0_OR_GREATER.
Type de changement cassant
Ce changement est un changement de comportement.
Raison du changement
Auparavant, l’ouverture d’une partie compressée pour la lecture à partir d’un ReadWrite package a toujours décompressé l’entrée entière dans une MemoryStream entrée avant de renvoyer le flux. Cette approche a produit un flux recherché, mais il a imposé des allocations de mémoire inutiles et une surcharge processeur pour le cas courant où les appelants lisent uniquement le flux séquentiellement (par exemple, XmlReader ou le Kit de développement logiciel (SDK) Open XML). Le nouveau comportement flux directement à partir de l’entrée d’archive ZIP sous-jacente pour les lectures en avant uniquement, ce qui évite la décompression frontale.
Pour plus d’informations, consultez dotnet/runtime#129698.
Action recommandée
Si votre code nécessite un flux recherché à partir d’une partie compressée d’un ReadWrite package, copiez-le manuellement MemoryStream :
using Stream partStream = part.GetStream(FileMode.Open, FileAccess.Read);
using MemoryStream seekable = new();
partStream.CopyTo(seekable);
seekable.Position = 0;
// Use 'seekable'. It's fully buffered and seekable.
Sinon, si votre cas d’usage ne nécessite ReadWrite pas d’accès au package, ouvrez-le à FileAccess.Read la place. Les packages en lecture seule ont déjà retourné des flux avant cette modification. Ce mode évite donc toute surprise pour le code sensible à la recherche.