# How to replace C ftell() and fseek() functions in Fortran?

**URL:** https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761
**Category:** Help
**Created:** [February 27, 2021, 5:28pm UTC](https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761 "2021-02-27T17:28:27Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)
#### Post date: [February 27, 2021, 5:28pm UTC](https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761/1 "2021-02-27T17:28:27Z")

</div>

I am translating another musical C program to Fortran. In the MIDI binary format, for each musical track I must write in the header of the track some bytes containing the size of its following data. As I don’t know that size before the end of the algorithm, I am using the C `ftell()` function to memorize the position where that size must be written. And when the track is finished, I easily go back to that position using the `fseek()` function, write the data size, then go back to the current end of the file to write other tracks, and so on. See:  
[https://www.tutorialspoint.com/c\_standard\_library/c\_function\_ftell.htm](https://www.tutorialspoint.com/c_standard_library/c_function_ftell.htm)  
[https://www.tutorialspoint.com/c\_standard\_library/c\_function\_fseek.htm](https://www.tutorialspoint.com/c_standard_library/c_function_fseek.htm)

I am really confused on how to do that in Fortran. I have not found exactly equivalent functions. Should I use `BACKSPACE` as many times as needed (because it goes back only one record at a time)? But then, how to go back to the current end of the file? Making as many `READ` as needed? (Note that happily, MIDI files are generally quite short: some kilobytes. Performance is not a problem.)

I could probably more easily work with an array, then transfer it to a file. But there is some elegance in the C way.

Thanks for help

---

<div class="post-metadata">

### Author: ![interkosmos](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/interkosmos/32/296_2.png) [@interkosmos](https://fortran-lang.discourse.group/u/interkosmos)
#### Post date: [February 27, 2021, 11:53pm UTC](https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761/2 "2021-02-27T23:53:03Z")

</div>

Not sure, if it helps:

The `inquire` statement has a `pos` specifier that returns the file position for a file connected for stream access in file storage units (in most cases, bytes). For record-based access, there is also the `nextrec` specifier that returns the number of the next record. You can call `inquire` whenever you like.

Furthermore, you can call the `rewind` statement to jump back to the beginning of a file. To check whether or not you have reached the end of a file, call the `read` statement with `iostat` specifier, and check the result with `is_iostat_end()`:

```
integer :: rc
! ...
read (file_unit, iostat=rc) buf

if (is_iostat_end(rc)) then
    ! end of file reached ...
end if
```

---

<div class="post-metadata">

### Author: ![billlong](https://avatars.discourse-cdn.com/v4/letter/b/71e660/32.png) [@billlong](https://fortran-lang.discourse.group/u/billlong)
#### Post date: [February 28, 2021, 5:57am UTC](https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761/3 "2021-02-28T05:57:28Z")

</div>

You probably want to use the STREAM I/O feature in Fortran. You can specify a starting position as part of the I/O statement. STREAM I/O is designed to be “C-like”.

---

<div class="post-metadata">

### Author: ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)
#### Post date: [February 28, 2021, 9:12am UTC](https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761/4 "2021-02-28T09:12:51Z")

</div>

Thanks @billlong and @interkosmos  
I was not aware that `INQUIRE` could be used on an opened file. Using your two answers, I have found that link:  
[https://www.star.le.ac.uk/~cgp/streamIO.html](https://www.star.le.ac.uk/~cgp/streamIO.html)  
After a quick read, I think it could help me doing the same thing as in C. I will report here my success or failure…

---

<div class="post-metadata">

### Author: ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)
#### Post date: [February 28, 2021, 9:00pm UTC](https://fortran-lang.discourse.group/t/how-to-replace-c-ftell-and-fseek-functions-in-fortran/761/5 "2021-02-28T21:00:01Z")

</div>

Thanks, it’s a success. In the following program, I write two 0xFF bytes, memorize the position of the second one (before writing it), write two other 0xFF, memorize the final position, replace the second byte by 0x00, then go back to the end and add a final 0x10 byte:

```auto
program writing_bytes
    use ISO_FORTRAN_ENV, only: INT8
    implicit none
    integer(INT8) :: i8
    integer :: status, my_pos, final_pos

    i8 = int(z'FF', kind=INT8)

    open(unit=1, file='bytes.bin', access='stream', status='replace', &
       & action='write', iostat=status)

    write(1, iostat=status) i8
    inquire(1, POS=my_pos)
    print *, "Second byte will be written at the position", my_pos
    write(1, iostat=status) i8
    write(1, iostat=status) i8
    write(1, iostat=status) i8

    inquire(1, POS=final_pos)
    print *, "Temp final position (unwritten) ", final_pos

    print *, "Let's replace the second 0xFF by 0x00"
    write(1, POS=my_pos, iostat=status) 0_INT8

    print *, "Let's add a final 0x10 = 16 byte"
    write(1, POS=final_pos, iostat=status) 16_INT8

    close(1, iostat=status)

    print *
    call execute_command_line("hexdump -C bytes.bin")
end program

```

The output is:

```bash
$ gfortran rewind_to_pos.f90 && ./a.out
 Second byte will be written at the position 2
 Temp final position (unwritten) 5
 Let's replace the second 0xFF by 0x00
 Let's add a final 0x10 = 16 byte

00000000 ff 00 ff ff 10 |.....|
00000005

```

P.s. Be careful with the `hexdump` command: always use the `-C` option _(Canonical)_ to avoid little-endian problems (by default `hexdump` is working with 16 bits values…)
