注意:
整个问题都基于错误的前提,即您可以通过合并两个PDF文件的二进制文件来生成一个合并后的PDF文件。这对于纯文本文件(在某种程度上)可能有效,但绝对不适用于PDF文件。答案只回答了如何合并两个二进制数据流,而不是特别指出如何合并两个PDF文件。它回答了提问者提出的问题,但实际上并没有解决他的问题。
当您使用
MemoryStream
的
byte[]
构造函数时,内存流不会随着添加更多数据而扩展。因此,它将无法容纳
stream1
和
stream2
的所有内容。此外,位置将从零开始,因此您正在用
stream1
中的数据覆盖
stream2
。
修复方法相当简单:
var result = new MemoryStream();
using (var file1 = File.OpenRead(file1Path)) file1.CopyTo(result);
using (var file2 = File.OpenRead(file2Path)) file2.CopyTo(result);
另一个选择是创建自己的流类,该类将是两个单独流的组合 - 如果您对组合性感兴趣,则非常有趣,但对于这样简单的事情来说可能过于复杂 :) 只是为了好玩,它可能看起来像这样:
public class DualStream : Stream
{
private readonly Stream _first;
private readonly Stream _second;
public DualStream(Stream first, Stream second)
{
_first = first;
_second = second;
}
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => false;
public override long Length => _first.Length + _second.Length;
public override long Position
{
get { return _first.Position + _second.Position; }
set { Seek(value, SeekOrigin.Begin); }
}
public override void Flush() { throw new NotImplementedException(); }
public override int Read(byte[] buffer, int offset, int count)
{
var bytesRead = _first.Read(buffer, offset, count);
if (bytesRead == count) return bytesRead;
return bytesRead + _second.Read(buffer, offset + bytesRead, count - bytesRead);
}
public override long Seek(long offset, SeekOrigin origin)
{
long targetPosition;
switch (origin)
{
case SeekOrigin.Begin: targetPosition = offset; break;
case SeekOrigin.Current: targetPosition = Position + offset; break;
case SeekOrigin.End: targetPosition = Length - offset; break;
default: throw new NotSupportedException();
}
targetPosition = Math.Max(0, Math.Min(Length, targetPosition));
var firstPosition = Math.Min(_first.Length, targetPosition);
_first.Position = firstPosition;
_second.Position = Math.Max(0, targetPosition - firstPosition);
return Position;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_first.Dispose();
_second.Dispose();
}
base.Dispose(disposing);
}
public override void SetLength(long value)
{ throw new NotImplementedException(); }
public override void Write(byte[] buffer, int offset, int count)
{ throw new NotImplementedException(); }
}
主要好处是您无需分配不必要的内存缓冲区即可拥有组合流——如果您敢于这样做,甚至可以直接使用文件流。而且它非常易于组合——您可以创建其他双重流的双重流,允许您将任意多个流链接在一起——与
IEnumerable.Concat
几乎相同。