Здравствуйте.
Ситуация следующая: мне нужно в файлах искать вхождения некоторых данных. Раньше файлы были маленькие и данных были в одном экземпляре (т.е. требовалось найти вхождение одних и тех же данных), сейчас же условия изменились и нужно найти разные данные, плюс к этому файлы очень сильно выросли (около 1Гб).
Задачу я решил (код ниже), но т.к. время время позволяет, то я решил попробовать написать в функциональном стиле, но как не пишу, всё равно получается, то, что есть.
Помогите, пожалуйста, переписать этот код. Я пытался и на F# (недавно начал изучать) и на C#, никак не выходит.
Для C# написал только такой код, а что дальше с ним делать — не понятно
IEnumerable<byte> GetBytes(string fileName)
{
int bytesReaden;
byte[]buffer = new byte[4096];
using (var file = File.OpenRead(fileName))
while ((bytesReaden = file.Read(buffer, 0, buffer.Length))>0)
{
for (int i = 0; i < bytesReaden; i++)
{
yield return buffer[i];
}
}
}
А вот существующий код:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
namespace TestProgram
{
internal class Entry
{
public string Item;
public int Offset;
}
internal class Program
{
private static void Main(string[] args)
{
string fileName = new StackTrace(true).GetFrame(0).GetFileName();
var entries = new[]
{
"Microsoft.Build.Conversion.v3.5.xml",
"Microsoft.Build.Engine.xml",
"Microsoft.Build.Framework.xml",
"Microsoft.Build.Utilities.v3.5.xml",
"Microsoft.VisualC.STLCLR.xml",
"System.AddIn.Contract.xml",
"System.AddIn.xml",
"System.Core.xml",
"System.Data.DataSetExtensions.xml",
"System.Data.Linq.xml",
"System.DirectoryServices.AccountManagement.xml",
"System.Management.Instrumentation.xml",
"System.Net.xml",
"System.ServiceModel.Web.xml",
"System.Web.Extensions.Design.xml",
"System.Web.Extensions.xml",
"System.Windows.Presentation.xml",
"System.WorkflowServices.xml",
"System.Xml.Linq.xml",
};
var list = new List<Entry>();
list.AddRange(FindEntries(fileName, entries));
Console.WriteLine("list: {0}", list.Count);
}
private static IEnumerable<Entry> FindEntries(string fileName, string[] entries)
{
var list = new List<Entry>();
using (FileStream file = File.OpenRead(fileName))
{
foreach (string entryString in entries)
{
file.Seek(0, SeekOrigin.Begin);
var buffer = new byte[4096];
int bytesReaden;
int offset = 0;
byte[] entryBytes = Encoding.ASCII.GetBytes(entryString);
int curPos = 0;
while ((bytesReaden = file.Read(buffer, offset, buffer.Length - offset)) > 0)
{
bytesReaden += offset;
for (int i = 0; i < bytesReaden - entryBytes.Length; i++)
{
bool match = true;
for (int j = 0; j < entryBytes.Length; j++)
{
if (buffer[i + j] != entryBytes[j])
{
match = false;
break;
}
}
if (match)
{
var entry = new Entry
{
Item = entryString,
Offset = curPos + i
};
i += entryBytes.Length;
list.Add(entry);
}
}
offset = entryBytes.Length;
curPos += bytesReaden - offset;
for (int i = 0; i < entryBytes.Length; i++)
{
buffer[i] = buffer[bytesReaden - entryBytes.Length + i];
}
}
}
}
return list;
}
}
}
//"Microsoft.Build.Conversion.v3.5.xml",