2015-10-31 2 views
0

мне трудно выразить себя, так что я буду прыгать прямо в кодИщет особое значение при использовании BinaryWriter

FileStream stream = new FileStream("//ignoreThis//demo.bin", 
         FileMode.Append, FileAccess.Write, FileShare.Write)); 
BinaryWriter writer = new BinaryWriter(stream); 
writer.Write(myNum); 
writer.Write(myString); 

я могу назвать этот метод несколько раз, и я знаю, что каждый раз, когда я делаю так, он добавит новые данные в конец файла «demo.bin». Теперь я пытаюсь написать метод, где я могу обратиться к моему третьему экземпляру (я не уверен, могу ли я это назвать). Основная проблема заключается в том, что переменные имеют разный размер, хотя я использую этот код, чтобы сделать String «фиксированной» длиной 20 (я знаю, что это не работает, когда кто-то пишет строку длиной более 20, но Я уже написал проверку, чтобы убедиться, что они не превышают этот предел)

Вот код, я использую, чтобы сделать строки постоянной длины

public String MakeFixedSize(int length, String inputString) 
{ 
    return inputString.PadRight(length, '\0'); 
} 

насколько я знаю, INT имеет фиксированный размер и длительность, которые я использую в этой программе (не в приведенном выше коде)

+0

Посмотрите [MSDN] (https://msdn.microsoft.com/de-de/library/vstudio/yzxa6408% 28v = vs.100% 29.aspx? F = 255 & MSPPError = -2147217396) - Это на немецком языке, но вы можете переключить язык, я надеюсь. Код объясняет, что делать, когда wrting (чтение строки с помощью бинарного журнала). Суть в том, что строки написаны бинарным шрифтом как «длина-префикс», поэтому вы можете набирать длину, просматривая первые два байта. лучше использовать «BinaryFormatter» и сериализовать данные. См. [здесь] (http://stackoverflow.com/questions/15750154/serialize-an-object-in-c-sharp-and-get-byte-stream) – TaW

+0

Что означает «писать прямо в папку»? Один файл для каждой записи? – TaW

+0

Я имел в виду файл. Я хочу разделить каждую запись различимым образом, чтобы быстрее выполнять поиск без использования сериализации (Т.е. с использованием массива байтов и сохраняя это через BinaryWriter и прочитывая его обратно, анализируя его). У меня уже есть код для синтаксического анализа и еще много чего, но мне нужен хороший способ разделить записи. – Gabrielus

ответ

0

Есть много способов сделать это, и я не уверен, что ch является лучшим для вашего случая.

Если вы можете и хотите создавать записи строго фиксированного размера, вы можете искать правильное положение прямо. Это может быть быстрее для больших объемов данных.

Или вы могли бы рассчитывать на BinaryWriter префикс каждую строку с двумя байтами длиной, а затем прочитать нужное количество символов ..

Если вы хотите, чтобы оставаться более гибкими и держать вещи просто вы могли бы пойти на сериализацию с BinaryFormatter:

Создать сериализуемую класс:

[Serializable] 
public class MyClass 
{ 
    public string Name; 
    public int Number; 
} 

Тогда вы можете написать несколько экземпляров на диск с помощью BinaryFormatter:

string fileName = "yourfileName"; 

FileStream stream = new FileStream(fileName, 
         FileMode.Append, FileAccess.Write, FileShare.Write); 
var formatter = new BinaryFormatter(); 
formatter.Serialize(stream, new MyClass() { Name = "A", Number = 12365 }); 
formatter.Serialize(stream, new MyClass() { Name = "B", Number = 2365 }); 
formatter.Serialize(stream, new MyClass() { Name = "C", Number = 365 }); 
stream.Close(); 

И читать его обратно, может быть, в List<T>, все еще используют один и тот же форматировщик:

FileStream stream2 = new FileStream(fileName, FileMode.Open, FileAccess.Read); 
List<MyClass> myClassList = new List<MyClass>(); 

while (stream2.Position < stream2.Length) 
    myClassList.Add((MyClass)formatter.Deserialize(stream2)); 

Теперь вы можете получить доступ к myClassList[2] ..

Update:

Похоже вы можете это сделать, если вы уверены в длине записи:

using (BinaryWriter binWriter = new BinaryWriter(File.Open(fileName, FileMode.Create))) 
{ 
    binWriter.Write("RAller"); 
    binWriter.Write(123); 
    binWriter.Write("RoBler"); 
    binWriter.Write(23); 
    binWriter.Write("RolCer"); 
    binWriter.Write(3); 
    binWriter.Write("RolDDr"); 
    binWriter.Write(423); 
    binWriter.Write("REEler"); 
    binWriter.Write(523); 
    binWriter.Write("RFFler"); 
    binWriter.Write(66); 
} 

using (BinaryReader br = new BinaryReader(File.Open(fileName, FileMode.Open))) 
{ 
    // string < 255 seems to get only a one byte length prefix: 
    int recLen = 1 + 6 + 4; 

    br.BaseStream.Seek(recLen * 3, SeekOrigin.Begin); 
    string s = br.ReadString(); 
    int i = br.ReadInt32(); 
} 

Короткие строки получить только один байт длины счетчик:

enter image description here

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

Я не могу представить, почему вы хотели бы этого, если только данные действительно большие.

Ну, иногда требования таковы, каковы они есть, и иногда они требуют допроса ..

+0

Задача специально требует, чтобы я не использовал сериализацию, а сохранил значения напрямую. Не могли бы вы расширить префикс строки? Я не знаком с концепцией – Gabrielus

+0

[link] (https://msdn.microsoft.com/de-de/library/yzxa6408%28v=vs.110%29.aspx) объясняет это довольно хорошо: _A length-prefixed string представляет длину строки, префикс строки в один байт или слово, которое содержит длину этой строки. Этот метод сначала записывает длину строки как кодированное без знака UTF-7 целое число, а затем записывает много символов в поток, используя текущую кодировку экземпляра BinaryWriter._ Стоит изучить код, где вы можете увидеть, как читать назад различные типы .. – TaW

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