2012-01-05 14 views
15

Nie rozumiem formatu niesformatowanych plików w Fortran.Format niesformatowanego Fortranu

Na przykład

open (3,file=filename,form="unformatted",access="sequential") 
write(3) matrix(i,:) 

wyjściu kolumny macierzy do pliku. Odkryłem, że plik jest nakładany 4 bajtami na każdym końcu, jednak tak naprawdę nie rozumiem, dlaczego i jak kontrolować to zachowanie. Czy istnieje sposób na usunięcie wyściółki?

Dzięki

+2

Zmieniono tytuł, ponieważ nie podoba mi się mylące użycie tego terminu - "binarny". Binary oznacza podstawę 2, która nie jest bezpośrednio związana z twoim problemem. Prawie wszystko na twoim komputerze jest binarne, na pewnym poziomie. Jest to powszechny termin w dzisiejszych czasach, ale "niesformatowany" Fortran jest o wiele bliższy. – Rook

+1

Kilka użytecznych informacji dotyczących strumienia ... http://www.star.le.ac.uk/~cgp/streamIO.html – Rook

+1

wydaje się być duplikatem http://stackoverflow.com/questions/8751154/ patrząc na binarne wyjście z Fortran-on-gnuplot, czy mógłbyś nie zadawać więcej pytań? – steabert

Odpowiedz

18

Dla unformated IO, kompilatory Fortran zazwyczaj napisać długość rekordu na początku i na końcu rekordu. Większość, ale nie wszystkie kompilatory używają czterech bajtów. Pomaga to w odczytywaniu rekordów, np. Długość na końcu pomaga w operacji backspace. Możesz to powstrzymać dzięki nowemu trybowi Stream IO w Fortranie 2003, który został dodany dla kompatybilności z innymi językami. Użyj access = 'stream' w swoim otwartym wyciągu.

+2

Jako niewielka uwaga, niektóre kompilatory, takie jak Gfortran i Intel Fortran, obsługują rekordy większe niż 2 GB, mimo że mają 4-bajtowe znaczniki rekordów, za pomocą podtekstów. – janneb

5

Fortran IO bazuje na rekordach, a nie na strumieniu. Za każdym razem, gdy piszesz coś przez write(), nie tylko piszesz dane, ale także znaczniki początku i końca tego rekordu. Oba znaczniki rekordów są wielkości tego rekordu. To jest powód, dla którego zapisanie paczki reali w jednym zapisie (jeden rekord: jeden znacznik początku, pęczek reali, jeden znacznik końcowy) ma inny rozmiar w odniesieniu do zapisywania każdego z nich w osobnym zapisie (wiele rekordów, każdy jednego znacznika początkowego, jednego rzeczywistego i jednego końcowego). Jest to niezwykle ważne, jeśli zapisujesz duże matryce, ponieważ możesz zawłaszczyć zawód, jeśli jest niewłaściwie napisany.

+3

to, co mówisz, odnosi się tylko do "sekwencyjnego" dostępu: – steabert

+1

@steabert: najczęściej używanym (99,999%). –

+1

Około połowa mojego kodu używa "bezpośredniego" dostępu - tak, że byłoby to tylko 50% dla mnie: P – mgilson

6

Nigdy nie użyłem dostępu sekwencyjnego z niesformatowanym wyjściem z tego powodu. Jednak zależy to od aplikacji, a czasami wygodnie jest mieć wskaźnik długości rekordu (szczególnie w przypadku danych niestrukturalnych). Zgodnie z sugestią firmy steabert w dokumencie Looking at binary output from fortran on gnuplot można tego uniknąć, używając argumentu słowa kluczowego ACCESS = 'DIRECT', w którym to przypadku należy określić długość rekordu. Ta metoda jest wygodna do wydajnego przechowywania dużych wielowymiarowych danych strukturalnych (stała długość rekordu). Poniższy przykład zapisuje plik niesformatowany, którego wielkość jest równa wielkości tablicy:

REAL(KIND=4),DIMENSION(10) :: a = 3.141 
INTEGER     :: reclen 

INQUIRE(iolength=reclen)a 
OPEN(UNIT=10,FILE='direct.out',FORM='UNFORMATTED',& 
    ACCESS='DIRECT',RECL=reclen) 
WRITE(UNIT=10,REC=1)a 
CLOSE(UNIT=10) 

END 

Zauważ, że to nie jest idealne aproach w sensie przenośności. W niesformatowanym pliku napisanym z bezpośrednim dostępem nie ma informacji o wielkości każdego elementu. Plik tekstowy readme, który opisuje rozmiar danych, sprawia, że ​​zadanie jest dla mnie w porządku, a ja wolę tę metodę zamiast wypełniania w trybie sekwencyjnym.

0

Fortran Unformatted IO Jestem dość obeznany z różnymi wyjściami przy użyciu kompilatorów Intel i Gnu. Na szczęście moje ogromne doświadczenie z lat 70. IBM pozwoliło mi rozszyfrować. Gnu podkłada rekordy z 4-bajtowymi licznikami całkowitymi, które dają rekordową długość. Intel używa 1-bajtowego licznika i pewnej liczby wbudowanych wartości kodowania, aby wskazać kontynuację lub koniec zliczania. Można nadal mieć bardzo długie długości rekordów, mimo że używany jest tylko 1 bajt. Mam oprogramowanie skompilowane przez kompilator Gnu, które musiałem zmodyfikować, aby mógł odczytać niesformatowany plik wygenerowany przez jeden z kompilatorów, więc musi wykryć, który format znajdzie. Odczytanie niesformatowanego pliku wygenerowanego przez kompilator Intel (który następuje po "starych" dniach IBM) trwa "na zawsze" za pomocą fgetc Gnu lub otwarcie pliku w trybie strumieniowym. Konwersja pliku do tego, co Gnu oczekuje wyników do 100 razy szybciej, zależy to od rozmiaru pliku, jeśli chcesz zawracać sobie głowę wykrywaniem i konwersją, czy też nie.Zmniejszyłem czas uruchamiania programu (który otwiera duży niesformatowany plik) z 5 minut do 10 sekund. Musiałem dodać opcje do rekonwersji z powrotem, jeśli użytkownik chce zabrać plik z powrotem do skompilowanego programu firmy Intel. To wszystko sprawia ból, ale proszę bardzo.