[C#] Zapis listy bool do pliku

Witam!

Mam program który zawiera listę bool’i:

var code = new List<bool>();

Chciałbym to teraz zapisać do pliku aby zajęło jak najmniej miejsca (może po 8 booli jako bajt albo char i to jakoś dalej?)

Wie ktoś jak to zrobić?

Bajt po bajcie? FileStream.WriteByte

A jak te 8 bool na bajt zrobić? Z jednego true/false wiem ale nie o to chodzi,

Tylko, jesli zapiszesz w ten sposób tracisz informację, ile elementów listy jest zapisanych. Możesz oczywiście sprawdzać każdy bit, ale to mało efektowne. Szczególnie, jak będziesz chciał zapisać coś jeszcze.

Najprościej, użyć klasy BinaryFormatter (MSDN), zserializować do pliku. Później tą samą klasą zdeserializujesz.

Poza tym zapisywanie listy nie da Ci małego pliku. Lepiej operować na tablicy.

Ewentualnie jeszcze tak:

boo[] array = code.ToArray(); // to wymaga using System.Linq;
using (var stream = new FileStream("file.bin", FileMode.Create, FileAccess.Write, FileShare.None))
using (var writer = new BinaryWriter(stream))
{
    foreach (bool item in array)
    {
        writer.Write(item);
    }
}

Ale, przy większej ilości danych, to może być wolniejsze od binarnej serializacji.

Jeśli rzeczywiście chcesz zapisywać bool jako bity, to musisz utworzyć sobie zmienną typu byte i w miarę dodawania nowych bitów 0/1 robić tzw przesunięcie bitowe. Zmienną byte później zapisać  za pomocą BinaryWriter, albo FileStream.WriteByte.

Dobra, święta idą, dobry uczynek ;):

byte b = 0x00;
var result = b ^ (1 << pozycja);

Powyższe, ustawia w zmiennej typu byte (b), bit w miejscu na które wskazuje “pozycja”, na 1. Czyli tworzysz sobie zmienną typu byte, iterujesz listę i ustawiasz odpowiednie bity.

Jeśli chcesz ustawić więcej bitów, to w tym momencie z b robisz tablicę b[].

Jak widzisz, w miarę proste, ale jeśli będziesz mieć więcej niz jeden bajt do zapisania, to się trochę skomplikuje sam zapis. Do tego musisz wiedzieć jaka jest kolejność.

Jeśli chcesz ustawić 0 na jakiejś pozycji to wtedy:

b ^ (0 << pozycja);

To tyle.

Można to łatwo zaimplementować z użyciem BitArray.

Działający przykład:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;

namespace ConsoleApplication3
{
    class Program
    {
        static string filename = "data.dat";
        static void Main(string[] args)
        {
            var bits = new Listbool { false, true, true, true, true, true, true, true };
            saveBoolListToFile(bits);

            var bits2 = loadBoolListFromFile();

            for (int i = 0; i bits2.Count; i++)
                Console.Write("bits2[{0}] = {1}\r\n", i, bits2[i]);

            Console.ReadKey();
        }

        private static Listbool loadBoolListFromFile()
        {
            byte[] bytes = File.ReadAllBytes(filename);
            var bitArray = new BitArray(bytes);

            var list = new Listbool(bitArray.Count);
            for (int i = 0; i bitArray.Count; i++)           
                list.Add(bitArray[i]);

            return list;
        }

        private static void saveBoolListToFile(Listbool list)
        {
            byte[] bytes = new byte[list.Count / 8 + (list.Count % 8 == 0 ? 0 : 1)];
            var bitArray = new BitArray(list.Count);
            for (int i = 0; i list.Count; i++)
                bitArray[i] = list[i];

            bitArray.CopyTo(bytes, 0);
            File.WriteAllBytes(filename, bytes);
        }               
    }
}