Recently, I came across a situation where I
need to extract the memo field data from an FPT file. After lot of googling I
found this documentation which describes the FPT structure and then I decided to
write my own code to parse the FPT file and extract the data stored in it.
public enum
MemoDataType
public class
MemoCollection :
IEnumerable<MemoBlock>
public MemoCollection(System.IO.Stream
memoStream)
#region IEnumerable<MemoBlock>
Members
public IEnumerator<MemoBlock>
GetEnumerator() #endregion
#region IEnumerable
Members
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
private IEnumerator<MemoBlock>
GetCollection()
private void
PositionToNextBlock()
private MemoBlock
ReadMemo()
private void
GetBlockSize() }
private int
ToInteger(byte[] data) #endregion
A memo file (FPT) file contains one header and any number of block structures.
The header part is 512 bytes long but the useful information is stored in 7th
and 8th byte which is the size of the block structure.![]()
Following the header is the first memo block. A memo block consists of a memo
block header and memo text. Memo block is 8 bytes long and stores the type of
memo data and the length of the memo data. 
A memo block can span over multiple blocks structures but a single block can't
have data of more than one memo block. It means if block is larger than the memo
size then remaining block will be unused.
Here is the code to extract memo data.
public
class MemoBlock
{
public
MemoDataType MemoDataType { get;
private set; }
public Byte[]
Memo { get; private
set; }
public MemoBlock(MemoDataType
type, Byte[] data)
{
this.MemoDataType = type;
this.Memo = data;
}
}
{
Picture = 0
, Text = 1
}
{
private System.IO.Stream
Stream = null;
private int
blockSize = 0;
{
this.Stream = memoStream;
}
{
return GetCollection();
}
{
return this.GetEnumerator();
}
{
Stream.Seek(0, SeekOrigin.Begin);
GetBlockSize();
while (Stream.Position <
Stream.Length)
{
var memo = ReadMemo();
PositionToNextBlock();
yield
return memo;
}
}
{
int unusedbytecount = (int)(Stream.Position
% blockSize);
if (unusedbytecount > 0)
Stream.Seek(blockSize - unusedbytecount,
SeekOrigin.Current);
}
{
Byte[] header =
new Byte[8];
Stream.Read(header, 0, header.Length);
MemoDataType type = (MemoDataType)ToInteger(header.Take(4).ToArray());
int memoSize =
ToInteger(header.Skip(4).Take(4).ToArray());
Byte[] memoData =
new Byte[memoSize];
Stream.Read(memoData, 0, memoData.Length);
return new
MemoBlock(type, memoData);
}
{
Byte[] buffer =
new Byte[512];
Stream.Read(buffer, 0, buffer.Length);
blockSize = ToInteger(new
Byte[] { 0,0,buffer[6],buffer[7]});
{
if (BitConverter.IsLittleEndian)
Array.Reverse(data);
return
BitConverter.ToInt32(data,0);
}
}
To see more from me, u can visit
http://zafarayousafi.blogspot.com/
Loading
Join the conversation! Your thoughts help the community grow.