Чтение текстового файла с помощью streamreader.
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string line = sr.ReadLine();
}
Я хочу заставить этот разделитель строк \n
not \r
. Итак, как я могу это сделать?
Чтение текстового файла с помощью streamreader.
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
string line = sr.ReadLine();
}
Я хочу заставить этот разделитель строк \n
not \r
. Итак, как я могу это сделать?
string text = sr.ReadToEnd();
string[] lines = text.Split('\r');
foreach(string s in lines)
{
// Consume
}
Я бы выполнил что-то вроде ответа Джорджа, но как метод расширения, который позволяет избежать загрузки всего файла сразу (не тестировался, но что-то вроде этого):
static class ExtensionsForTextReader
{
public static IEnumerable<string> ReadLines (this TextReader reader, char delimiter)
{
List<char> chars = new List<char> ();
while (reader.Peek() >= 0)
{
char c = (char)reader.Read ();
if (c == delimiter) {
yield return new String(chars.ToArray());
chars.Clear ();
continue;
}
chars.Add(c);
}
}
}
Что можно было бы использовать как:
using (StreamReader sr = new StreamReader(FileName, Encoding.Default))
{
foreach (var line in sr.ReadLines ('\n'))
Console.WriteLine (line);
}
Согласно документации:
http://msdn.microsoft.com/en-us/library/system.io.streamreader.readline.aspx
Строка определяется как последовательность символов, за которой следует строка ( "\n" ), возврат каретки ( "\ r" ) или возврат каретки немедленно за которым следует строка ( "\ r\n" ).
По умолчанию метод StreamReader ReadLine распознает строку как с помощью \n, так и\r
Мне понравился ответ @Pete. Я просто хотел бы внести небольшую модификацию. Это позволит вам передать строковый разделитель вместо одного символа:
using System;
using System.IO;
using System.Collections.Generic;
internal static class StreamReaderExtensions
{
public static IEnumerable<string> ReadUntil(this StreamReader reader, string delimiter)
{
List<char> buffer = new List<char>();
CircularBuffer<char> delim_buffer = new CircularBuffer<char>(delimiter.Length);
while (reader.Peek() >= 0)
{
char c = (char)reader.Read();
delim_buffer.Enqueue(c);
if (delim_buffer.ToString() == delimiter || reader.EndOfStream)
{
if (buffer.Count > 0)
{
if (!reader.EndOfStream)
{
yield return new String(buffer.ToArray()).Replace(delimiter.Substring(0, delimiter.Length - 1), string.Empty);
}
else
{
buffer.Add(c);
yield return new String(buffer.ToArray());
}
buffer.Clear();
}
continue;
}
buffer.Add(c);
}
}
private class CircularBuffer<T> : Queue<T>
{
private int _capacity;
public CircularBuffer(int capacity)
: base(capacity)
{
_capacity = capacity;
}
new public void Enqueue(T item)
{
if (base.Count == _capacity)
{
base.Dequeue();
}
base.Enqueue(item);
}
public override string ToString()
{
List<String> items = new List<string>();
foreach (var x in this)
{
items.Add(x.ToString());
};
return String.Join("", items);
}
}
}
Вы либо должны самостоятельно разбирать поток по байтам и обрабатывать разделение, либо вам нужно использовать поведение ReadLine по умолчанию, которое разбивается на /r,/n или/r/n.
Если вы хотите разбирать побайтовые байты, я бы использовал что-то вроде следующего метода расширения:
public static string ReadToChar(this StreamReader sr, char splitCharacter)
{
char nextChar;
StringBuilder line = new StringBuilder();
while (sr.Peek() > 0)
{
nextChar = (char)sr.Read();
if (nextChar == splitCharacter) return line.ToString();
line.Append(nextChar);
}
return line.Length == 0 ? null : line.ToString();
}
Вы можете просто использовать ReadToEnd() для чтения, а затем использовать String.Split, чтобы разграничить его в любом случае, когда вы сочтете нужным.
Даже если вы сказали "Using StreamReader", так как вы также сказали: "Я в моем случае, у файла может быть множество записей...", я бы рекомендовал попробовать SSIS. Он идеально подходит для того, что вы пытаетесь сделать. Вы можете обрабатывать очень большой файл и легко указывать разделители строк и столбцов.
Это улучшение ответа на совпадение. Извините, я бы хотел прокомментировать, хотя моя репутация не позволяет мне это делать. Это улучшение устраняет 2 проблемы:
когда последние символы в потоке равны разделителю, функция неверно вернуть строку, включая разделители.
using System;
using System.IO;
using System.Collections.Generic;
internal static class StreamReaderExtensions
{
public static IEnumerable<string> ReadUntil(this StreamReader reader, string delimiter)
{
List<char> buffer = new List<char>();
CircularBuffer<char> delim_buffer = new CircularBuffer<char>(delimiter.Length);
while (reader.Peek() >= 0)
{
char c = (char)reader.Read();
delim_buffer.Enqueue(c);
if (delim_buffer.ToString() == delimiter || reader.EndOfStream)
{
if (buffer.Count > 0)
{
if (!reader.EndOfStream)
{
buffer.Add(c);
yield return new String(buffer.ToArray()).Substring(0, buffer.Count - delimeter.Length);
}
else
{
buffer.Add(c);
if (delim_buffer.ToString() != delimiter)
yield return new String(buffer.ToArray());
else
yield return new String(buffer.ToArray()).Substring(0, buffer.Count - delimeter.Length);
}
buffer.Clear();
}
continue;
}
buffer.Add(c);
}
}
private class CircularBuffer<T> : Queue<T>
{
private int _capacity;
public CircularBuffer(int capacity)
: base(capacity)
{
_capacity = capacity;
}
new public void Enqueue(T item)
{
if (base.Count == _capacity)
{
base.Dequeue();
}
base.Enqueue(item);
}
public override string ToString()
{
List<String> items = new List<string>();
foreach (var x in this)
{
items.Add(x.ToString());
};
return String.Join("", items);
}
}
}
вы можете использовать метод split, более подробную информацию на этой странице
http://msdn.microsoft.com/en-us/library/system.string.split.aspx
Bye
Этот фрагмент кода будет читать строку из файла, пока он не встретит "\n".
using (StreamReader sr = new StreamReader(path))
{
string line = string.Empty;
while (sr.Peek() >= 0)
{
char c = (char)sr.Read();
if (c == '\n')
{
//end of line encountered
Console.WriteLine(line);
//create new line
line = string.Empty;
}
else
{
line += (char)sr.Read();
}
}
}
Поскольку этот код читает символ по символу, он будет работать с файлом любой длины, не будучи ограниченным доступной памятью.
Мне нужно решение, которое читается до "\ r\n", и не останавливается на "\n". Решение jp1980 работало, но было очень медленным в большом файле. Итак, я преобразовал решение Майка Сактона для чтения, пока не будет найдена указанная строка.
public static string ReadToString(StreamReader sr, string splitString)
{
char nextChar;
StringBuilder line = new StringBuilder();
int matchIndex = 0;
while (sr.Peek() > 0)
{
nextChar = (char)sr.Read();
line.Append(nextChar);
if (nextChar == splitString[matchIndex])
{
if(matchIndex == splitString.Length - 1)
{
return line.ToString().Substring(0, line.Length - splitString.Length);
}
matchIndex++;
}
else
{
matchIndex = 0;
}
}
return line.Length == 0 ? null : line.ToString();
}
И он называется так...
using (StreamReader reader = new StreamReader(file))
{
string line;
while((line = ReadToString(reader, "\r\n")) != null)
{
Console.WriteLine(line);
}
}