FileInputStream: примеры (JAVA)

Чтение данных из файлов с помощью FileInputStream
Раздел: Потоки ввода-вывода (Streams) байтовые
FileInputStream(File file, String name)

Класс FileInputStream - назначение и сигнатуры

Класс FileInputStream предоставляет байтовый поток для чтения содержимого файлов. Применяется для работы с бинарными файлами, когда требуется низкоуровневое чтение байтов, а также при совместной работе с NIO-каналами. Поток возвращает либо отдельный байт в виде int (0..255), либо количество прочитанных байтов при чтении в массив. В случае конца файла метод чтения возвращает -1 или 0 в соответствующих перегрузках.

Основные конструкторы и их параметры:

FileInputStream(File file)
FileInputStream(String name)
FileInputStream(FileDescriptor fdObj)

Пояснения к аргументам:

  • File - объект из java.io.File, указывающий путь; может вызвать FileNotFoundException, если файл отсутствует.
  • String - строка с путём до файла; поведение аналогично.
  • FileDescriptor - дескриптор открытого файла (например, FileDescriptor.in, .out, .err).

Основные методы и окончания их значений:

int read() throws IOException                     // один байт, -1 при EOF
int read(byte[] b) throws IOException             // количество байт или -1
int read(byte[] b, int off, int len) throws IOException
void close() throws IOException
int available() throws IOException                // оценка доступных байт
long skip(long n) throws IOException
FileChannel getChannel()
FileDescriptor getFD() throws IOException
// с Java 9 унаследованы: byte[] readAllBytes(), int readNBytes(byte[] b, int off, int len), long transferTo(OutputStream out)

Возвращаемые значения обычно представляют собой количество прочитанных байт или одиночный байт. В случае ошибок генерируются исключения IOException или более конкретные FileNotFoundException. Поток реализует Closeable и поддерживает конструкцию try-with-resources.

Короткие примеры использования

1) Чтение файла по одному байту:

import java.io.*;

public class ReadByteByByte {
    public static void main(String[] args) throws Exception {
        try (FileInputStream fis = new FileInputStream("example.txt")) {
            int b;
            while ((b = fis.read()) != -1) {
                System.out.print((char) b);
            }
        }
    }
}
Результат (если в example.txt текст "Hello\n"):
Hello

2) Чтение в буфер:

import java.io.*;

public class ReadWithBuffer {
    public static void main(String[] args) throws Exception {
        try (FileInputStream fis = new FileInputStream("example.bin")) {
            byte[] buf = new byte[8];
            int n;
            while ((n = fis.read(buf)) != -1) {
                System.out.println("Прочитано байт: " + n);
            }
        }
    }
}
Пример вывода:
Прочитано байт: 8
Прочитано байт: 3

3) Использование readAllBytes (Java 9+):

import java.io.*;

public class ReadAllBytesExample {
    public static void main(String[] args) throws Exception {
        try (FileInputStream fis = new FileInputStream("text.txt")) {
            byte[] all = fis.readAllBytes();
            System.out.println(new String(all));
        }
    }
}
Результат: содержимое файла как строка

4) Ошибка при отсутствии файла:

import java.io.*;

public class NotFound {
    public static void main(String[] args) throws Exception {
        new FileInputStream("missing.file");
    }
}
Исключение:
java.io.FileNotFoundException: missing.file (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method)
    ...

Аналоги в Java и их особенности

  • BufferedInputStream - добавляет буферизацию над FileInputStream, улучшает производительность при частом чтении маленьких блоков.
  • FileReader - символьный поток, подходит для текстовых файлов с преобразованием кодировок; если требуются байты, предпочтительнее FileInputStream.
  • Files.newInputStream(Path) (NIO.2) - более гибкий способ открытия потока с опциями; удобен при работе с Path и атрибутами.
  • RandomAccessFile - поддерживает чтение и запись в произвольных позициях; полезен при необходимости позиционирования и записи.
  • FileChannel - для высокопроизводительных операций, передачи данных между каналами и memory-mapped файлов; используется через getChannel().
  • ByteArrayInputStream - для тестов и чтения из памяти.

Выбор зависит от задач: для текстовых файлов лучше FileReader или java.nio.file.Files; для больших бинарных потоков и копирования - FileChannel/transferTo; для простого побайтного чтения без буфера - FileInputStream.

Аналоги в других языках и отличия

PHP (функции fopen/fread):

$f = fopen('file.bin', 'rb');
$data = fread($f, 1024);
fclose($f);
Результат: массив байтов в строковом виде или бинарная строка

JavaScript (Node.js):

const fs = require('fs');
const buf = fs.readFileSync('file.bin');
console.log(buf.length);
Вывод: количество байт, например 1234

Python:

with open('file.bin', 'rb') as f:
    data = f.read(1024)
    print(len(data))
Вывод: число прочитанных байт

C#:

using (var fs = new FileStream("file.bin", FileMode.Open))
{
    byte[] buf = new byte[1024];
    int n = fs.Read(buf, 0, buf.Length);
}
Результат: n - число прочитанных байт

Go:

f, _ := os.Open("file.bin")
buf := make([]byte, 1024)
n, _ := f.Read(buf)
n - количество байт

Kotlin (использует JVM-классы или удобные расширения):

val fis = java.io.FileInputStream("file.bin")
val bytes = fis.readBytes()
bytes - ByteArray со всем содержимым

