Java에서 파일을 바이트로 []


757

어떻게 변환합니까 java.io.FileA를 byte[]?


내가 생각할 수있는 한 가지 용도는 파일에서 직렬화 된 객체를 읽는 것입니다.
Mahm00d

2
다른 하나는 헤더를 사용하여 파일 형식을 찾는 것입니다.
James P.

이 byte [] bytes = null; BufferedInputStream fileInputStream = null; try {File file = 새 파일 (filePath); fileInputStream = 새로운 버퍼 입력 스트림 (새로운 파일 입력 스트림 (파일)); // fileInputStream = Thread.currentThread (). getContextClassLoader (). getResourceAsStream (this.filePath); 바이트 = 새로운 바이트 [(int) file.length ()]; fileInputStream.read (bytes); } catch (FileNotFoundException ex) {throw ex; }
Rohit Chaurasiya

답변:


486

그것은 당신에게 가장 좋은 방법에 달려 있습니다. 생산성면에서는 휠을 재발 명하지 말고 Apache Commons를 사용하십시오. 어느 것이 여기에 있습니다 IOUtils.toByteArray(InputStream input).


29
@ ymajoros : 사실이야! 차라리 다른 종속성보다 코드 줄이 더 필요합니다. 종속성에는 숨겨진 비용이 있습니다. 해당 라이브러리를 최신 상태로 유지하고 빌드 스크립팅 등에 종속성을 포함하고 코드 등을 사용하여 사람들과 의사 소통하십시오. 이미 사용하는 것보다 코드가있는 라이브러리를 사용하고 있다면 otherwsie 직접 작성하십시오.
Stijn de Witt

11
이것은 파일을 읽는 방법에 대한 질문이지만 java.IO.File 유형의 객체를 byte []로 변환하는 방법에 대한 질문에는 대답하지 않습니다.
Ingo

5
어떻게 이런 일이를 읽는 데 사용됩니다 Filebyte[]? Java6를 사용하고 있으므로 NIO 메소드를 사용할 수 없습니다. (
PASTRY

4
@ymajoros는 "표준 3 라인 솔루션"을 우리와 친절하게 공유하길 바랍니다. 따라서 휠 의존성에 의존 할 필요가 없습니까?
matteo

3
@ matteo : 뭐요? Files.readAllBytes ()와 같은 다른 답변을 참조하십시오. 간단하고 의존성이 없습니다.
ymajoros

1292

JDK 7 부터 사용할 수 있습니다 Files.readAllBytes(Path).

예:

import java.io.File;
import java.nio.file.Files;

File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());

10
나는 File 객체가 아닌 (HTTP POST를 요청에서) 경로가
aldo.roman.nurena

81
@ aldo.roman.nurena JDK7은 Path Object를 제공하는 File.toPath () 메소드를 도입했습니다.
KevinL

6
파일에서 경로를 얻을 수 있습니다. 시도 : 파일 파일 = 새 파일 ( "/ 경로"); 경로 경로 = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (경로);
gfelisberto

2
java.nio에서 파일 닫기는 어떻게 처리됩니까? 즉, 위의 코드가 무언가를 닫아야합니까?
akauppi

4
@akauppi 대답에있는 링크를 참조하십시오 : "파일이 닫혀 있는지 메소드 보장하지만 ..."
베른하르트 바커에게

226

JDK 7부터-하나의 라이너 :

byte[] array = Files.readAllBytes(Paths.get("/path/to/file"));

외부 의존성이 필요하지 않습니다.


13
이것은 이제 Apache Commons가 필요한 허용 된 답변보다 더 나은 선택입니다.
james.garriss

1
고마워 :) 나는 이것 또한 필요했다 : String text = new String (Files.readAllBytes (new File ( "/ path / to / file"). toPath ()));
출처

5
안드로이드에서는 최소 API 레벨이 26이어야합니다.
Ashutosh Chamoli

2
당신은 추가해야합니다 import java.nio.file.Files;그리고 import java.nio.file.Paths;당신이 이미하지 않은 경우.
Sam

164
import java.io.RandomAccessFile;
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

Java 8에 대한 설명서 : http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html


2
f.read ()의 반환 값을 확인해야합니다. 때때로 전체 파일을 읽지 못할 수도 있습니다.
bugs_

