Существует несколько причин хранения исходного msi:
нормальный способ вещей состоит в том, чтобы Windows сохранил файл кэшируемым для Вас, таким образом, Вы не должны думать об этом. Посмотрите свой %WINDIR %\Installer\папка. Единственная причина это попросило бы у Вашего исходного msi, состоит в том, если что-то неправильно с сохраненным файлом. Это обращается к большинству Ваших проблем, хотя это действительно повышает новый один (дисковое пространство).
Вы можете легко написать программу чтения строк на основе LINQ, используя блок итератора:
static IEnumerable<SomeType> ReadFrom(string file) {
string line;
using(var reader = File.OpenText(file)) {
while((line = reader.ReadLine()) != null) {
SomeType newRecord = /* parse line */
yield return newRecord;
}
}
}
или, чтобы порадовать Джона:
static IEnumerable<string> ReadFrom(string file) {
string line;
using(var reader = File.OpenText(file)) {
while((line = reader.ReadLine()) != null) {
yield return line;
}
}
}
...
var typedSequence = from line in ReadFrom(path)
let record = ParseLine(line)
where record.Active // for example
select record.Key;
, тогда у вас есть ReadFrom (...)
как последовательность с отложенным вычислением без буферизации, идеально подходящая для , где
и т. Д.
Обратите внимание, что если вы используете OrderBy
или стандартный GroupBy
, он необходимо буферизовать данные в памяти; Если вам нужна группировка и агрегация, в PushLINQ есть необычный код, позволяющий выполнять агрегирование данных, но отбрасывать их (без буферизации). Объяснение Джона здесь .
Проще прочитать строку и проверить, является ли она нулевой, чем постоянно проверять наличие EndOfStream.
Однако у меня также есть класс LineReader
в MiscUtil , который делает все это намного проще - в основном он предоставляет файл (или Func
как IEnumerable
, который позволяет вам делать Над ним работает LINQ. Таким образом, вы можете делать такие вещи, как:
var query = from file in Directory.GetFiles("*.log")
from line in new LineReader(file)
where line.Length > 0
select new AddOn(line); // or whatever
В основе LineReader
лежит реализация IEnumerable
:
public IEnumerator<string> GetEnumerator()
{
using (TextReader reader = dataSource())
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
Почти все остальное. источник просто предоставляет гибкие способы настройки dataSource
(который является Func
).
ПРИМЕЧАНИЕ : вам нужно остерегаться решения IEnumerable
, так как оно приведет к тому, что файл будет открыт на время обработки.
Например, с ответом Марка Грейвелла:
foreach(var record in ReadFrom("myfile.csv")) {
DoLongProcessOn(record);
}
файл будет оставаться открытым в течение всей обработки.
Спасибо всем за ответы! Я решил использовать смесь, в основном сосредоточившись на Марке, так как мне нужно будет читать только строки из файла. Думаю, вы можете утверждать, что разделение необходимо везде, но жизнь слишком коротка!
Что касается сохранения файла открытым, то в данном случае это не будет проблемой, поскольку код является частью настольного приложения .
Наконец, я заметил, что все вы использовали строчные буквы. Я знаю, что в Java есть разница между строкой с заглавной и без заглавной буквы, но я думал, что в C # строчная строка была просто ссылкой на строку с заглавной буквы?
public void Load(AddonCollection<T> collection)
{
// read from file
var query =
from line in LineReader(_LstFilename)
where line.Length > 0
select CreateAddon(line);
// add results to collection
collection.AddRange(query);
}
protected T CreateAddon(String line)
{
// create addon
T addon = new T();
addon.Load(line, _BaseDir);
return addon;
}
protected static IEnumerable<String> LineReader(String fileName)
{
String line;
using (var file = System.IO.File.OpenText(fileName))
{
// read each line, ensuring not null (EOF)
while ((line = file.ReadLine()) != null)
{
// return trimmed line
yield return line.Trim();
}
}
}