2014-09-23 4 views
0

У меня есть файл, который содержит записи для данных и изображений сотрудников. Каждая запись для одного сотрудника и его данные, его образ и образ его жены. Я не могу изменить файловую структуруЧтение двоичных данных (изображений) из разделенного файла

Существуют разделители между текстовыми данными и изображениями.

Вот пример одной записи:

номер записи D01 = имя сотрудника = IMG1 = сотрудник изображения ~ \ IMG2 = жена изображение ^!\ г \ п

(D01 = & ! = IMG1 = & ~ \ IMG2 = & ^!) являются сепараторы

Это код, как файл был написан:

FileStream fs = new FileStream(filePath, FileMode.Create); 
StreamWriter sw = new StreamWriter(fs, Encoding.UTF8); 
BinaryWriter bw = new BinaryWriter(fs); 

sw.Write(employeeDataString); 
sw.Write("!=IMG1="); 
sw.Flush(); 

bw.Write(employeeImg, 0, employeeImg.Length); 
bw.Flush(); 

sw.Write(@"~\IMG2="); 
sw.Flush(); 

bw.Write(wifeImg, 0, wifeImg.Length); 
bw.Flush(); 

sw.Write("^!"); 
sw.Flush(); 

sw.Write(@"\r\n"); 
sw.Flush(); 

Итак, как читать этот файл?

+4

Фундаментально, у вас есть проблемы, есть - если вы читаете данные изображения, чтобы определить длину файла там (если он даже поддерживает его!) вы не можете надежно обнаружить, когда файл закончится, и начнется следующая часть записи. В основном это разбитый формат файла. –

+0

@JonSkeet полная запись заканчивается на «\ r \ n» –

+2

И что заставляет вас думать, что файл изображения не может содержать байты, которые - при интерпретации текста - являются '\ r \ n'? –

ответ

0

Там много видов файлов; три наиболее распространенных способа хранения записей:

  • Зарегистрированные записи фиксированного размера, в идеале с полями фиксированного размера. Очень просто реализовать произвольный доступ.
  • Tagged файлы с тегами и данные переплетаются. Немного сложный, но очень гибкий и по-прежнему достаточно читаемый, поскольку теги содержат позиции и длину данных.
  • А после этого есть разделенные файлы. Всегда боль.

два вопроса:

  • Вы должны быть уверены, что разделители никогда в данных. Не 100% возможно, если у вас есть двоичные данные, такие как изображения ..
  • Там не эффективный способ получить доступ к отдельным записям ..

Игнорирование 1-й выпуск, вот кусок кода, который будет читать все записи в список классов ARecord.

FileStream fs; 
BinaryReader br; 
List<ARecord> theRecords; 

class ARecord 
{ 
    public string name { get; set; } 
    public Image img1 { get; set; } 
    public Image img2 { get; set; } 
} 

int readFile(string filePath) 
{ 
    fs = new FileStream(filePath, FileMode.Open); 
    br = new BinaryReader(fs, Encoding.UTF8); 

    theRecords = new List<ARecord>(); 
    ARecord record = getNextRecord(); 
    while (record != null) 
    { 
     theRecords.Add(record); 
     record = getNextRecord(); 
    } 
    return theRecords.Count; 
} 

ARecord getNextRecord() 
{ 
    ARecord record = new ARecord(); 

    MemoryStream ms; 
    System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(); 
    byte[] sepImg1 = enc.GetBytes(@"!=IMG1="); 
    byte[] sepImg2 = enc.GetBytes(@"~\IMG2="); 
    byte[] sepRec = enc.GetBytes(@"^!\r\n"); 

    record.name = enc.GetString(readToSep(sepImg1)); 

    ms = new MemoryStream(readToSep(sepImg2)); 
    if (ms.Length <= 0) return null;    // check for EOF 
    record.img1 = Image.FromStream(ms); 

    ms = new MemoryStream(readToSep(sepRec)); 
    record.img2 = Image.FromStream(ms); 

    return record; 
} 

byte[] readToSep(byte[] sep) 
{ 
    List<byte> data = new List<byte>(); 
    bool eor = false; 
    int sLen = sep.Length; 
    int sPos = 0; 
    while (br.BaseStream.Position < br.BaseStream.Length && !eor) 
    { 
     byte b = br.ReadByte(); 
     data.Add(b); 
     if (b != sep[sPos]) { sPos = 0; } 
     else if (sPos < sLen - 1) sPos++; else eor = true; 
    } 
    if (data.Count > sLen) data.RemoveRange(data.Count - sLen , sLen); 
    return data.ToArray(); 
} 

Примечание:

  • Там нет проверки вообще ошибки.
  • Следите за этими разделителями! это @ действительно правильно ??
  • Расширение кода для создания номера записи оставляется вам
+0

Это должно работать, но я должен сказать, что ваше соглашение об именах немного странно для C# (название класса с верблюжьей оболочкой, поля в верхнем регистре). – Groo

+1

Вы правы. Я исправил. Это происходило из двух версий в одном решении параллельно. Иногда мне нравится использовать короткие имена Caps для локальных ссылок на объекты, чтобы выделить их как «Label L = (Label) отправитель» – TaW

Смежные вопросы