C#: что эффективный путь состоит в том, чтобы проанализировать строку с одним разделителем для каждого ReadLine () TextReader?
Моя цель состоит в том, чтобы загрузить список прокси к ListView в два столбца (Proxy|Port), читающий из .txt файла. Как был бы я идти после разделения каждого readline () в прокси и переменные порта с разделителем ":"?
Это - то, что я имею до сих пор,
public void loadProxies(string FilePath)
{
string Proxy; // example/temporary place holders
int Port; // updated at each readline() loop.
using (TextReader textReader = new StreamReader(FilePath))
{
string Line;
while ((Line = textReader.ReadLine()) != null)
{
// How would I go about directing which string to return whether
// what's to the left of the delimiter : or to the right?
//Proxy = Line.Split(':');
//Port = Line.Split(':');
// listview stuff done here (this part I'm familiar with already)
}
}
}
В противном случае существует ли более эффективный способ сделать это?
Вы можете попробовать что-то подобное.
var items = File.ReadAllText(FilePath)
.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
.Select(line => line.Split(':'))
.Select(pieces => new {
Proxy = pieces[0],
Port = int.Parse(pieces[1])
});
Если вы знаете, что в конце файла не будет случайной новой строки, вы можете это сделать.
var items = File.ReadAllLines(FilePath)
.Select(line => line.Split(':'))
.Select(pieces => new {
Proxy = pieces[0],
Port = Convert.ToInt32(pieces[1])
});
Как насчет выполнения регулярного выражения для всего файла?
var parts=
Regex.Matches(input, @"(?<left>[^:]*):(?<right>.*)",RegexOptions.Multiline)
.Cast<Match>()
.Where(m=>m.Success)
.Select(m => new
{
left = m.Groups["left"],
right = m.Groups["right"]
});
foreach(var part in parts)
{
//part.left
//part.right
}
Или, если он слишком велик, почему бы не выполнить Linqify операцию ReadLine с помощью метода уступки?
static IEnumerable<string> Lines(string filename)
{
using (var sr = new StreamReader(filename))
{
while (!sr.EndOfStream)
{
yield return sr.ReadLine();
}
}
}
И запустить ее так:
var parts=Lines(filename)
.Select(
line=>Regex.Match(input, @"(?<left>[^:]*):(?<right>.*)")
)
.Where(m=>m.Success)
.Select(m => new
{
left = m.Groups["left"],
right = m.Groups["right"]
});
foreach(var part in parts)
{
//part.left
//part.right
}
string [] parts = line.Split(':');
string proxy = parts[0];
string port = parts[1];
You можно разделить их следующим образом:
string line;
string[] tokens;
while ((Line = textReader.ReadLine()) != null)
{
tokens = line.Split(':');
proxy = tokens[0];
port = tokens[1];
// listview stuff done here (this part I'm familiar with already)
}
лучше всего использовать имена переменных в C # с маленькой буквы, так как остальные зарезервированы для имен классов / пространств имен и т. д.
С точки зрения эффективности Я думаю, вам будет сложно превзойти:
int index = line.IndexOf(':');
if (index < 0) throw new InvalidOperationException();
Proxy = line.Substring(0, index);
Port = int.Parse(line.Substring(index + 1));
Это позволяет избежать создания / распределения массива связан с Split
, и смотрит только до первого разделителя. Но я должен подчеркнуть, что это вряд ли будет подлинным узким местом в производительности, если объем данных не будет огромным , так что почти любой подход подойдет. На самом деле, возможно, самая важная вещь (мне напомнил комментарий ниже) - это приостановить пользовательский интерфейс при добавлении:
myListView.BeginUpdate();
try {
// TODO: add all the items here
} finally {
myListView.EndUpdate();
}