- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个程序在 XE2 中运行良好,但现在在 XE6 中失败。追踪问题并不是太困难。我使用内置的 zip 处理类创建 TZDecompressionStream 并将其提交给 TStreamReader。该代码旨在支持普通的未压缩文件和压缩文件,因此读者会指向一个“FileStream”变量,该变量要么是 TFileStream(可以工作),要么是 TZDecompressionStream(显示错误)
Reader := TStreamReader.Create(FileStream, TEncoding.ASCII);
问题在于,TStreamReader 在读取数据时会调用内部例程 AdjustEndOfBuffer,该例程会尝试确保缓冲区始终只包含完整的字符。不幸的是,下面的行会在必要时倒带流,但无论是否需要倒带都会被调用
FStream.Position := FStream.Position - Rewind;
在我的例子中,Rewind 的值为零,而 TZDecompressionStream 对此异常(exception)。显然,这是 TZDecompressionStream 中的一个错误,因为对当前位置的查找应该被评估为 OK,因为它是无操作。实际的 Seek 在 TStreamReader 中表示为移动到相对于流开头的当前偏移量。
TZDecompressionStream.Seek 中的实际代码允许返回开始(即倒回流)、向前移动经过当前位置并移动到结束,但特别不允许移动精确给出当前位置。以下代码判断是否允许继续
(((NativeUInt(offset) - FZStream.total_out) > 0) and (Origin = soBeginning))
但应该有一个 >= 如下
(((NativeUInt(offset) - FZStream.total_out) >= 0) and (Origin = soBeginning))
有谁知道解决这个错误的方法而不是简单地放弃 TStreamReader 吗?有没有办法修改 TzipFile 类为我创建的 TZDecompressionStream 的行为?
最佳答案
我已经提出了自己的答案,可以避免弄乱 VCL 源代码。这不是一件很好的事情,但它相当简短,并且避免了系统其他部分的任何困惑。我已经实现了一个 TsptZDecompressionStream 类,它覆盖了错误的 Seek,并且基本上对移动为零进行了无操作。我有一个类函数 Convert,它用新类的 VMT 指针替换 TZDecompressionStream 中的 VMT 指针。这应该是安全的,因为除了重写的方法之外,这些类在所有方面都是相同的。遇到同样问题的其他人应该能够简单地使用此代码并调用
TsptZDecompressionStream.Convert(Stream as TZDecompressionStream);
触发转换
声明
type
TsptZDecompressionStream = class(TZDecompressionStream)
class procedure Convert(DecompressionStream: TZDecompressionStream);
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
end;
实现
{ TsptZDecompressionStream }
class procedure TsptZDecompressionStream.Convert(DecompressionStream: TZDecompressionStream);
begin
// switch vmt pointer to point to TsptZDecompressionStream vmt
PPointer(DecompressionStream)^ := PPointer(TsptZDecompressionStream);
end;
function TsptZDecompressionStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
if (Origin = soBeginning) and (Offset = Position) then
begin
Result := Offset;
Exit;
end
else
begin
Result := inherited Seek(Offset, Origin);
end;
end;
除了破解内部数据格式的常见问题之外,我想不出任何理由说明这是一个特别糟糕的主意,但我欢迎进一步的评论。
请注意,该实现适用于 64 位 Seek,因为这是 TZDecompressionStream 实现的版本。 Delphi 现在指示所有流应实现 32 位版本(旧的查找方法签名)或 64 位版本。请记住,我的代码将无法与实现 32 位 Seek 的 TZDecompressionStream 的任何版本一起运行(我不知道它的历史是否足够早,足以实现这种情况)
关于delphi - 将 TStreamReader 与 TZDecompressionStream 结合使用时出现 EZDecompressionError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30176659/
我在 Delphi Tokyo 中编写了一个例程,它接受多个文件(例如 CSV)并将它们合并在一起,让用户可以选择忽略除第一个文件之外的所有文件的第一行(因为 CSV 文件通常有标题行)/列名称行,合
我正在使用 Embarcadero 的 Rad Studio Delphi (10.2.3),并且在读取非常大的文本文件(700 万行以上,每行都不同,行长度可以是 1 到 ~200 个字符等)时遇到
我在读取使用 Excel 2013 生成的普通 csv 文件时遇到问题。似乎编码在 TStreamReader 类中无法正常工作。奇怪的是,一个文件在工作,另一个文件不工作。读取第二个文件时,TStr
我在读取使用 Excel 2013 生成的普通 csv 文件时遇到问题。似乎编码在 TStreamReader 类中无法正常工作。奇怪的是,一个文件在工作,另一个文件不工作。读取第二个文件时,TStr
我有一个程序在 XE2 中运行良好,但现在在 XE6 中失败。追踪问题并不是太困难。我使用内置的 zip 处理类创建 TZDecompressionStream 并将其提交给 TStreamReade
我是一名优秀的程序员,十分优秀!