Я ищу безошибочный способ вернуть StreamReader в начало, особенно когда его базовый BaseStream начинается с BOM, но также должен работать, когда BOM отсутствует.Создание нового StreamReader, который читает с начала потока, также допустимо.
Исходный StreamReader может быть создан с любой кодировкой, а для detectEncodingFromByteOrderMarks установлено значение true или false.Кроме того, чтение может быть сделано или нет до вызова сброса.
Поток может быть произвольным текстом, а файлы, начинающиеся с байтов 0xef, 0xbb, 0xbf, могут быть файлами с спецификацией или файлами, начинающимися с допустимой последовательности символов (например, «» », если ISO-8859-1кодирование), в зависимости от параметров, использованных при создании StreamReader.
Я видел других решений , но они не работают должным образом, когда BaseStream начинается с спецификации.StreamReader запоминает, что он уже обнаружил спецификацию, и первый символ, который возвращается при выполнении чтения, - это специальный символ спецификации.
Также я могу создать новый StreamReader, но не могу знать,исходный StreamReader был создан с параметром detectEncodingFromByteOrderMarks, установленным в значение true или в значение false.
Это то, что я пробовал в первую очередь:
//fails with TestMethod1
void ResetStream1(ref StreamReader sr) {
sr.BaseStream.Position = 0;
sr.DiscardBufferedData();
}
//fails with TestMethod2
void ResetStream2(ref StreamReader sr) {
sr.BaseStream.Position = 0;
sr = new StreamReader(sr.BaseStream, sr.CurrentEncoding, true);
}
//fails with TestMethod3
void ResetStream3(ref StreamReader sr) {
sr.BaseStream.Position = 0;
sr = new StreamReader(sr.BaseStream, sr.CurrentEncoding, false);
}
И вот эти методы метода:
Stream StreamWithBOM = new MemoryStream(new byte[] {0xef,0xbb,0xbf,(byte)'X'});
[TestMethod]
public void TestMethod1() {
StreamReader sr=new StreamReader(StreamWithBOM);
int before=sr.Read(); //reads X
ResetStream(ref sr);
int after=sr.Read();
Assert.AreEqual(before, after);
}
[TestMethod]
public void TestMethod2() {
StreamReader sr = new StreamReader(StreamWithBOM,Encoding.GetEncoding("ISO-8859-1"),false);
int before = sr.Read(); //reads ï
ResetStream(ref sr);
int after = sr.Read();
Assert.AreEqual(before, after);
}
[TestMethod]
public void TestMethod3() {
StreamReader sr = new StreamReader(StreamWithBOM, Encoding.GetEncoding("ISO-8859-1"), true);
int expected = (int)'X'; //no Read() done before reset
ResetStream(ref sr);
int after = sr.Read();
Assert.AreEqual(expected, after);
}
Наконец, я нашел решение (см. Мой собственный ответ), которое проходит все 3 теста, но я хочу посмотреть, возможно ли более элегантное или быстрое решение.