Ваш оператор read
просто прочитает 2 символа для tifhead(1)
, следующие 2 символа для tifhead(2)
, et c, , включая пробелы . Следовательно, вы получите tifhead(1)="49"
, tifhead(2)=" 4"
, tifhead(3)="9 "
и так далее. Вы думаете, что прочитали первые 2 байта правильно только потому, что вы печатаете строки «49», «4», «9», ... одну за другой, поэтому на выходе они выглядят как «49 49». Компилятор не может узнать, что есть одно пустое пространство, разделяющее строки, и 2 пробела на каждые четыре данных.
Чтобы правильно прочитать ваши данные, вы должны использовать форматированный read
ing, что подразумевает, что вы также должны объявить свой stream
как «отформатированный» в заявлении open
. В следующем примере показано, как это можно сделать:
program example
implicit none
character(len=2) :: tifhead(8), greyscale(8)
open(1, file="example.txt", access='stream', form='formatted')
read(1, "(4(a2,tr1),tr1,3(a2,tr1),a2)", advance='no') tifhead
read(1, "(tr2,4(a2,tr1),tr1,3(a2,tr1),a2)", advance='no') greyscale
close(1)
print "(a,7(a2,tr1),a2,a)", " tifhead = (", tifhead, ")"
print "(a,7(a2,tr1),a2,a)", "greyscale = (", greyscale, ")"
end program example
Возможно, потребуется некоторое пояснение: a2,tr1
означает чтение строки из 2 символов, а затем однократное перемещение указателя чтения (при этом пропускается пробел между шестнадцатеричными числами. «числа» - фактически, они рассматриваются как просто строки). 4(a2,tr1)
означает сделать это 4 раза. Читаются первые 4 байта плюс один пробел. Теперь есть еще один пробел перед следующими данными, которые нужно прочитать, поэтому мы добавляем tr1
, чтобы пропустить его, и пока наш формат 4(a2,tr1),tr1
; затем мы читаем еще 3 байта с 3(a2,tr1)
, затем последний байт только с a2
(не пропуская пробел после него). Таким образом, строка формата (4(a2,tr1),tr1,3(a2,tr1),a2)
, которая будет правильно читать первые 8 байтов, оставляя указатель чтения сразу после 8-го байта. Обратите внимание, что advance='no'
необходимо, иначе Fortran предположит возврат каретки и пропустит остальные данные в той же записи (строке).
Теперь, чтобы прочитать следующие 8 байтов, мы используем тот же формат, за исключением того, что мы добавляем tr2
в начале, чтобы пропустить два пробела. Я добавил в программу форматированную печать, чтобы проверить правильность чтения данных. Запуск программы дает:
tifhead = (49 49 2A 00 08 00 20 00)
greyscale = (00 00 0B 02 00 00 00 00)
, который проверяет, что данные были прочитаны правильно.
И последнее, но не менее важное: я бы рекомендовал избегать использования устаревшего Fortran в вашем коде и приведенном выше примере. Это означает, что используйте newunit
, чтобы позволить программе найти первую свободную единицу вместо того, чтобы явно указывать номер единицы, иметь способ проверить, действительно ли существует файл, который вы пытаетесь открыть, или если вы достигли конца файла, избегайте безымянных аргументов, используйте атрибут dimension
для объявления массивов и т.д. c. Ничего из этого не является строго необходимым, и поначалу это может показаться излишним многословием. Но в конечном итоге строгость (как поощряет современный Фортран) сэкономит вам много времени при отладке более крупных программ. Таким образом, приведенный выше пример можно (возможно, следует) записать следующим образом:
program example2
implicit none
integer :: unt, status
character(len=2), dimension(8) :: tifhead, greyscale
open(newunit=unt, file="example.txt", access='stream', form='formatted',&
action='read', status='old', iostat=status)
if (status /= 0) then
print "(a)","Error reading file."; stop
end if
! More sophisticated reading is probably needed to check for end of file.
read(unit=unt, fmt="(4(a2,tr1),tr1,3(a2,tr1),a2)", advance='no') tifhead
read(unit=unt, fmt="(tr2,4(a2,tr1),tr1,3(a2,tr1),a2)") greyscale
close(unit=unt)
print "(a,7(a2,tr1),a2,a)", " tifhead = (", tifhead, ")"
print "(a,7(a2,tr1),a2,a)", "greyscale = (", greyscale, ")"
end program example2