Pracuję nad problemem w Programming Pearls - w szczególności implementacją programu, który sortuje plik zawierający najwyżej 10 000 000 liczb całkowitych (kolumna 1, problem 3). Ponieważ książka nie określa, w jaki sposób dane powinny być przechowywane w pliku, rozważam przechowywanie liczb całkowitych jako nieprzetworzonych bajtów (istnieją inne ograniczenia, które sprawiają, że nieprzetworzone bajty są dobrą opcją). Nigdy wcześniej nie pracowałem na tak niskim poziomie, więc chcę wiedzieć, czy jest coś niebezpiecznego, na co powinienem uważać. Czy muszę się martwić, że przypadkowo użyję jakiejś sekwencji końca pliku, gdy na przykład zapisuję surowe bajty do pliku?
Edytować:
Teraz zdaję sobie sprawę, jak szerokie było moje pytanie. Naprawdę miałem na myśli problemy bardziej katastrofalne, takie jak przypadkowe zastąpienie innych plików na dysku. Przepraszam, nie byłem jaśniejszy.
Odpowiedzi:
Jedynym niebezpieczeństwem, na które napotkasz, jest niewielka kontra duża endianizm (niezależnie od tego, czy bajt o największym lub najmniejszym znaczeniu jest zapisywany jako pierwszy). Jeśli jednak pozostaniesz w tym samym środowisku, nie będzie problemu. oprócz ogólnego zapewnienia pisania / parsowania w obie strony.
System plików jest zaprojektowany do obsługi dowolnej sekwencji bajtów.
źródło
Nie, w rzeczywistości tak działa wiele formatów plików. Typowe przykłady takich plików binarnych to obrazy i pliki muzyczne / audio.
Aby zachować integralność pliku i odczytanych z niego danych, należy przestrzegać następujących wskazówek:
Szczegółowe informacje będą się różnić w zależności od frameworka, platformy i języka, ale powinno to obejmować podstawowe „gotchas” z I / O pliku.
źródło
int
może zawierać od 2 do 8 lub więcej bajtów (tak naprawdę oktetów).int
na dwóch różnych komputerach można uznać za różne typy danych.Oprócz wszystkich wspomnianych już gotchas, jeśli tworzysz nowy format pliku binarnego, a nie odczytujesz i zapisujesz dane w istniejącym formacie, absolutnie niezbędne jest dołączenie nagłówka pliku : bloku danych na samym początku pliku, który jednoznacznie identyfikuje format pliku i rejestruje wszelkie wymagane metadane.
Dobre nagłówki plików obejmują co najmniej trzy rzeczy:
„ Magiczna liczba ”, co najmniej cztery bajty. Magiczna liczba MUSI rfc2119 być pierwszym N bajtami w pliku, MUSI nigdy nie być używana w żadnym innym formacie pliku, który można wykopać, i MUSI zawierać co najmniej jeden bajt, który nie jest drukowalnym znakiem ASCII. Zobacz specyfikację PNG, aby dowiedzieć się, jak zaprojektować naprawdę dokładną liczbę magiczną. Zobacz kod źródłowy
file(1)
polecenia, aby znaleźć bazę istniejących magicznych liczb, która jest tak obszerna, jak to tylko możliwe.Magiczna liczba polega na jednoznacznym oznaczeniu pliku wewnątrz pasma jego formatem. Jeśli nie podasz magicznej liczby lub nie jest to pierwsza rzecz w pliku, ryzykujesz, że programy błędnie zidentyfikują Twój plik jako inny typ pliku, co prowadzi do utraty danych, wykrycia wirusów i innych tego typu katastrofy.
Wskazanie wersji formatu pliku. Nawet jeśli uważasz, że nigdy nie będziesz musiał radykalnie zmieniać formatu pliku, utwórz kolejne dwa bajty po magicznej liczbie
00 00
i udokumentuj, że jest to 16-bitowy numer wersji z pewną dokładnością (cokolwiek chcesz, ale wybierz jeden i trzymaj się go w całym pliku ) i zostanie zwiększony, jeśli znaczenie kolejnych danych zmieni się radykalnie. Twoje przyszłe ja będzie ci wdzięczne.(Specyfikacja PNG podąża tutaj inną drogą, określając, że formaty porcji są zamrożone i że wszystkie przyszłe zmiany formatu przyjmą formę nowych typów porcji. Jest to również ważne, ale zalecam proste podejście magicznej liczby + numeru wersji dla początkujący do binarnego przetwarzania danych. Ludzie, którzy zaprojektowali PNG, czerpali z kolektywnych dekad doświadczeń z formatami obrazów.)
Pewien mechanizm osadzania dowolnych metadanych w pliku. Może to być tak proste, że kolejne dwa bajty to 16-bitowe przesunięcie od końca nagłówka do początku rzeczywistych danych, przy czym wszystko pomiędzy należy interpretować jako pary klucz-wartość UTF-8 a la RFC 822 (to znaczy „
Tag: value\n
” - jeśli wybierzesz tę trasę, zalecam nie zezwalanie na składanie długich linii). Ponownie PNG jest znacznie mądrzejszy.źródło
Różne architektury mają różne reprezentacje liczb całkowitych. Głównym ryzykiem tutaj jest zapisanie bajtowej reprezentacji liczby całkowitej na maszynie A, a następnie próba odczytania tego z powrotem i zinterpretowania zawartości jako liczb całkowitych na maszynie B. Jeśli maszyny A i B mają różne rozmiary liczb całkowitych i / lub inny endian , „ Najprawdopodobniej spowoduje niezdefiniowane zachowanie (np. w C) lub wyjątek.
Ponieważ jest to tylko przykład programowania, a nie „prawdziwy” program, nie jest to tak naprawdę problemem. Gdyby to był prawdziwy program, rozwijanie własnego formatu binarnego specyficznego dla aplikacji zwykle nie jest dobrym pomysłem; istnieją lepsze rozwiązania, takie jak SQLite lub oparte na łańcuchach formaty szeregowania, takie jak JSON, YAML, XML itp. W przypadku pojedynczych wartości wystarczyłoby przekształcenie go w ciąg; w przypadku prostych list można zapisać jeden ciąg w wierszu i po prostu podzielić dane wejściowe na nowe wiersze po ponownym odczytaniu.
źródło