데이터가 어떻게 직렬화되었는지 (프로토콜이나 데이터 설명을 지정하지 않음) 알지 못합니다. 그러나 당신은 다른 질문에 대한 해답이 당신의 문제를 해결할 것이라고 말했습니다. 나는 당신에게 다음과 같은 정교함을 제공하고있다 : 당신이 내 구현을 변경하여 (다음 예에서와 같이) 바이너리 스트림을 사용하는 대신 데이터가 사용자의 포맷에 따라 파싱되도록하는 것이 쉽다.
나는 당신이 말하는 질문에서 해결책을 얻기 위해 자신의 속성을 구현할 것을 제안했다.
여기에 구현 예를 들려 줄 수 있습니다 (단지 예일 뿐이므로 생산 사용 전에 편집하십시오 ...) :
파일 데이터 구조를 포함 :
//MyData.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FixedLengthFileReader
{
class MyData
{
[Layout(0, 10)]
public string field1;
[Layout(10, 4)]
public int field2;
[Layout(14, 8)]
public double field3;
public override String ToString() {
return String.Format("String: {0}; int: {1}; double: {2}", field1, field2, field3);
}
}
}
속성 :
// LayoutAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FixedLengthFileReader
{
[AttributeUsage(AttributeTargets.Field)]
class LayoutAttribute : Attribute
{
private int _index;
private int _length;
public int index
{
get { return _index; }
}
public int length
{
get { return _length; }
}
public LayoutAttribute(int index, int length)
{
this._index = index;
this._length = length;
}
}
}
리더 구현 예 :
//FixedLengthReader.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
namespace FixedLengthFileReader
{
class FixedLengthReader
{
private Stream stream;
private byte[] buffer;
public FixedLengthReader(Stream stream)
{
this.stream = stream;
this.buffer = new byte[4];
}
public void read<T>(T data)
{
foreach (FieldInfo fi in typeof(T).GetFields())
{
foreach (object attr in fi.GetCustomAttributes())
{
if (attr is LayoutAttribute)
{
LayoutAttribute la = (LayoutAttribute)attr;
stream.Seek(la.index, SeekOrigin.Begin);
if (buffer.Length < la.length) buffer = new byte[la.length];
stream.Read(buffer, 0, la.length);
if (fi.FieldType.Equals(typeof(int)))
{
fi.SetValue(data, BitConverter.ToInt32(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(bool)))
{
fi.SetValue(data, BitConverter.ToBoolean(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(string)))
{
// --- If string was written using UTF8 ---
byte[] tmp = new byte[la.length];
Array.Copy(buffer, tmp, tmp.Length);
fi.SetValue(data, System.Text.Encoding.UTF8.GetString(tmp));
// --- ALTERNATIVE: Chars were written to file ---
//char[] tmp = new char[la.length - 1];
//for (int i = 0; i < la.length; i++)
//{
// tmp[i] = BitConverter.ToChar(buffer, i * sizeof(char));
//}
//fi.SetValue(data, new string(tmp));
}
else if (fi.FieldType.Equals(typeof(double)))
{
fi.SetValue(data, BitConverter.ToDouble(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(short)))
{
fi.SetValue(data, BitConverter.ToInt16(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(long)))
{
fi.SetValue(data, BitConverter.ToInt64(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(float)))
{
fi.SetValue(data, BitConverter.ToSingle(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(ushort)))
{
fi.SetValue(data, BitConverter.ToUInt16(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(uint)))
{
fi.SetValue(data, BitConverter.ToUInt32(buffer, 0));
}
else if (fi.FieldType.Equals(typeof(ulong)))
{
fi.SetValue(data, BitConverter.ToUInt64(buffer, 0));
}
}
}
}
}
}
}
및 프로그램 구현의 마지막 예 (매우 간단합니다) :
// Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace FixedLengthFileReader
{
class Program
{
static void Main(string[] args)
{
MyData md = new MyData();
Console.WriteLine(md);
Stream s = File.OpenRead("testFile.bin");
FixedLengthReader flr = new FixedLengthReader(s);
flr.read(md);
s.Close();
Console.WriteLine(md);
}
}
}
당신은 예를 들어 바이너리 파일에 대해이 코드를 테스트하려면 다음 16 진수 코드를 가진 파일을 만들 수 있습니다
41 42 43 44 45 46 47 48 49 4A 01 00 00 00 00 00 00
00 00 00 E0 3F
에 대한 바이트를 나타냅니다
- 문자열을 ABCDEFGHIJ (10 바이트)
- 정수 1 (4 바이트)
- 더블 0.5 (8 바이트)
(16 진수 코드를 추가하고 testFile.bin으로 저장 한 파일을 만들었습니다.)
고정 길이 파일은 어떻게 생겼습니까? 우리가 무엇을 제안하기 전에 내용을 엿볼 수 있습니까? –
@theghostofc 지금 StreamReader를 구현하고 나중에 spilled 또는 indexof와 같은 간단한 문자열 함수를 사용하여 데이터를 얻으려고합니다. 그러나이 모든 것이 건너 뛸 수 있는지 궁금합니다. 위에 제공된 링크 중 하나와 비슷하지만, 코드가 훨씬 깨끗해 보일 것입니다. 제발 여기에 코드를 요구하지 않고 단지이 경우에 어떤 옵션이 있는지 알고 싶지는 마십시오. – IFlyHigh
고정 길이 파일 샘플에 대해서도 내 질문을 편집했습니다. – IFlyHigh