Как удалить все случаи характера от файла в C#?

Я обрабатываю XML-файлы от третьего лица. У этих файлов иногда есть недопустимые символы в них который причины XMLTextReader. Читайте() , чтобы бросить исключение.

Я в настоящее время обращаюсь с этим со следующей функцией:

XmlTextReader GetCharSafeXMLTextReader(string fileName)
{
    try
    {
        MemoryStream ms = new MemoryStream();
        StreamReader sr = new StreamReader(fileName);
        StreamWriter sw = new StreamWriter(ms);
        string temp;
        while ((temp = sr.ReadLine()) != null)
            sw.WriteLine(temp.Replace(((char)4).ToString(), "").Replace(((char)0x14).ToString(), ""));

        sw.Flush();
        sr.Close();
        ms.Seek(0, SeekOrigin.Begin);
        return new XmlTextReader(ms);
    }
    catch (Exception exp)
    {
        throw new Exception("Error parsing file: " + fileName + " " + exp.Message, exp.InnerException);
    }
}

Мой пищеварительный тракт говорит, что должен быть лучший/быстрее способ сделать это. (И да, заставление третьего лица зафиксировать их XMLs было бы большим, но этого не происходит в этом пункте.)

Править: Вот конечное решение, на основе ответа cfeduke:


    public class SanitizedStreamReader : StreamReader
    {
        public SanitizedStreamReader(string filename) : base(filename) { }
        /* other ctors as needed */
       //this is the only one that XmlTextReader appears to use but
       //it is unclear from the documentation which methods call each other
       //so best bet is to override all of the Read* methods and Peek
        public override string ReadLine()
        {
            return Sanitize(base.ReadLine());
        }

        public override int Read()
        {
            int temp = base.Read();
            while (temp == 0x4 || temp == 0x14)
                temp = base.Read();
            return temp;
        }

        public override int Peek()
        {
            int temp = base.Peek();
            while (temp == 0x4 || temp == 0x14)
            {
                temp = base.Read();
                temp = base.Peek();
            }
            return temp;
        }

        public override int Read(char[] buffer, int index, int count)
        {
            int temp = base.Read(buffer, index, count);
            for (int x = index; x < buffer.Length; x++)
            {
                if (buffer[x] == 0x4 || buffer[x] == 0x14)
                {
                    for (int a = x; a < buffer.Length - 1; a++)
                        buffer[a] = buffer[a + 1];
                    temp--; //decrement the number of characters read
                }  
            }
            return temp;
        }

        private static string Sanitize(string unclean)
        {
            if (unclean == null)
                return null;
            if (String.IsNullOrEmpty(unclean))
                return "";
            return unclean.Replace(((char)4).ToString(), "").Replace(((char)0x14).ToString(), "");
        }
    }
2
nl ja de
Строго говоря, если у файлов есть недопустимые символы в них, которые заставляют стандартно-послушного читателя xml задохнуться, они не файлы Xml, просто что-то, что почти похоже на xml - который приносит мне к: Таким образом, у файлов по некоторым причинам есть знаки 4 и 20 усыпанный в ни по какой причине?
добавлено автор O. R. Mapper, источник
Есть ли определенная проблема с тем, что вы имеете? It' s трудно, чтобы сделать что-то лучше, если вы don' t знают почему это потребности быть лучше.
добавлено автор Jon B, источник
Или в этом отношении напишите линию за линией файлу временного секретаря и затем скопируйте назад. Тем путем вы don' у t должно быть все это в памяти.
добавлено автор Jon B, источник
@Kevin, как вы проходите его дважды? You' ре читая его в память и затем вручая его анализатору. Я предполагаю, что анализатор технически проходит его во второй раз, но that' s не преодолимый.
добавлено автор Jon B, источник
Главным образом, it' s просто, которого код "чувствует запах" мне. Прохождение целого файла дважды просто doesn' t кажутся правильным. Это добавляет ко времени обработки, который до сих пор isn' t огромная проблема, но мог стать той. Возможно, I' m думающий должен быть выбор IgnoreInvalidCharacters, или я должен написать класс, чтобы сделать это.
добавлено автор Kevin, источник
С тех пор you' ре читая целый файл в память так или иначе, вы могли просто использовать ReadToEnd вместо того, чтобы обработать линию за линией, тогда звонят , Заменяют на одной последовательности.
добавлено автор prprcupofcoffee, источник

2 ответы

Очистка данных важна. Иногда случаи края - недопустимые символы в "XML" - действительно происходят. Ваше решение правильно. Если вы хотите решение, которое вписывается в.NET структуру в отношении вытекания, реструктурируют ваш код, чтобы вписаться в его собственный Поток:

public class SanitizedStreamReader : StreamReader {
  public SanitizedStreamReader(string filename) : base(filename) { }
  /* other ctors as needed */

 //it is unclear from the documentation which methods call each other
 //so best bet is to override all of the Read* methods and Peak
  public override string ReadLine() {
    return Sanitize(base.ReadLine());
  }

 //TODO override Read*, Peak with a similar logic as this.ReadLine()
 //remember Read(Char[], Int32, Int32) to modify the return value by
 //the number of removed characters

  private static string Sanitize(string unclean) {
    if (String.IsNullOrEmpty(unclean)
      return "";
    return unclean.Replace(((char)4).ToString(), "").Replace(((char)0x14);
  }
}

С этим новым SanitizedStreamReader вы будете в состоянии приковать его цепью в обработку потоков по мере необходимости, вместо того, чтобы полагаться на волшебный метод, чтобы убрать вещи и подарить вам XmlTextReader:

return new XmlTextReader(new SanitizedStreamReader("filename.xml"));

По общему признанию это может быть большим количеством работы, чем необходимый, но вы получите гибкость от этого подхода.

6
добавлено
+1 добавил бы Прочитанный, Быстрый взгляд и ReadToEnd.
добавлено автор paparazzo, источник
Спасибо @cfeduke, я осуществил решение на основе вашего ответа.
добавлено автор Kevin, источник

XML касается в стороне, если бы файл не достаточно большой, чтобы гарантировать обработку последовательно, я упростил бы код до чего-то вдоль тех линий:

var xml = File.ReadAllText(pathName);
var fixedXml = xml.Replace(((char)4).ToString(), "").Replace(((char)0x14).ToString(), "");
File.WriteAllText(pathName, fixedXml);
1
добавлено