2011-03-18 4 views
5

배열 모델 개체를 이진 스트림에 직렬화하고자합니다. 모델 클래스는 주로 문자열 및 정수 속성을가집니다.C의 레코드가 1000 개가있는 이진 파일 형식

클래스를 [Serializable]로 표시하고 이진 형식 지정자를 사용할 수 있다고 생각하지만이 방법이 내 우선 순위가 더 작은 파일로 유지되는 최선의 방법이라고 생각하는지 알고 싶습니다. 가능하면 낮은 대역폭 연결을 통해 전송할 수 있습니다 (파일을 압축/압축 해제 할 수도 있음).

파일에는 1000 개의 레코드가있을 수 있으므로 전체 파일을 한 번에 메모리에 저장하지 않고 디스크에 추가하고 디스크 레코드에서 레코드를 읽을 수 있기를 바랍니다.

그래서 내 우선 순위는 작은 파일 크기와 효율적인 메모리 사용입니다.

아마도이 용도로 미리 작성된 프레임 워크가 있습니까? XML 및 CSV 파일을 사용하면 쉽게 할 수 있습니다! 바라건대 그것은 맞춤형 바이너리 형식이기도하다.

감사

답변

6

나는 매우 효율적으로 protobuf.net을 제안합니다.

그렇다고해서 컬렉션의 개별 개체를 직렬화/비 직렬화 할 수는 없습니다. 그 부분을 스스로 구현해야합니다.

  • 한 가지 해결책은 다음과 같습니다. 개체를 개별 파일로 폴더에 저장합니다. 파일 이름에는 참조를 포함하므로 이름을 기반으로 필요한 객체를 찾을 수 있습니다.

  • 또 하나의 파일이 있지만 파일의 모든 개체 및 위치 목록을 유지하는 색인 ​​파일을 유지하는 것입니다. 이것은 파일의 중간에있는 오브젝트를 저장할 때 다른 모든 주소를 이동해야하고 b- 트리가 더 효과적 일 때와 같이 훨씬 더 복잡합니다.

+2

두 번째 옵션은 [FileDB] (http://nuget.org/List/Packages/FileDB)입니다. –

+0

Martinho 감사합니다. 나는 FileDB를 좋아했다! – Aliostad

1

당신은 BinaryFormatter를 사용할 수 있습니다. 작은 파일을 원한다면 좋은 솔루션이지만 도메인에 가장 적합한 솔루션인지는 알 수 있습니다. 그래도 한 번에 하나의 레코드를 읽을 수 있다고 생각하지 않습니다.

이 예제 코드는 DataSet입니다. 이러한 확장 메서드는 사용자 지정 DataSet을 직렬화합니다. 올바르게 호출하면 BinaryFormatter를 사용할 수있는 형식을 만드는 가장 쉬운 방법입니다.

public static TDataSet LoadBinary<TDataSet>(Stream stream) where TDataSet : DataSet 
{ 
    var formatter = new BinaryFormatter(); 
    return (TDataSet)formatter.Deserialize(stream); 
} 

public static void WriteBinary<TDataSet>(this TDataSet dataSet, Stream stream) where TDataSet : DataSet 
{ 
    dataSet.RemotingFormat = SerializationFormat.Binary; 
    var formatter = new BinaryFormatter(); 
    formatter.Serialize(stream, dataSet); 
} 

당신은 또한 (간단히 말해서 C# 4.0, Albahari & Albahari에 따라) 직렬화를 처리하는 .NET의 새로운 '표준'방식이다 DataContractSerializer 한 번 봐, 걸릴 수 있습니다. 이 경우 Best Practices: Data Contract Versioning을 읽는 것이 좋습니다. 다음은 작은 파일을 원하기 때문에 상황에 직접적으로 적용되지는 않지만 XML 및 JSON에서 직렬화하는 방법의 예입니다. 하지만 파일을 압축 할 수 있습니다.

/// <summary> 
/// Converts this instance to XML using the <see cref="DataContractSerializer"/>. 
/// </summary> 
/// <typeparam name="TSerializable"> 
/// A type that is serializable using the <see cref="DataContractSerializer"/>. 
/// </typeparam> 
/// <param name="value"> 
/// The object to be serialized to XML. 
/// </param> 
/// <returns> 
/// Formatted XML representing this instance. Does not include the XML declaration. 
/// </returns> 
public static string ToXml<TSerializable>(this TSerializable value) 
{ 
    var serializer = new DataContractSerializer(typeof(TSerializable)); 
    var output = new StringWriter(); 
    using (var writer = new XmlTextWriter(output) { Formatting = Formatting.Indented }) 
    { 
     serializer.WriteObject(writer, value); 
    } 
    return output.GetStringBuilder().ToString(); 
} 

/// <summary> 
/// Converts this instance to XML using the <see cref="DataContractSerializer"/> and writes it to the specified file. 
/// </summary> 
/// <typeparam name="TSerializable"> 
/// A type that is serializable using the <see cref="DataContractSerializer"/>. 
/// </typeparam> 
/// <param name="value"> 
/// The object to be serialized to XML. 
/// </param> 
/// <param name="filePath">Path of the file to write to.</param> 
public static void WriteXml<TSerializable>(this TSerializable value, string filePath) 
{ 
    var serializer = new DataContractSerializer(typeof(TSerializable)); 
    using (var writer = XmlWriter.Create(filePath, new XmlWriterSettings { Indent = true })) 
    { 
     serializer.WriteObject(writer, value); 
    } 
} 

/// <summary> 
/// Creates from an instance of the specified class from XML. 
/// </summary> 
/// <typeparam name="TSerializable">The type of the serializable object.</typeparam> 
/// <param name="xml">The XML representation of the instance.</param> 
/// <returns>An instance created from the XML input.</returns> 
public static TSerializable CreateFromXml<TSerializable>(string xml) 
{ 
    var serializer = new DataContractSerializer(typeof(TSerializable)); 

    using (var stringReader = new StringReader(xml)) 
    using (var reader = XmlReader.Create(stringReader)) 
    { 
     return (TSerializable)serializer.ReadObject(reader); 
    } 
} 

/// <summary> 
/// Creates from an instance of the specified class from the specified XML file. 
/// </summary> 
/// <param name="filePath"> 
/// Path to the XML file. 
/// </param> 
/// <typeparam name="TSerializable"> 
/// The type of the serializable object. 
/// </typeparam> 
/// <returns> 
/// An instance created from the XML input. 
/// </returns> 
public static TSerializable CreateFromXmlFile<TSerializable>(string filePath) 
{ 
    var serializer = new DataContractSerializer(typeof(TSerializable)); 

    using (var reader = XmlReader.Create(filePath)) 
    { 
     return (TSerializable)serializer.ReadObject(reader); 
    } 
} 

public static T LoadJson<T>(Stream stream) where T : class 
{ 
    var serializer = new DataContractJsonSerializer(typeof(T)); 
    object readObject = serializer.ReadObject(stream); 
    return (T)readObject; 
} 

public static void WriteJson<T>(this T value, Stream stream) where T : class 
{ 
    var serializer = new DataContractJsonSerializer(typeof(T)); 
    serializer.WriteObject(stream, value); 
} 
1

나는 서버에 많은 요청을 제공하는 높은 페이로드에서 그것을 사용, 그것은 매우 가볍고 매우 빨리, 직렬화없이 객체와 같은 객체를 저장할 수의 SQL Server Compact를 사용하는 것이 좋습니다 것입니다.

저장하려는 개체를 변경할 때 매우 고통 스럽기 때문에 데이터를 이진 형식 (직렬화 된 형식)으로 저장하는 것을 권장하지 않습니다. 전체 컬렉션을 deserialize해야하기 때문에 저장하고있는 것을 볼 필요가 있으면 또한 고통 스럽습니다.

보내는 경우 필자는 필요한 경우 Zip 압축을 사용하여 XML 직렬화를 사용하는 것이 더 좋습니다. XML 형식을 사용하면 보내는 내용을 확인하거나 테스트를 수행해야 할 경우 디버깅을 훨씬 쉽게 할 수 있습니다.

0

작게 만들고 싶다면 직접하십시오. 필요한 데이터 만 저장하십시오. 예를 들어 255 개의 서로 다른 값만있는 경우 한 바이트를 사용하십시오.

http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

나는 거의 항상 데이터를 저장하기 위해 다음과 같은 간단한 구조를 사용

ID (USHORT)

DATA_SIZE (단위) 크기 DATA_SIZE의

데이터

가지고 있어야하는 정보 만 저장하고 어떻게 사용되는지 생각하지 마십시오. 로드 할 때 데이터를 사용하는 방법을 고려해야합니다.

0

개체 자체에 BinaryFormatter를 사용하거나 다른 곳에서 제안 된대로 protobuf.net을 사용하고 싶습니다.

랜덤 액세스 측면이 매우 중요하다면 (레코드로 레코드 읽기 및 추가) 색인 파일과 각 개체를 포함하는 zip 파일 (또는 유사한 파일)을 zip (또는 작은 컬렉션).

이렇게하면 압축 된 미니 파일 시스템을 효과적으로 만들 수 있으며 레코드에 개별적으로 액세스 할 수 있습니다.

2

또 다른 옵션은 고정 폭 텍스트 파일 형식으로 직렬화하고 ZIP에서 압축을 처리하도록하는 것입니다. 고정 폭이란 전체 파일을 메모리에로드하지 않고도 MemoryMappedFile을 사용하여 각 레코드를 쉽게 찾을 수 있음을 의미합니다.