📄 ole2document.cs
字号:
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Fawvw.Components.NExcel.MyXls.ByteUtil;
using Io = System.IO;
namespace Microsoft.Fawvw.Components.NExcel.MyOle2
{
/// <summary>
/// Represents an OLE2 Compound Document format Document.
/// </summary>
public class Ole2Document
{
private readonly Header _header;
private readonly Msat _msat;
private readonly Sat _sat;
private readonly Ssat _ssat;
private readonly Directory _directory;
private readonly Streams _streams;
private byte[] _docFileID;
private byte[] _docUID;
private byte[] _fileFormatRevision;
private byte[] _fileFormatVersion;
private bool _isLittleEndian;
private ushort _sectorSize; //in power of 2 (min = 7)
private ushort _shortSectorSize; //in power of 2 (max = ShortSectorSize)
private byte[] _blank1;
private byte[] _blank2;
private uint _standardStreamMinBytes; //in bytes
private int _bytesPerSector;
private int _bytesPerShortSector;
/// <summary>
/// Initializes a new, blank, Ole2Document object.
/// </summary>
public Ole2Document()
{
SetDefaults();
_header = new Header(this);
_msat = new Msat(this);
_sat = new Sat(this);
_ssat = new Ssat(this);
_directory = new Directory(this);
_streams = new Streams(this);
_streams.AddNamed(new Bytes(), Directory.RootName);
}
/// <summary>
/// Gets this Ole2Document's Header object.
/// </summary>
public Header Header { get { return _header; } }
/// <summary>
/// Gets this Ole2Document's MSAT (Main Sector Allocation Table) object.
/// </summary>
public Msat MSAT { get { return _msat; } }
/// <summary>
/// Gets this Ole2Document's Directory object.
/// </summary>
public Directory Directory { get { return _directory; } }
/// <summary>
/// Gets this Ole2Document's Streams collection.
/// </summary>
public Streams Streams { get { return _streams; } }
/// <summary>
/// Gets this Ole2Document's SSAT (Short Sector Allocation Table) object.
/// </summary>
public Ssat SSAT { get { return _ssat; } }
/// <summary>
/// Gets this Ole2Document's SAT (Sector Allocation Table) object.
/// </summary>
public Sat SAT { get { return _sat; } }
/// <summary>
/// Gets the number of bytes per Short Sector in this Ole2Document (set with ShortSectorSize).
/// </summary>
public int BytesPerShortSector
{
get { return _bytesPerShortSector; }
}
/// <summary>
/// Gets the number of bytes per Sector in this Ole2Document (set with SectorSize).
/// </summary>
public int BytesPerSector
{
get { return _bytesPerSector; }
}
/// <summary>
/// Gets or sets the number of bytes per Standard (not short) Stream in this Ole2Document.
/// This is not normally changed from its default.
/// </summary>
public uint StandardStreamMinBytes
{
get { return _standardStreamMinBytes; }
set
{
if (value <= 2)
throw new ArgumentOutOfRangeException("value", "must be > 2");
_standardStreamMinBytes = value;
}
}
/// <summary>
/// Gets or sets the Ole2Document FileID of this Ole2Document.
/// This is not normally changed from its default.
/// </summary>
public byte[] DocFileID
{
get { return _docFileID; }
set
{
if (value.Length != 8)
throw new ArgumentOutOfRangeException("value", "must be 8 bytes in length");
_docFileID = value;
}
}
/// <summary>
/// Gets or sets the Ole2Document UID of this Ole2Document.
/// This is not normally changed from its default.
/// </summary>
public byte[] DocUID
{
get { return _docUID; }
set
{
if (value.Length != 16)
throw new ArgumentOutOfRangeException("value", "must be 16 bytes in length");
_docUID = value;
}
}
/// <summary>
/// Gets or sets the FileFormatRevision of this Ole2Document.
/// This is not normally changed from its default.
/// </summary>
public byte[] FileFormatRevision
{
get { return _fileFormatRevision; }
set
{
if (value.Length != 2)
throw new ArgumentOutOfRangeException("value", "must be 2 bytes in length");
_fileFormatRevision = value;
}
}
/// <summary>
/// Gets or sets the FileFormatVersion of this Ole2Document.
/// This is not normally changed from its default.
/// </summary>
public byte[] FileFormatVersion
{
get { return _fileFormatVersion; }
set
{
if (value.Length != 2)
throw new ArgumentOutOfRangeException("value", "must be 2 bytes in length");
_fileFormatVersion = value;
}
}
/// <summary>
/// Gets whether this Ole2Document should be encoded in Little Endian (or
/// Big Endian) format. Currently only Little Endian is supported.
/// </summary>
public bool IsLittleEndian
{
get { return _isLittleEndian; }
set { if (value == false) throw new NotSupportedException("Big Endian not currently supported"); _isLittleEndian = value; }
}
/// <summary>
/// Gets or sets the Sector Size of this Ole2Document. This is the number of bytes
/// per standard sector as a power of 2 (e.g. setting this to 9 sets the
/// BytesPerSector to 2 ^ 9 or 512). This is not normally changed from its
/// default of 9.
/// </summary>
public ushort SectorSize
{
get { return _sectorSize; }
set
{
if (value < 7)
throw new ArgumentOutOfRangeException("value", "must be >= 7");
_sectorSize = value;
_bytesPerSector = (int)Math.Pow(2, value);
}
}
/// <summary>
/// Gets or sets the Short Sector Size of this Ole2Document. This is the number of
/// bytes per short sector as a power of 2 (e.g. setting this to 6 sets the
/// BytesPerShortSector to 2 ^ 6 or 128). This is not normally changed from
/// its default of 6.
/// </summary>
public ushort ShortSectorSize
{
get { return _shortSectorSize; }
set
{
if (value > SectorSize)
throw new ArgumentOutOfRangeException(string.Format("value must be <= SectorSize {0}", SectorSize));
_shortSectorSize = value;
_bytesPerShortSector = (int)Math.Pow(2, ShortSectorSize);
}
}
private void SetDefaults()
{
//Standard from OOo compdocfileformat.pdf
DocFileID = new byte[] {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1};
//Can be any 16-byte value per OOo compdocfileformat.pdf
DocUID = new byte[16];
//Unused standard per OOo compdocfileformat.pdf
FileFormatRevision = new byte[] {0x3E, 0x00};
//Unused standard per OOo compdocfileformat.pdf
FileFormatVersion = new byte[] {0x03, 0x00};
//Standard per OOo compdocfileformat
IsLittleEndian = true;
//Most common (BIFF8) value per OOo compdocfileformat.pdf
SectorSize = 9;
//Most common (BIFF8) value per OOo compdocfileformat.pdf
ShortSectorSize = 6;
//Unused per OOo compdocfileformat.pdf
_blank1 = new byte[10];
//Unused per OOo compdocfileformat.pdf
_blank2 = new byte[4];
//Most common (BIFF8) value per OOo compdocfileformat
StandardStreamMinBytes = 4096;
}
/// <summary>
/// Gets a Bytes object containing all the bytes of this Ole2Document. This Bytes object's
/// ByteArray is what should be saved to disk to persist this Ole2Document as a file on disk.
/// </summary>
public Bytes Bytes
{
get
{
Bytes bytes = new Bytes();
//===================================================
//DON'T CHANGE THE ORDER HERE OR ALL SID0'S WILL BE OFF
//TODO: Should refactor this to function which does
//lookups via a section-order array (would have to
//check this for determining SID0's)
//===================================================
bytes.Append(Header.Bytes);
bytes.Append(MSAT.Bytes);
bytes.Append(SAT.Bytes);
bytes.Append(SSAT.Bytes);
bytes.Append(Streams.Bytes);
bytes.Append(Directory.Bytes);
return bytes;
}
}
/// <summary>
/// Loads this Ole2Document object from the provided stream (e.g. a FileStream to load
/// from a File). This is only preliminarily supported and tested for Excel
/// files.
/// </summary>
/// <param name="stream"></param>
public void Load(System.IO.Stream stream)
{
if (stream.Length == 0)
throw new Exception("No data (or zero-length) found!");
if (stream.Length < 512)
throw new Exception(string.Format("File length {0} < 512 bytes", stream.Length));
byte[] head = new byte[512];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -