Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Quando abres um Package com System.IO.FileAccess.ReadWrite?displayProperty=nameWithType> e depois abres uma parte comprimida para leitura que não foi modificada na sessão atual, PackagePart.GetStream agora retorna um fluxo apenas avançado em vez de um objeto de busca MemoryStream<.
Versão introduzida
.NET 11 Pré-visualização 7
Comportamento anterior
Anteriormente, quando se abria um Package com FileAccess.ReadWrite (que mapeia internamente para ZipArchiveMode.Update), abrir uma parte comprimida para leitura devolveu um objeto MemoryStream de busca que continha o conteúdo da entrada totalmente descomprimido.
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
Novo comportamento
A partir do .NET 11, a mesma chamada devolve um fluxo apenas encaminhado (não procurável) para partes comprimidas que não foram modificadas na sessão atual.
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)
Todas as seguintes condições devem ser verdadeiras simultaneamente para que possa observar esta mudança:
- O pacote é aberto com
FileAccess.ReadWrite(Package.Open(..., FileAccess.ReadWrite)). - A parte está aberta apenas para leitura (
GetStream(FileMode.Open, FileAccess.Read)). - A peça é comprimida (
CompressionOptionexcetoNotCompressed). - A parte não foi escrita nem modificada anteriormente na mesma sessão.
- O consumidor procura incondicionalmente o fluxo ou lê
Position.
Os seguintes cenários não são afetados:
- Pacotes de apenas leitura (
FileAccess.Read): Os seus fluxos de peças comprimidos já eram apenas para avançar. - Peças não comprimidas (
Stored): Permanecem procuráveis. - Partes modificadas mais cedo na sessão atual: São servidas a partir de um instantâneo em memória, por isso permanecem procuráveis.
- Aceder
Stream.Lengtha . - Consumidores apenas forward-only (o caso comum, como
XmlReader,XDocument.Load, o SDK Open XML, eCopyTo). - Frameworks alvo anteriores ao .NET 11: A otimização está bloqueada por
NET11_0_OR_GREATERtrás de .
Tipo de mudança disruptiva
Esta mudança é uma mudança comportamental.
Motivo da mudança
Anteriormente, abrir uma parte comprimida para ler de um ReadWrite pacote descomprimia sempre toda a entrada em a MemoryStream antes de devolver o fluxo. Esta abordagem produziu um fluxo procurável, mas impunha alocações desnecessárias de memória e sobrecarga de CPU para o caso comum em que os chamadores apenas leem o fluxo sequencialmente (por exemplo, XmlReader ou o Open XML SDK). O novo comportamento é transmitido diretamente da entrada subjacente do arquivo ZIP para leituras apenas diretas, o que evita a descompressão inicial.
Para mais informações, consulte dotnet/runtime#129698.
Ação recomendada
Se o seu código requer um fluxo procurável de uma parte comprimida de um ReadWrite pacote, copie-o 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.
Alternativamente, se o seu caso de uso não exigir ReadWrite acesso ao pacote, abre-o em vez disso.FileAccess.Read Os pacotes apenas de leitura já devolvevam fluxos apenas avançados antes desta alteração, pelo que este modo evita surpresas para código sensível à procura.