メモリにすべてを収めることができない場合は、IEnumerableでデータをストリーミングすることができます。私はperfの最後のドロップが必要なので、私はMemoryMappedファイルでも遊んでいますが、これまで私はBinaryReader/Writerに固執しました。
DB支持者の場合:実際にperfの最後のドロップが必要な場合は、自分のバイナリファイルも作成します。プロセスをDBにすると、実際にオーバーヘッドが増えます。また、全体のセキュリティ/ロギング、ACIDなどが追加されます。
ここでは、f_resultsクラスをストリームする例を示します。ディレクトリ情報のツリーを読む/書く方法を示すために例を更新しました
EDIT
。私はすべてのディレクトリを保持する1つのファイルを保持します。このツリーは一度にメモリにロードされ、すべてのf_resultsがあるファイルを指します。 さらに、すべてのファイルのf_resultsを保持するディレクトリごとに別個のファイルを作成する必要があります。どのようにするかはあなたのコードに依存しますが、それを理解できるはずです。
幸運を祈る!
public class f_results {
public String name { get; set; }
public DateTime cdate { get; set; }
public DateTime mdate { get; set; }
public DateTime adate { get; set; }
public Int64 size { get; set; }
// write one to a file
public void WriteTo(BinaryWriter wrtr) {
wrtr.Write(name);
wrtr.Write(cdate.Ticks);
wrtr.Write(mdate.Ticks);
wrtr.Write(adate.Ticks);
wrtr.Write(size);
}
// read one from a file
public f_results(BinaryReader rdr) {
name = rdr.ReadString();
cdate = new DateTime(rdr.ReadInt64());
mdate = new DateTime(rdr.ReadInt64());
adate = new DateTime(rdr.ReadInt64());
size = rdr.ReadInt64();
}
// stream a whole file as an IEnumerable (so very little memory needed)
public static IEnumerable<f_results> FromFile(string dataFilePath) {
var file = new FileStream(dataFilePath, FileMode.Open);
var rdr = new BinaryReader(file);
var eos = rdr.BaseStream.Length;
while (rdr.BaseStream.Position < eos) yield return new f_results(rdr);
rdr.Close();
file.Close();
}
}
class Program {
static void Main(string[] args) {
var d1 = new DirTree(@"C:\",
new DirTree(@"C:\Dir1",
new DirTree(@"C:\Dir1\Dir2"),
new DirTree(@"C:\Dir1\Dir3")
),
new DirTree(@"C:\Dir4",
new DirTree(@"C:\Dir4\Dir5"),
new DirTree(@"C:\Dir4\Dir6")
));
var path = @"D:\Dirs.dir";
// write the directory tree to a file
var file = new FileStream(path, FileMode.CreateNew | FileMode.Truncate);
var w = new BinaryWriter(file);
d1.WriteTo(w);
w.Close();
file.Close();
// read it from the file
var file2 = new FileStream(path, FileMode.Open);
var rdr = new BinaryReader(file2);
var d2 = new DirTree(rdr);
// now inspect d2 in debugger to see that it was read back into memory
// find files bigger than (roughly) 1GB
var BigFiles = from f in f_results.FromFile(@"C:\SomeFile.dat")
where f.size > 1e9
select f;
}
}
class DirTree {
public string Path { get; private set; }
private string FilesFile { get { return Path.Replace(':', '_').Replace('\\', '_') + ".dat"; } }
public IEnumerable<f_results> Files() {
return f_results.FromFile(this.FilesFile);
}
// you'll want to encapsulate this in real code but I didn't for brevity
public DirTree[] _SubDirectories;
public DirTree(BinaryReader rdr) {
Path = rdr.ReadString();
int count = rdr.ReadInt32();
_SubDirectories = new DirTree[count];
for (int i = 0; i < count; i++) _SubDirectories[i] = new DirTree(rdr);
}
public DirTree(string Path, params DirTree[] subDirs){
this.Path = Path;
_SubDirectories = subDirs;
}
public void WriteTo(BinaryWriter w) {
w.Write(Path);
w.Write(_SubDirectories.Length);
// depth first is the easiest way to do this
foreach (var f in _SubDirectories) f.WriteTo(w);
}
}
}
データベースの代わりに、メモリ内の表現を使用して検討していますか? –
はい、私は持っていましたが、実行したいクエリーは、ディレクトリとそのサブパーツのサイズを読み、合計するなど非常に厄介なものになります。 – BugFinder
それでもあなたのベスト・ベットです。確かにそれを確認してください。このタイプの問題を解決するのは、データベースのためのものです。 –