Created
May 4, 2013 22:09
-
-
Save jirkapenzes/5518928 to your computer and use it in GitHub Desktop.
FileIndex - RTree - přímý přístup do souboru
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
namespace GraphAnalyzer.RTree.FileIndex | |
{ | |
public class BaseFile<T> | |
{ | |
private IList<IRTreeEdge<T>> _buffer; | |
private int _currentBufferAddress; | |
private readonly IExtendedFileManager<T> _fileManager; | |
private readonly int _treeOrder = RTreeConfig.Instance.TreeOrder; // řád stromu | |
private readonly int _capacity; | |
public BaseFile(IExtendedFileManager<T> fileManager, int capacity) | |
{ | |
_buffer = new List<IRTreeEdge<T>>(); | |
_fileManager = fileManager; | |
_currentBufferAddress = -1; | |
_capacity = capacity; | |
} | |
public void SaveEdge(Stream stream, IRTreeEdge<T> edge, int address) | |
{ | |
// prostě uložím jednu položku do souboru | |
_fileManager.Save(stream, edge, address); | |
} | |
public IRTreeEdge<T> LoadEdge(Stream stream, int address) | |
{ | |
// komentáře jsou ke třetímu řádu (předpokládám tři potomky) | |
// zjistím adresu bloku (př. pokud chci 7 prvek, tak patří do druhého bloku [7 / 3 = 2,333]) | |
int bufferAddress = address / _treeOrder; | |
// vypočítám adresu prvku v jednom bloku | |
// soubor vypadá nějak takto: | 0 1 2 | 3 4 5 | 6 7 8 | 9 10 11 | ... | |
// já načetl druhý blok -> | 6 7 8 | -> a chci získat adresu sedmičky -> tj. 1 | |
// 7 - (2 * 3) = 1 | |
int dataAddressInBlock = address - (bufferAddress * _treeOrder); | |
// ověřím, jestli už náhodou není blok načtený | |
if (bufferAddress == _currentBufferAddress) | |
{ | |
return _buffer[dataAddressInBlock]; | |
} | |
// pokud chci adresu z jiného bloku, tak musím načíst nový blok do bufferu | |
LoadBuffer(stream, bufferAddress * _treeOrder); | |
return _buffer[dataAddressInBlock]; | |
} | |
private void LoadBuffer(Stream stream, int address) | |
{ | |
int count = _treeOrder; | |
// zjistím, zda mohu načíst maximální počet prvků (konec souboru) | |
if (IsLastBlock(address)) | |
{ | |
// pokud jsem na konci, tak si vypočítám, kolik je v posledním bloku dat | |
// nemusí být celý obsazen. Př. Chci načíst poslední blok, ale nikolic 3 prvky, ale 2 | |
// 0 1 2 | 3 4 5 | 6 7 | |
// count = 8 - (2 * 3) = 2 | |
count = _capacity - (address * _treeOrder); | |
} | |
// načtu nový buffer | |
_buffer = _fileManager.LoadEdge(stream, address, count); | |
// nastaví novou adresu aktuálního bloku dat | |
_currentBufferAddress = address; | |
} | |
private bool IsLastBlock(int address) | |
{ | |
int lastBlock = _capacity / _treeOrder; | |
return lastBlock == address; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
namespace GraphAnalyzer.RTree.FileIndex | |
{ | |
internal class Converter | |
{ | |
public static byte[] ConvertStringToByteArray(string text, int capacity) | |
{ | |
var byteText = text.Length < 10 ? text.PadRight(10, ' ') : text.Substring(0, 10); | |
return Encoding.ASCII.GetBytes(byteText); | |
} | |
public static string ConvertByteArrayToString(byte[] bytes) | |
{ | |
var text = ""; | |
foreach (var c in Encoding.ASCII.GetChars(bytes)) | |
text = text + c; | |
return text.Trim(); | |
} | |
public static byte[] ConvertIntToByteArray(int i) | |
{ | |
return BitConverter.GetBytes(i); | |
} | |
public static int ConvertByteArrayToInt(byte[] bytes) | |
{ | |
return BitConverter.ToInt32(bytes, 0); | |
} | |
public static byte[] ConvertDoubleToByteArray(double d) | |
{ | |
return BitConverter.GetBytes(d); | |
} | |
public static double ConvertByteArrayToDouble(byte[] bytes) | |
{ | |
return BitConverter.ToDouble(bytes, 0); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
namespace GraphAnalyzer.RTree.FileIndex | |
{ | |
public class FileDataBlock<T> | |
{ | |
public int Address { get; set; } | |
public T Data { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.IO; | |
namespace GraphAnalyzer.RTree.FileIndex | |
{ | |
public class FileManager<T> | |
{ | |
private readonly int _treeOrder; | |
public FileManager(int treeOrder) | |
{ | |
_treeOrder = treeOrder; | |
} | |
public FileNode MakeFileNode(RTreeNode<T> rTreeNode, int blockAddress, ref int currentBlockAddress) | |
{ | |
var fileNode = new FileNode | |
{ | |
Position = blockAddress, | |
BaseBlockAddress = -1, | |
RTreeArea = new RTreeArea | |
{ | |
X = rTreeNode.RTreeArea.X, | |
Y = rTreeNode.RTreeArea.Y, | |
Width = rTreeNode.RTreeArea.Width, | |
Height = rTreeNode.RTreeArea.Height | |
}, | |
ChildrenAddresses = new List<int>(_treeOrder) | |
}; | |
if (rTreeNode.RTreeEdge != null) | |
{ | |
for (var i = 0; i < _treeOrder; i++) | |
fileNode.ChildrenAddresses.Add(-1); | |
} | |
else | |
{ | |
for (var i = 0; i < _treeOrder; i++) | |
{ | |
if (i < rTreeNode.Children.Count) | |
fileNode.ChildrenAddresses.Add(++currentBlockAddress); | |
else | |
fileNode.ChildrenAddresses.Add(-1); | |
} | |
} | |
return fileNode; | |
} | |
public void SaveFileNode(Stream stream, FileNode node, int fileAddress) | |
{ | |
stream.Seek(fileAddress * GetFileNodeSize(), SeekOrigin.Begin); | |
var writer = new BinaryWriter(stream); | |
writer.Write(Converter.ConvertIntToByteArray(node.Position)); | |
writer.Write(Converter.ConvertIntToByteArray(node.BaseBlockAddress)); | |
writer.Write(Converter.ConvertDoubleToByteArray(node.RTreeArea.X)); | |
writer.Write(Converter.ConvertDoubleToByteArray(node.RTreeArea.Y)); | |
writer.Write(Converter.ConvertDoubleToByteArray(node.RTreeArea.Width)); | |
writer.Write(Converter.ConvertDoubleToByteArray(node.RTreeArea.Height)); | |
foreach (var childrenAddress in node.ChildrenAddresses) | |
writer.Write(Converter.ConvertIntToByteArray(childrenAddress)); | |
} | |
public FileNode LoadNode(Stream stream, int blockAddress) | |
{ | |
var fileNode = new FileNode(); | |
stream.Seek(blockAddress * GetFileNodeSize(), SeekOrigin.Begin); | |
fileNode.Position = LoadValueInteger(stream); | |
fileNode.BaseBlockAddress = LoadValueInteger(stream); | |
fileNode.RTreeArea = new RTreeArea | |
{ | |
X = LoadValueDouble(stream), | |
Y = LoadValueDouble(stream), | |
Width = LoadValueDouble(stream), | |
Height = LoadValueDouble(stream) | |
}; | |
for (var i = 0; i < _treeOrder; i++) | |
{ | |
var address = LoadValueInteger(stream); | |
if (address > 0) | |
fileNode.ChildrenAddresses.Add(address); | |
} | |
return fileNode; | |
} | |
private static int LoadValueInteger(Stream stream) | |
{ | |
var bytes = new byte[4]; | |
stream.Read(bytes, 0, sizeof(int)); | |
return Converter.ConvertByteArrayToInt(bytes); | |
} | |
private static double LoadValueDouble(Stream stream) | |
{ | |
var bytes = new byte[8]; | |
stream.Read(bytes, 0, sizeof(double)); | |
return Converter.ConvertByteArrayToDouble(bytes); | |
} | |
public int GetFileNodeSize() | |
{ | |
var size = sizeof(int); // position | |
size += sizeof(int); // BaseBlockAddress | |
size += sizeof(double); // RTreeArea.X | |
size += sizeof(double); // RTreeArea.Y | |
size += sizeof(double); // RTreeArea.Width | |
size += sizeof(double); // RTreeArea.Height | |
for (var i = 0; i < _treeOrder; i++) // Children address | |
size += sizeof(int); | |
return size; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
namespace GraphAnalyzer.RTree.FileIndex | |
{ | |
public class FileNode | |
{ | |
public FileNode() | |
{ | |
ChildrenAddresses = new List<int>(); | |
} | |
public int Position { get; set; } | |
public int BaseBlockAddress { get; set; } | |
public RTreeArea RTreeArea { get; set; } | |
public IList<int> ChildrenAddresses { get; set; } | |
public bool HasChildren() | |
{ | |
return ChildrenAddresses.Any(address => address > 0); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
namespace GraphAnalyzer.RTree.FileIndex | |
{ | |
public interface IExtendedFileManager<T> | |
{ | |
// umí uložit soubor na požadovanou pozici do streamu | |
void Save(Stream stream, IRTreeEdge<T> rTreeEdge, int address); | |
// umít načíst data ze soubory (i větší počet najednou) | |
IList<IRTreeEdge<T>> LoadEdge(Stream stream, int address, int count); | |
// umí vypočítat adresu jednoho bloku dat | |
int GetFileSize(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment