Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Quando você abre um Package com <System.IO.FileAccess.ReadWrite?displayProperty=nameWithType> e, em seguida, abre uma parte compactada para leitura que não foi modificada na sessão atual, PackagePart.GetStream agora retorna um fluxo somente de encaminhamento em vez de um buscavel MemoryStream.
Versão introduzida
.NET 11 Versão Prévia 7
Comportamento anterior
Anteriormente, quando você abriu um Package com FileAccess.ReadWrite (que é mapeado internamente para ZipArchiveMode.Update), abrir uma parte compactada para leitura retornou uma busca MemoryStream que continha o conteúdo de entrada totalmente descompactado.
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 retorna um fluxo somente de encaminhamento (não pesquisável) para partes compactadas 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 você observe essa alteração:
- O pacote é aberto com
FileAccess.ReadWrite(Package.Open(..., FileAccess.ReadWrite)). - A parte é aberta somente para leitura (
GetStream(FileMode.Open, FileAccess.Read)). - A parte é compactada (
CompressionOptiondiferente deNotCompressed). - A parte não foi escrita ou 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 somente leitura (
FileAccess.Read): seus fluxos de partes compactadas já eram somente para encaminhamento. - Partes não compactadas (
Stored): elas permanecem buscadas. - Partes modificadas anteriormente na sessão atual: elas são atendidas a partir de um instantâneo na memória, para que permaneçam buscadas.
- Acessando
Stream.Length. - Consumidores somente encaminhamento (o caso comum, como
XmlReader,XDocument.Loado SDK do Open XML eCopyTo). - Estruturas de destino anteriores a .NET 11: a otimização é fechada atrás
NET11_0_OR_GREATER.
Tipo de mudança disruptiva
Esta é uma alteração comportamental.
Motivo da alteração
Anteriormente, abrir uma parte compactada para leitura de um ReadWrite pacote sempre descompactou toda a entrada em um MemoryStream antes de retornar o fluxo. Essa abordagem produziu um fluxo pesquisável, mas impôs alocações de memória desnecessárias e sobrecarga de CPU para o caso comum em que os chamadores só leem o fluxo sequencialmente (por exemplo, XmlReader ou o SDK do Open XML). O novo comportamento é transmitido diretamente da entrada de arquivo ZIP subjacente para leituras somente de encaminhamento, o que evita a descompactação inicial.
Para obter mais informações, consulte dotnet/runtime#129698.
Ação recomendada
Se o código exigir um fluxo buscavel de uma parte compactada 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.
Como alternativa, se o caso de uso não exigir ReadWrite acesso ao pacote, abra-o em FileAccess.Read vez disso. Os pacotes somente leitura já retornavam fluxos somente de encaminhamento antes dessa alteração, portanto, esse modo evita qualquer surpresa para código sensível à busca.