8
이러한 상황은 파일을 읽는 동안 파일이 변경되는 경우에만 발생할 수 있습니다. 다른 모든 경우에는 IOException이 발생합니다. 이 문제를 해결하려면 파일을 읽기 / 쓰기 모드로 열 것을 제안합니다. RandomAccessFile (fileName, "rw")
Dmitry Mitskevich 10

5
파일의 일부만 읽는 다른 소스 (파일은 네트워크 공유에 있습니다 ...) readFully ()는 당신이 찾고있는 계약을 가지고 있다고 상상할 수 있습니다.
DThought

3
RandomAccessFile은 스레드로부터 안전하지 않습니다. 따라서 경우에 따라 동기화가 필요할 수 있습니다.
bancer

@DmitryMitskevich 파일 시스템에 적합하지 않은 다른 경우도 있습니다. 예를 들어 리눅스에서 / proc /에서 "파일"을 읽으면 짧은 읽기 (즉, 모든 것을 읽으려면 루프가 필요함)
nos

78

기본적으로 메모리에서 읽어야합니다. 파일을 열고 배열을 할당 한 후 파일에서 배열로 내용을 읽습니다.

가장 간단한 방법은 다음과 유사합니다.

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1) {
            ous.write(buffer, 0, read);
        }
    }finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
        }

        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return ous.toByteArray();
}

파일 내용을 불필요하게 복사하는 경우가 있습니다 (실제로 데이터를 파일에서 buffer,에서 buffer으로 ByteArrayOutputStream, ByteArrayOutputStream실제 결과 배열로 세 번 복사 함 ).

또한 메모리에서 특정 크기의 파일 만 읽도록해야합니다 (일반적으로 응용 프로그램에 따라 다름) :-).

또한 IOException함수 외부 를 처리해야 합니다.

다른 방법은 다음과 같습니다.

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }

    byte[] buffer = new byte[(int) file.length()];
    InputStream ios = null;
    try {
        ios = new FileInputStream(file);
        if (ios.read(buffer) == -1) {
            throw new IOException(
                    "EOF reached while trying to read the whole file");
        }
    } finally {
        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return buffer;
}

불필요한 복사는 없습니다.

FileTooBigException사용자 지정 응용 프로그램 예외입니다. MAX_FILE_SIZE상수는 어플리케이션 파라미터이다.

큰 파일의 경우 스트림 처리 알고리즘을 생각하거나 메모리 매핑을 사용해야합니다 (참조 java.nio).


시도 밖에서 ios를 선언해야 함
Daryl Spitzer

두 번째 예의 "ios.read (buffer)"문은 파일의 처음 4096 바이트에서만 읽습니다 (첫 번째 예에서 사용 된 것과 동일한 4k 버퍼로 가정). 두 번째 예제가 작동하려면 읽기가 -1 (파일 끝에 도달)에 대한 결과를 확인하는 while 루프 안에 있어야한다고 생각합니다.
Stijn de Witt

죄송합니다. 위의 설명을 무시하고 파일 길이에 대한 명령문 설정 버퍼를 놓치십시오. 아직도, 나는 첫 번째 예를 더 좋아합니다. 한 번에 전체 파일을 버퍼로 읽는 것은 확장 할 수 없습니다. 파일이 크면 메모리가 손상 될 위험이 있습니다.
Stijn de Witt

"가장 간단한"방법은 리소스를 사용하여 시도하는 것입니다.
Sina Madani 2016 년

시원하지만 조금 장황합니다.
Sapphire_Brick

77

누군가가 말했듯이 Apache Commons File Utils 에는 원하는 것이있을 수 있습니다.

public static byte[] readFileToByteArray(File file) throws IOException

사용 예 ( Program.java) :

import org.apache.commons.io.FileUtils;
public class Program {
    public static void main(String[] args) throws IOException {
        File file = new File(args[0]);  // assume args[0] is the path to file
        byte[] data = FileUtils.readFileToByteArray(file);
        ...
    }
}

23

NIO API를 사용할 수도 있습니다. 총 파일 크기 (바이트)가 int에 맞는 한이 코드 로이 작업을 수행 할 수 있습니다.