Lua:

local f = io.open('file.bin', 'rb')
local data = f:read(1024)
f:close()
data - бинарная строка или nil при EOF

SQL (извлечение BLOB через JDBC):

ResultSet rs = stmt.executeQuery("SELECT data FROM files WHERE id=1");
if (rs.next()) {
    InputStream in = rs.getBinaryStream(1);
    // далее чтение как из FileInputStream
}
Результат: InputStream для BLOB, чтение аналогично чтению из файла

Отличия: в разных языках API различается по синхронности, обработке ошибок и представлению байтов. Java предоставляет тесную интеграцию с NIO и Channel, а ряд языков предлагают более высокоуровневые утилиты для чтения целиком в память.

Типичные ошибки и их проявления

1) Отсутствие файла - FileNotFoundException:

new FileInputStream("no_such.file");
java.io.FileNotFoundException: no_such.file (No such file or directory)

2) Чтение после закрытия - IOException:

FileInputStream fis = new FileInputStream("a.txt");
fis.close();
fis.read();
java.io.IOException: Stream closed

3) Неправильные параметры read(byte[], off, len) - IndexOutOfBoundsException:

byte[] b = new byte[10];
fis.read(b, -1, 5);
java.lang.IndexOutOfBoundsException

4) Утечка ресурсов при отсутствии закрытия - исчерпание дескрипторов, особенно при массовом открытии файлов. Решение: try-with-resources или явный finally с close().

5) Неправильная трактовка кодировки при чтении текста как байтов. Для текстовых данных применимость FileInputStream ограничена: лучше использовать Reader с указанием кодировки.

Изменения и рекомендации в современных версиях Java

  • Java 7: поддержка try-with-resources, класс реализует Closeable и удобно закрывается автоматически.
  • Java 9: в абстрактном классе InputStream добавлены удобные методы readAllBytes(), readNBytes(...) и transferTo(OutputStream). FileInputStream наследует эти возможности, что упрощает чтение и копирование.
  • NIO интеграция: FileInputStream предоставляет getChannel() для получения FileChannel (добавлено ранее), при этом для высокопроизводительных операций часто рекомендуется прямо использовать java.nio.channels.FileChannel или java.nio.file.Files.
  • Прямых устареваний или удаления FileInputStream в актуальных релизах нет; при этом для общего использования рекомендуется API java.nio.file для гибкости и расширенных опций.

Расширенные и необычные варианты использования

1) Копирование файла «по-нулю» с помощью transferTo (эффективно для больших файлов):

Пример java
import java.io.*;
import java.nio.channels.FileChannel;

public class ZeroCopyCopy {
    public static void main(String[] args) throws Exception {
        try (FileInputStream fis = new FileInputStream("big.bin");
             FileOutputStream fos = new FileOutputStream("big_copy.bin")) {
            FileChannel inCh = fis.getChannel();
            FileChannel outCh = fos.getChannel();
            long pos = 0;
            long size = inCh.size();
            while (pos < size) {
                pos += inCh.transferTo(pos, size - pos, outCh);
            }
            System.out.println("Скопировано байт: " + size);
        }
    }
}
Скопировано байт: 104857600

2) Вычисление SHA-256 с помощью DigestInputStream:

Пример java
import java.io.*;
import java.security.*;
import javax.xml.bind.DatatypeConverter;

public class HashFile {
    public static void main(String[] args) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        try (FileInputStream fis = new FileInputStream("file.bin");
             DigestInputStream dis = new DigestInputStream(fis, md)) {
            byte[] buf = new byte[8192];
            while (dis.read(buf) != -1) { }
        }
        byte[] digest = md.digest();
        System.out.println(DatatypeConverter.printHexBinary(digest).toLowerCase());
    }
}
Пример: e3b0c44298fc1c149afbf4c8996fb92427ae41e4...

3) Чтение фиксированного диапазона: комбинация skip + readNBytes (Java 9+):

Пример java
try (FileInputStream fis = new FileInputStream("video.mp4")) {
    long offset = 1024 * 1024; // 1 MB
    fis.skip(offset);
    byte[] segment = fis.readNBytes(4096);
    System.out.println("Прочитано сегмент байт: " + segment.length);
}
Прочитано сегмент байт: 4096

4) Использование FileInputStream с FileDescriptor для чтения из стандартного ввода:

Пример java
import java.io.*;

public class ReadFromStdin {
    public static void main(String[] args) throws Exception {
        try (FileInputStream fis = new FileInputStream(FileDescriptor.in)) {
            byte[] b = new byte[64];
            int n = fis.read(b);
            System.out.println("Введено байт: " + n);
        }
    }
}
При вводе "hello": Введено байт: 6 (включая символ перевода)

5) Параллельное чтение небольших фрагментов при помощи нескольких RandomAccessFile/Channels вместо FileInputStream; для частых произвольных доступов FileInputStream мало годится, потому что он не предоставляет произвольного позиционирования напрямую.

6) Обработка больших потоков с контролем скорости: чтение блоками и паузами, использование ScheduledExecutor для лимитирования скорости передачи, при этом FileInputStream используется как источник данных.

Пояснения: приведённые примеры демонстрируют, как сочетать возможности FileInputStream с NIO и криптографическими утилитами для эффективной и безопасной работы с файлами.

джава FileInputStream function comments

En
FileInputStream A input stream for reading data from a file