Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Quando si apre un oggetto Package con System.IO.FileAccess.ReadWrite?displayProperty=nameWithType> e quindi si apre una parte compressa per la lettura che non è stata modificata nella sessione corrente, PackagePart.GetStream ora restituisce un flusso forward-only anziché un oggetto seekableMemoryStream<.
Versione introdotta
.NET 11 Preview 7
Comportamento precedente
In precedenza, quando si apre un Package oggetto con FileAccess.ReadWrite (che esegue il mapping internamente a ZipArchiveMode.Update), l'apertura di una parte compressa per la lettura ha restituito un elemento ricercabile MemoryStream che conteneva il contenuto della voce completamente decompresso.
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
Nuovo comportamento
A partire da .NET 11, la stessa chiamata restituisce un flusso forward-only (non ricercabile) per parti compresse che non sono state modificate nella sessione corrente.
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)
Per osservare questa modifica, è necessario che tutte le condizioni seguenti siano vere contemporaneamente:
- Il pacchetto viene aperto con
FileAccess.ReadWrite(Package.Open(..., FileAccess.ReadWrite)). - La parte viene aperta solo per la lettura (
GetStream(FileMode.Open, FileAccess.Read)). - La parte è compressa (
CompressionOptiondiversa daNotCompressed). - La parte non è stata scritta o modificata in precedenza nella stessa sessione.
- Il consumer cerca in modo incondizionato il flusso o legge
Position.
Gli scenari seguenti non sono interessati:
- Pacchetti di sola lettura (
FileAccess.Read): i flussi di parti compressi erano già forward-only. - Parti non compresse (
Stored): rimangono ricercabili. - Parti modificate in precedenza nella sessione corrente: vengono gestite da uno snapshot in memoria, in modo che rimangano ricercabili.
- Accesso a
Stream.Length. - Consumer forward-only (caso comune, ad esempio
XmlReader, ,XDocument.Load, Open XML SDK eCopyTo). - Framework di destinazione precedenti a .NET 11: l'ottimizzazione viene controllata dietro
NET11_0_OR_GREATER.
Tipo di cambiamento che interrompe la compatibilità
Questa modifica è una modifica funzionale.
Motivo della modifica
In precedenza, l'apertura di una parte compressa per la lettura da un ReadWrite pacchetto decomprimeva sempre l'intera voce in un MemoryStream oggetto prima di restituire il flusso. Questo approccio ha prodotto un flusso ricercabile, ma ha imposto allocazioni di memoria non necessarie e sovraccarico della CPU per il caso comune in cui i chiamanti leggono il flusso in sequenza (ad esempio, XmlReader o Open XML SDK). Il nuovo comportamento viene trasmesso direttamente dalla voce di archivio ZIP sottostante per le letture forward-only, evitando così la decompressione iniziale.
Per altre informazioni, vedere dotnet/runtime#129698.
Azione consigliata
Se il codice richiede un flusso ricercabile da una parte compressa di un ReadWrite pacchetto, copiarlo manualmente: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.
In alternativa, se il caso d'uso non richiede ReadWrite l'accesso al pacchetto, aprirlo con FileAccess.Read . I pacchetti di sola lettura hanno già restituito flussi forward-only prima di questa modifica, quindi questa modalità evita eventuali sorprese per il codice sensibile alla ricerca.