File f = new File("c:\\wscp.script");
FileInputStream fin = null;
FileChannel ch = null;
try {
    fin = new FileInputStream(f);
    ch = fin.getChannel();
    int size = (int) ch.size();
    MappedByteBuffer buf = ch.map(MapMode.READ_ONLY, 0, size);
    byte[] bytes = new byte[size];
    buf.get(bytes);

} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} finally {
    try {
        if (fin != null) {
            fin.close();
        }
        if (ch != null) {
            ch.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

MappedByteBuffer를 사용한 이후로 매우 빠르다고 생각합니다.


2
파일을 한 번만 읽으려는 경우 메모리 매핑을 사용할 필요가 없으며 일반 FileInputStream을 사용하는 것보다 두 배의 메모리를 사용하게됩니다.
james

1
불행히도 MappedByteBuffer는 자동으로 해제되지 않습니다.
Tom Hawtin-tackline

2
놀랍게도 새로운 예제에는 고전적인 예외 예외 처리 인 printStackTrace가 포함됩니다.
제임스

동의합니다 .. 이클립스가 사용하는 기본 항목입니다. 예외를 다시 던져야한다고 생각합니다!
아 미트

파일에서 byte []를 만들기 위해 nio를 벤치마킹했습니다. 직접 버퍼를 사용하는 것 외에는 실제로 두 배의 메모리가 필요합니다. 매우 큰 파일 (200M의 경우 버퍼 IO보다 약 2 배 빠름)이 더 빠르지 만 5M 정도의 파일에 대해서는 5 배가 빠지는 것 같습니다.
Chaffers

22

Java 8이없는 경우 몇 줄의 코드 작성을 피하기 위해 대규모 라이브러리를 포함하는 것이 좋지 않다는 것에 동의합니다.

public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] b = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    int c;
    while ((c = inputStream.read(b)) != -1) {
        os.write(b, 0, c);
    }
    return os.toByteArray();
}

발신자는 스트림을 닫을 책임이 있습니다.


21
// Returns the contents of the file in a byte array.
    public static byte[] getBytesFromFile(File file) throws IOException {        
        // Get the size of the file
        long length = file.length();

        // You cannot create an array using a long type.
        // It needs to be an int type.
        // Before converting to an int type, check
        // to ensure that file is not larger than Integer.MAX_VALUE.
        if (length > Integer.MAX_VALUE) {
            // File is too large
            throw new IOException("File is too large!");
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;

        InputStream is = new FileInputStream(file);
        try {
            while (offset < bytes.length
                   && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
                offset += numRead;
            }
        } finally {
            is.close();
        }

        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }
        return bytes;
    }

또한 루프 안에 numRead를 넣습니다. 가능한 가장 작은 유효 범위에서 변수를 선언하십시오. while 루프 외부에 두는 것은 복잡한 "while"테스트를 가능하게하기 위해서만 필요합니다. 루프 내부에서 EOF 테스트를 수행하는 것이 좋습니다 (발생하는 경우 EOFException 발생).
erickson

throw new IOException("File is too large!");파일이 너무 클 때 어떻게해야합니까? 그것에 대한 예가 있습니까?
Fer

21

간단한 방법 :

File fff = new File("/path/to/file");
FileInputStream fileInputStream = new FileInputStream(fff);

// int byteLength = fff.length(); 

// In android the result of file.length() is long
long byteLength = fff.length(); // byte count of the file-content

byte[] filecontent = new byte[(int) byteLength];
fileInputStream.read(filecontent, 0, (int) byteLength);

이미 언급 된 단일 라이너와 같은 더 간단한 방법이 있습니다.
Sapphire_Brick

@Sapphire_Brick 더 간단한 방법은 그렇습니다. 그러나 하나의 라이너가 모든 상황에 맞지는 않습니다. 안드로이드와 같은.
Behr

17

파일에서 바이트를 읽는 가장 간단한 방법

import java.io.*;

class ReadBytesFromFile {
    public static void main(String args[]) throws Exception {
        // getBytes from anyWhere
        // I'm getting byte array from File
        File file = null;
        FileInputStream fileStream = new FileInputStream(file = new File("ByteArrayInputStreamClass.java"));

        // Instantiate array
        byte[] arr = new byte[(int) file.length()];

        // read All bytes of File stream
        fileStream.read(arr, 0, arr.length);

        for (int X : arr) {
            System.out.print((char) X);
        }
    }
}

1
나는 "가장 간단한 방법"이라고 주장합니다 :)
BlondCode

