Прежде чем я начну этот ответ, позвольте мне повторить то, что я сказал в комментариях к вашему вопросу:
Не стоит недооценивать, сколько данных вы можете поместить в один массив.Чтение один раз, а затем хранение всего в памяти по-прежнему является самым быстрым из возможных способов.
Но давайте предположим, что данные действительно становятся слишком большими.
Похоже, ваша главная проблема заключается в-читайте все данные с самого начала, пока не найдете нужное значение.Это занимает время.
Если вы можете рассчитать, какая строка файла данных представляет интересующее вас значение, это может помочь преобразовать файл в неотформатированный файл прямого доступа.
Здесьэто пример кода для преобразования.Он использует функции Fortran 2008, поэтому, если ваш компилятор не может этого сделать, вы должны изменить его:
program convert
use iso_fortran_env, only: real64
implicit none
integer, parameter :: reclength = 6*8 ! Six 8-byte values
integer :: ii, ios
integer :: u_in, u_out
real(kind=real64) :: pos(3), B(3)
open(newunit=u_in, file='data.txt', form='formatted', &
status='old', action='read', access='sequential')
open(newunit=u_out, file='data.bin', form='unformatted', &
status='new', action='write', access='direct', recl=reclength)
ii = 0
do
ii = ii + 1
read(u_in, *, iostat=ios) pos, B
if (ios /= 0) exit
write(u_out, rec=ii) pos, B
end do
close(u_out)
close(u_in)
end program convert
После того, как вы конвертируете данные, вы можете читать только нужную вам запись, еслиВы можете рассчитать, какой это.Я предположил, что, как и в вашем примере, z
-координата меняется быстрее всего, а x
-координата меняется медленнее.
program read_txt
use iso_fortran_env, only: real64
implicit none
integer, parameter :: nx=601, ny=181, nz=61
real(kind=real64), parameter :: x_min=real(-nx/2, kind=real64)
real(kind=real64), parameter :: y_min=real(-ny/2, kind=real64)
real(kind=real64), parameter :: z_min=real(-nz/2, kind=real64)
real(kind=real64), parameter :: x_step = 1.0_real64
real(kind=real64), parameter :: y_step = 1.0_real64
real(kind=real64), parameter :: z_step = 1.0_real64
real(kind=real64) :: request(3), pos(3), B(3)
integer :: ios, u_in
integer :: ii, jj, kk, record
integer, parameter :: reclength = 6 * 8 ! Six 8-byte values
open(newunit=u_in, file='data.bin', access='direct', form='unformatted', &
status='old', action='read', recl=reclength)
mainloop : do
read(*, *, iostat=ios) request
if (ios /= 0) exit mainloop
write(*, '(A, 3F7.2)') 'searching for ', request
! Calculate record
ii = nint((request(1)-x_min)/x_step)
jj = nint((request(2)-y_min)/y_step)
kk = nint((request(3)-z_min)/z_step)
record = kk + jj * nz + ii * nz * ny + 1
read(u_in, rec=record, iostat=ios) pos, B
if (ios /= 0) then
print *, 'failure to read'
cycle mainloop
end if
write(*, '(2(A, 3F7.2))') "found pos: ", pos, " Bx, By, Bz: ", B
end do mainloop
close(u_in)
end program read_txt
Обратите внимание, что неотформатированный не зависит от компилятора и системы.Файл, созданный на одном компьютере или с помощью программы, скомпилированной одним компилятором, может быть недоступен для чтения с другой программой или на другом компьютере.
Но если у вас есть контроль над ним, это может быть полезным способомускорить процесс.
PS: я оставил координаты x, y и z в файле, чтобы вы могли проверить, действительно ли значения соответствуют вашим ожиданиям.Всегда хорошо проверять эти вещи.