2017-02-06 5 views
0

저는 (Car 클래스의) 객체를 직렬화하여 XML 파일로 저장합니다. 그러나 때로는 (매우 드문 경우지만 복제 할 수 없습니다.) 파일 크기가 올바르더라도 null 문자 (ASCII 코드가 0 인 문자) 만 포함 된 파일을 얻습니다.XML 직렬화로 인해 문자가 널 문자로 가득합니다.

public void SaveCar(Car car) 
{ 
    var serializer = new XmlSerializer(typeof(Car)); 
    using (var stream = new MemoryStream()) 
    { 
     serializer.Serialize(stream, car); 
     byte[] binaryCar = stream.ToArray(); 
     FileHelper.WriteAllBytes(@"C:\car.xml", binaryCar); 
    } 
} 

FileHelper.WriteAllBytes가 존재하지 않는 경우는 부모 디렉토리를 생성하는 것을 제외하고 System.IO.File.WriteAllBytes과 동일합니다.

public static class FileHelper 
{ 
    public static void WriteAllBytes(string path, byte[] bytes) 
    { 
     CreateParentDirectoryForPathIfDoesntExist(path); 
     File.WriteAllBytes(path, bytes); 
    } 

    public static void CreateParentDirectoryForPathIfDoesntExist(string filePath) 
    { 
     var file = new FileInfo(filePath); 
     if (file.Exists) 
     { 
      return; 
     } 

     if (file.Directory != null && !file.Directory.Exists) 
     { 
      Directory.CreateDirectory(file.Directory.FullName); 
     } 
    } 
} 

어떤 원인 일 수 있습니까? 인코딩 문제?

+1

가 '가끔'할 때입니다 기능을 다음과 같이 테스트되었습니다? 특정 파일? 특정 차? 'NUL' 문자로 파일을 만드는 것을 확실하게 증명하는 [mcve]가 유용 할 것입니다. –

+3

그리고'FileHelper'에 대해 더 자세히 설명하십시오. 후보 문제 소스처럼 보입니다. –

+1

질문에 'FileHelper' 코드를 포함하십시오. –

답변

1

귀하의 'SaveCar'방법 솔기는 잘 작동합니다,하지만 당신은 당신이 당신의 예에서 가장 큰 차이는 시리얼 인스턴스가 한 번 생성되고 UTF8 인코딩을 강제로입니다 구현

public class XmlCar { 
    public static readonly Encoding Utf8Encoding = Encoding.UTF8; 
    public static readonly XmlSerializer CarSerializer = new XmlSerializer(typeof(Car)); 
    public static Car Load(string path) { 
     using (var stream = new StreamReader(path, Utf8Encoding, false)) { 
      using (var reader = XmlReader.Create(stream)) { 
       return (Car)CarSerializer.Deserialize(reader); 
      } 
     } 
    } 
    public static void Save(string path, Car instance) { 
     using (var stream = new StreamWriter(path, false, Utf8Encoding)) { 
      using (var writer = XmlWriter.Create(stream)) { 
       CarSerializer.Serialize(writer, instance); 
      } 
     } 
    } 
} 

를 사용할 수 있습니다합니다.

귀하의 방법은 다음과 같은 클래스로 시도 된

[XmlRoot] 
public class Car { 
    [XmlAttribute] 
    public string Model { get; set; } 
    [XmlAttribute] 
    public string Plate { get; set; } 
    [XmlArray] 
    [XmlArrayItem] 
    public List<Part> Parts { get; set; } 
} 
[XmlRoot] 
public class Part { 
    [XmlAttribute] 
    public string Type { get; set; } 
    [XmlAttribute] 
    public string Code { get; set; } 
    [XmlAttribute] 
    public int Quantity { get; set; } 
} 

이 샘플이이 사이트에서 발견 된 샘플에서 파생 있습니다.

파일 이름에 대한 제어를 위해 Yours 메서드가 약간 변경되었습니다.

public static void SaveCar(Car car, int i) 
    { 
     var serializer = new XmlSerializer(typeof(Car)); 
     using (var stream = new MemoryStream()) 
     { 
      serializer.Serialize(stream, car); 
      byte[] binaryCar = stream.ToArray(); 
      File.WriteAllBytes("car"+ i + ".xml", binaryCar); 
     } 
    } 

방법은

static void Main(string[] args) { 

     var random = new Random(); 
     var cars = new List<Car>(); 

     for (var c = 0; c < 10; c++) { 
      var car = new Car() { 
       Model = Guid.NewGuid().ToString(), 
       Plate = (random.Next(500) + 500).ToString(), 
       Parts = new List<Part>() 
      }; 
      for (var p = 0; p < 100; p++) { 
       car.Parts.Add(new Part() { 
        Type = Guid.NewGuid().ToString(), 
        Code = (random.Next(500) + 1500).ToString(), 
        Quantity = random.Next(100) + 1 
       }); 
      } 
      SaveCar(car, c); 
      cars.Add(XmlCar.Load("car" + c + ".xml")); 
     } 
    } 
+1

['XmlTextReader'] (https://msdn.microsoft.com/en-us/library/system.xml.xmltextreader (v = vs.110) .aspx) 및 ['XmlTextWriter'] (https : // msdn Microsoft.com/ko-kr/library/system.xml.xmltextwriter (v = vs.110) .aspx)는 권장되지 않습니다 (링크 된 문서 참조). 'XmlReader.Create'와'XmlWriter.Create'를 사용해야합니다. 'StreamReader'와'StreamWriter'는 기본적으로 UTF8로되어 있습니다 만, 파일 경로를 받아들이는'Create' 오버로드를 사용한다면 둘 다 필요하지 않습니다. 이러한 변화가 큰 타격을주지는 않지만, 나는 그들이 질문에 대답하는 것을 보지 못한다. –

+0

루프에서 복제를 시도해 주셔서 감사합니다. 불행히도 이런 식으로 오류를 찾을 수 없습니다. 내가 오류의 원인을 찾지 못하면 해결책을 찾을 것입니다. 아마도 인코딩의 부족이 문제의 원인 일 것입니다. – Bedford

+1

@Bedford, 이후에 읽을 스트림을 작성할 때마다 Flush()를 호출했는지 확인하십시오 (지원되는 경우 해당 내용이 모두 들어 있는지 확인하십시오). 또한 유용한 것으로 입증 될 수있는 것은 다음 읽기 전에 스트림의 시작 부분으로 위치를 이동하는 것입니다. – recineshto