여기서 설명해 주시겠습니까? 왜 논쟁이 있습니까?
Muhammad Sadiq

3
특별한 것은 없지만 가장 간단하게 말하면 더 간단한 해결책을 볼 수 있습니다.-> 제 생각에는 가장 간단하지 않습니다. 아마 몇 년 전 일지 모르지만 세상은 변하고 있습니다. 나는 그런 진술로 내 자신의 솔루션에 레이블을 붙이지 않을 것입니다. ;) 만약 당신이 "내 생각으로는 가장 간단한 것이 .."또는 "내가 찾은 가장 간단한 것"이라고 쓴다면, 당신을 귀찮게하고 싶지 않다.
BlondCode

@ MuhammadSadiq : 아무것도 가져 오지 마십시오 .*, 나쁜 습관으로 간주됩니다.
사파이어

13

Guava는 Files.toByteArray () 를 제공합니다. 몇 가지 장점이 있습니다.

  1. 파일이 길이가 0을보고하지만 여전히 내용을 가지고있는 코너 케이스를 다룹니다.
  2. 파일을로드하려고 시도하기 전에 큰 파일을 읽으려고하면 OutOfMemoryException이 발생합니다. (file.length ()의 영리한 사용을 통해)
  3. 바퀴를 재발 명할 필요는 없습니다.

12
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

File file = getYourFile();
Path path = file.toPath();
byte[] data = Files.readAllBytes(path);

어떤 JDK 레벨입니까?
Jonathan S. Fisher

11

커뮤니티 위키 답변과 동일한 접근 방식을 사용하지만 깨끗하고 즉시 사용 가능 (Android에서 Apache Commons 라이브러리를 가져 오지 않으려는 경우 선호되는 접근 방식) :

public static byte[] getFileBytes(File file) throws IOException {
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1)
            ous.write(buffer, 0, read);
    } finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
            // swallow, since not that important
        }
        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
            // swallow, since not that important
        }
    }
    return ous.toByteArray();
}

8

나는 이것이 가장 쉬운 방법이라고 믿습니다.

org.apache.commons.io.FileUtils.readFileToByteArray(file);

7
2009 년 Tom의 제안에 대한 답변이 이미 있습니다
Knut Herrmann

7

ReadFully 현재 파일 포인터에서 시작하여이 파일에서 바이트 배열로 b.length 바이트를 읽습니다. 이 메소드는 요청 된 바이트 수를 읽을 때까지 파일에서 반복적으로 읽습니다. 이 메소드는 요청 된 바이트 수를 읽거나 스트림의 끝이 감지되거나 예외가 발생할 때까지 차단합니다.

RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

5

미리 할당 된 바이트 버퍼로 바이트를 읽으려면이 답변이 도움이 될 수 있습니다.

당신의 첫 번째 추측은 아마 사용하는 것입니다 InputStream read(byte[]). 그러나이 방법에는 결함이있어 사용하기가 부적절합니다. EOF가 발생하지 않더라도 어레이가 실제로 완전히 채워질 것이라는 보장은 없습니다.

대신을 살펴보십시오 DataInputStream readFully(byte[]). 이것은 입력 스트림의 래퍼이며 위에서 언급 한 문제가 없습니다. 또한이 방법은 EOF가 발생하면 발생합니다. 훨씬 좋습니다.


4

다음과 같은 방법으로 java.io.File을 byte []로 변환 할뿐만 아니라 서로 다른 여러 Java 파일 읽기 메소드를 테스트 할 때 파일에서 읽는 가장 빠른 방법 인 것도 발견했습니다 .

java.nio.file.Files.readAllBytes ()

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class ReadFile_Files_ReadAllBytes {
  public static void main(String [] pArgs) throws IOException {
    String fileName = "c:\\temp\\sample-10KB.txt";
    File file = new File(fileName);

    byte [] fileBytes = Files.readAllBytes(file.toPath());
    char singleChar;
    for(byte b : fileBytes) {
      singleChar = (char) b;
      System.out.print(singleChar);
    }
  }
}

