Ars*_*bal 6 c# memorystream itextsharp
我试图将两个PDF文件读入两个内存流,然后返回一个包含两个流数据的流.但我似乎不明白我的代码有什么问题.
示例代码:
string file1Path = "Sampl1.pdf";
string file2Path = "Sample2.pdf";
MemoryStream stream1 = new MemoryStream(File.ReadAllBytes(file1Path));
MemoryStream stream2 = new MemoryStream(File.ReadAllBytes(file2Path));
stream1.Position = 0;
stream1.Copyto(stream2);
return stream2; /*supposed to be containing data of both stream1 and stream2 but contains data of stream1 only*/
Run Code Online (Sandbox Code Playgroud)
在PDF文件的情况下,内存流的合并与.txt文件不同.对于PDF,您需要使用一些.dll,因为我使用iTextSharp.dll(在AGPL许可下可用),然后使用此库的功能将它们组合如下:
MemoryStream finalStream = new MemoryStream();
PdfCopyFields copy = new PdfCopyFields(finalStream);
string file1Path = "Sample1.pdf";
string file2Path = "Sample2.pdf";
var ms1 = new MemoryStream(File.ReadAllBytes(file1Path));
ms1.Position = 0;
copy.AddDocument(new PdfReader(ms1));
ms1.Dispose();
var ms2 = new MemoryStream(File.ReadAllBytes(file2Path));
ms2.Position = 0;
copy.AddDocument(new PdfReader(ms2));
ms2.Dispose();
copy.Close();
Run Code Online (Sandbox Code Playgroud)
finalStream包含ms1和ms2的合并pdf.
注意:
整个问题基于一个错误的前提,即您可以通过合并两个PDF文件的二进制文件来生成合并的PDF文件.这适用于纯文本文件,例如(在某种程度上),但绝对不适用于PDF.答案仅解决了如何合并两个二进制数据流,而不是如何合并两个PDF文件.它按照要求回答OP的问题,但实际上并没有解决他的问题.
当您使用byte[]构造函数时MemoryStream,内存流将不会随着您添加更多数据而展开.所以它不会是两个足够大stream1和stream2.此外,该位置将从零开始,因此您将覆盖stream2数据stream1.
修复很简单:
var result = new MemoryStream();
using (var file1 = File.OpenRead(file1Path)) file1.CopyTo(result);
using (var file2 = File.OpenRead(file2Path)) file2.CopyTo(result);
Run Code Online (Sandbox Code Playgroud)
另一个选择是创建自己的流类,它将是两个独立流的组合 - 如果你对可组合性感兴趣,那么这很有趣,但对于像这样简单的东西可能有点过分了:)
只是为了好玩,它看起来像这样:
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)
{
// To simplify, let's assume seek always works as if over one big MemoryStream
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(); }
}
Run Code Online (Sandbox Code Playgroud)
主要的好处是,它意味着您不必为了组合流而分配不必要的内存缓冲区 - 它甚至可以直接与文件流一起使用,如果您敢于:D并且它很容易组合 - 您可以制作其他双流的双流,允许您根据需要链接尽可能多的流 - 几乎相同IEnumerable.Concat.
| 归档时间: |
|
| 查看次数: |
8925 次 |
| 最近记录: |