Подтвердить что ты не робот

ReadAllLines для объекта Stream?

Существует File.ReadAllLines, но не Stream.ReadAllLines.

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string result = reader.ReadToEnd();
}

Есть ли способ сделать это или мне нужно вручную прокручивать файл по строкам?

4b9b3361

Ответ 1

Вы можете написать метод, который читается по строкам, например:

public IEnumerable<string> ReadLines(Func<Stream> streamProvider,
                                     Encoding encoding)
{
    using (var stream = streamProvider())
    using (var reader = new StreamReader(stream, encoding))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

Затем назовите его как:

var lines = ReadLines(() => Assembly.GetExecutingAssembly()
                                    .GetManifestResourceStream(resourceName),
                      Encoding.UTF8)
                .ToList();

Часть Func<> должна справляться при чтении более одного раза и избегать ненужных потоков. Конечно, вы можете легко обернуть этот код в методе.

Если вам не нужно все сразу в памяти, вам даже не понадобится ToList...

Ответ 2

Свойство .EndOfStream может использоваться в цикле вместо проверки того, не следующая ли следующая строка.

List<string> lines = new List<string>();

using (StreamReader reader = new StreamReader("example.txt"))
{
    while(!reader.EndOfStream)
    {
        lines.Add(reader.ReadLine());
    }
}

Ответ 3

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    // Would prefer string[] result = reader.ReadAllLines();
    string[] result = reader.ReadToEnd().Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
}

Ответ 4

Использование Split здесь:

reader
   .ReadToEnd()
   .Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

не эквивалентен ReadLine. Если вы посмотрите на источник ReadLine, StreamReader.cs, вы увидите, что он обрабатывает терминаторы строк:\r,\n и \r\n правильно. ReadLine не возвращает лишнюю пустую строку, когда терминатор строки \r\n, что типично для DOS/Windows. Split "видит" (анализирует)\r, за которым следует \n как два отдельных разделителя и возвращает пустую строку.

'StringSplitOptions.RemoveEmptyEntries' в приведенном выше коде удаляет эти пустые строки, но также удаляет любые пустые строки, которые также появляются на входе.

Таким образом, для ввода   line1\г   \р   line3\г ReadLine возвращает 3 строки. Второй пуст. Split создает 4 строки. (После последней \r. Есть дополнительная строка). Затем он удаляет 2-й и 4-й.

Обратите внимание, что Split не подходит для разбора текстовых строк, которые являются "пост-исправными". То есть разделитель появляется после токена. Пока Split подходит для инфикса, где между токенами появляются разделители. Это разница между a, b, c и line1\r, line2, line3\r. Для этих входов Split возвращает 3 строки или 4 строки соответственно.

Ответ 5

Если вы хотите использовать StreamReader, тогда да, вам нужно будет использовать ReadLine и цикл через StreamReader, считая строку за строкой.

Что-то вроде этого:

string line;

using (StreamReader reader = new StreamReader(stream))
{
    while ((line = reader.ReadLine()) != null)
    {   
        Console.WriteLine(line); 
    }
}

или попробуйте

using (StreamReader reader = new StreamReader("file.txt"))
    {

       string[] content = reader.ReadToEnd().Replace("\n","").Split('\t');
    }

Ответ 6

Используя следующий метод расширения:

public static class Extensions
{
    public static IEnumerable<string> ReadAllLines(this StreamReader reader)
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

Можно получить нужный код:

using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Test_Resources.Resources.Accounts.txt"))
using (StreamReader reader = new StreamReader(stream))
{
    string[] result = reader.ReadAllLines().ToArray();
}