3

타사 라이브러리를 사용하지 않고 다른 솔루션을 추가하겠습니다. Scott 이 제안한 예외 처리 패턴을 재사용합니다 ( link ). 그리고 추한 부분을 별도의 메시지로 옮겼습니다 (일부 FileUtils 클래스에서 숨길 것입니다.))

public void someMethod() {
    final byte[] buffer = read(new File("test.txt"));
}

private byte[] read(final File file) {
    if (file.isDirectory())
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is a directory");
    if (file.length() > Integer.MAX_VALUE)
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is too big");

    Throwable pending = null;
    FileInputStream in = null;
    final byte buffer[] = new byte[(int) file.length()];
    try {
        in = new FileInputStream(file);
        in.read(buffer);
    } catch (Exception e) {
        pending = new RuntimeException("Exception occured on reading file "
                + file.getAbsolutePath(), e);
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (Exception e) {
                if (pending == null) {
                    pending = new RuntimeException(
                        "Exception occured on closing file" 
                             + file.getAbsolutePath(), e);
                }
            }
        }
        if (pending != null) {
            throw new RuntimeException(pending);
        }
    }
    return buffer;
}

3
public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] buffer = new byte[32 * 1024];
    int bufferSize = 0;
    for (;;) {
        int read = inputStream.read(buffer, bufferSize, buffer.length - bufferSize);
        if (read == -1) {
            return Arrays.copyOf(buffer, bufferSize);
        }
        bufferSize += read;
        if (bufferSize == buffer.length) {
            buffer = Arrays.copyOf(buffer, bufferSize * 2);
        }
    }
}

1

파일에서 바이트를 읽는 또 다른 방법

Reader reader = null;
    try {
        reader = new FileReader(file);
        char buf[] = new char[8192];
        int len;
        StringBuilder s = new StringBuilder();
        while ((len = reader.read(buf)) >= 0) {
            s.append(buf, 0, len);
            byte[] byteArray = s.toString().getBytes();
        }
    } catch(FileNotFoundException ex) {
    } catch(IOException e) {
    }
    finally {
        if (reader != null) {
            reader.close();
        }
    }

속이 빈 캐치 블록을 사용하지 마십시오. 디버깅을 어렵게 만듭니다.
Sapphire_Brick

1
//The file that you wanna convert into byte[]
File file=new File("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4"); 

FileInputStream fileInputStream=new FileInputStream(file);
byte[] data=new byte[(int) file.length()];
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);

//Now the bytes of the file are contain in the "byte[] data"

1
이 코드는 질문에 대한 해결책을 제공 할 수 있지만 왜 / 어떻게 작동하는지에 대한 컨텍스트를 추가하는 것이 좋습니다. 이것은 미래의 사용자가 배우고 그 지식을 자신의 코드에 적용하는 데 도움이 될 수 있습니다. 또한 코드를 설명 할 때 사용자의 의견을 공감 형태로 긍정적 인 피드백을받을 가능성이 있습니다.
borchvm

글쎄, 그것은 미래의 게시물에서 명심해야 할 중요한 부분입니다. 유용한 통찰력에 감사드립니다.
우 사마 Mehmood

0

이 시도 :

import sun.misc.IOUtils;
import java.io.IOException;

try {
    String path="";
    InputStream inputStream=new FileInputStream(path);
    byte[] data=IOUtils.readFully(inputStream,-1,false);
}
catch (IOException e) {
    System.out.println(e);
}

다른 JRE에서 실행될 경우 앱을 중단시키는 특정 JRE 구현이 필요합니다.
rattaman

2
작은 실수는 : :) IOException이 아닌 IOException이 있지만, 덕분에
마탄 마르시 아노

1
@MatanMarciano : 내 나쁜
사파이어

-7

에서 JDK8

Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();

2
프랑스어를 사용하는 친구의 질문을 읽고 "byte []"로 변환하는 것에 대해 질문하지만 답변에서 제공하지 않습니다.
Kaiser Keister

2
이것은 byte []로 변환하기위한 원격 옵션을 제공하지 않습니다!
Anddo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.