매우 많은 양의 이진 데이터를 파일에서 읽어야합니다. 고정 된 레코드 크기 (38)가 있으며 한 번에 여러 레코드를 건너 뜁니다. FileStrea, Position 또는 Seek를 사용하여이 작업을 시도했지만 너무 시간이 많이 걸리는 것처럼 보입니다. 따라서 10 개의 레코드를 건너 뛰더라도 10 개의 파일을 읽지는 않습니다.바이너리 파일의 일부를 FileStream.Position보다 빨리 건너 뛸 수있는 방법이 있습니까?
여기에 SSCCE가 있습니다.
중재자 참고 : 이것은 반복 질문이 아니며, 다른 질문에서 추출한 후속 작업으로 다른 초점을 탐구 할 수 있습니다.
두 개의 직렬화 및 비 직렬화 버튼을 만들어야합니다.
Serialize는 더미 데이터 파일을 만듭니다.
역 직렬화를 통해 읽습니다.
전체 파일의 원시 읽기를 보려면 fs.Position 행을 주석 처리하십시오. 내 컴퓨터에서 12 초가 걸립니다. 그런 다음 주석 처리를 제거하면 매번 10 개의 레코드가 건너 뜁니다. 속도가 10 배 향상 되길 바랬지 만, 내 컴퓨터에서는 8 초가 걸렸습니다. 그래서 나는 변화 fs.Position 비싸다고 가정합니다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ProtoBuf;
using System.IO;
using System.Diagnostics;
namespace BinTest3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Serialize_Click(object sender, EventArgs e)
{
FileStream outBin = null;
string binFileName = @"C:\binfile.dft";
outBin = File.Create(binFileName, 2048, FileOptions.None);
DateTime d = DateTime.Now;
TickRecord tr = new TickRecord(d, 1.02, 1.03,200,300);
for (int i =0; i < 20000000; i++)
{
tr.BidPrice += 1;
Serializer.SerializeWithLengthPrefix(outBin, tr, PrefixStyle.Base128);
}
outBin.Close();
label1.Text = "Done ";
}
private void Deserialize_Click(object sender, EventArgs e)
{
Stopwatch sw = new Stopwatch();
sw.Start();
FileStream fs;
string binFileName = @"C:\binfile.dft";
fs = new FileStream(binFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4 * 4096);
long skipRate =10;
int count = 0;
TickRecord tr;
long skip = (38*skipRate);
try
{
while ((tr = Serializer.DeserializeWithLengthPrefix<TickRecord>(fs, PrefixStyle.Base128)) != null) //fs.Length > fs.Position)
{
count++;
fs.Position += skip; //Comment out this line to see raw speed
}
}
catch (Exception)
{
}
fs.Close();
sw.Stop();
label1.Text = "Time taken: " + sw.Elapsed + " Count: " + count.ToString("n0");
}
}
[ProtoContract]
public class TickRecord
{
[ProtoMember(1, DataFormat = DataFormat.FixedSize)]
public DateTime DT;
[ProtoMember(2)]
public double BidPrice;
[ProtoMember(3)]
public double AskPrice;
[ProtoMember(4, DataFormat = DataFormat.FixedSize)]
public int BidSize;
[ProtoMember(5, DataFormat = DataFormat.FixedSize)]
public int AskSize;
public TickRecord()
{
}
public TickRecord(DateTime DT, double BidPrice, double AskPrice, int BidSize, int AskSize)
{
this.DT = DT;
this.BidPrice = BidPrice;
this.AskPrice = AskPrice;
this.BidSize = BidSize;
this.AskSize = AskSize;
}
}
}
디스크를 찾아서 ** 모든 시간을 디스크 읽기에 소비하지 않아야합니다 **. 1 개의 레코드 만 읽더라도 1 밀리 초 시간이 없어도 –
아니요, 더 빠른 방법은 없습니다. 빠른 탐색을 원하면 SSD를 사용하십시오. 또한, 당신이하는 것처럼 많은 작은 탐색을하는 것은 특히 비효율적입니다. 파일의 큰 부분을 건너 뛰면 훨씬 큰 차이가 있음을 알 수 있습니다. –