83

I am trying to get file content in bytes in Android application. I have get the file in SD card now want to get the selected file in bytes. I googled but no such success. Please help

Below is the code to get files with extension. Through this i get files and show in spinner. On file selection I want to get file in bytes.

private List<String> getListOfFiles(String path) {

   File files = new File(path);

   FileFilter filter = new FileFilter() {

      private final List<String> exts = Arrays.asList("jpeg", "jpg", "png", "bmp", "gif","mp3");

      public boolean accept(File pathname) {
         String ext;
         String path = pathname.getPath();
         ext = path.substring(path.lastIndexOf(".") + 1);
         return exts.contains(ext);
      }
   };

   final File [] filesFound = files.listFiles(filter);
   List<String> list = new ArrayList<String>();
   if (filesFound != null && filesFound.length > 0) {
      for (File file : filesFound) {
         list.add(file.getName());
      }
   }
   return list;
}
Bruno_Ferreira
  • 1,305
  • 21
  • 33
Azhar
  • 20,500
  • 38
  • 146
  • 211

10 Answers10

137

here it's a simple:

File file = new File(path);
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
    BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
    buf.read(bytes, 0, bytes.length);
    buf.close();
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Add permission in manifest.xml:

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Fortran
  • 2,218
  • 2
  • 27
  • 33
idiottiger
  • 5,147
  • 2
  • 25
  • 21
  • 9
    Note that `buf.read()` may not read the number of bytes you request. See the javadoc here: http://docs.oracle.com/javase/6/docs/api/java/io/BufferedInputStream.html#read(byte[], int, int) – vaughandroid Sep 05 '13 at 09:33
  • 1
    Don't forget in manifest. – CoolMind Apr 27 '16 at 16:28
  • 1
    If you're going to read the entire file in one hit, there is no need to wrap the FileInputStream in a BufferedInputStream -indeed doing so will use more memory and slow things down as the data will be copied unnecessarily. – Clyde Mar 14 '17 at 01:54
  • 3
    This answer is actually wrong as the first comment notes, despite its high reputation and despite its being accepted. This is unfortunately the dark side of stackoverflow. – President James K. Polk Apr 02 '17 at 18:17
  • @JamesKPolk how about the answer of Siavash? Is it right? – CoderYel May 02 '17 at 19:24
  • @CoderYel: I think so, but I prefer the simplicity of [`DataInputStream.readFully()`](https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html#readFully-byte:A-) – President James K. Polk May 02 '17 at 22:28
  • @JamesKPolk Thanks, I finally use the method of FileUtils.readFileToByteArray. And I read the source code of it, just like Siavash – CoderYel May 04 '17 at 15:52
  • Read only! First 2147483647 bytes ~ 2GB.Because int size = (int) file.length(); – Fortran Oct 15 '17 at 10:18
  • https://stackoverflow.com/questions/8854359/exception-open-failed-eacces-permission-denied-on-android/13569364#13569364 for android 23+ onward – charitha amarasinghe Feb 04 '18 at 06:04
27

The easiest solution today is to used Apache common io :

http://commons.apache.org/proper/commons-io/javadocs/api-release/org/apache/commons/io/FileUtils.html#readFileToByteArray(java.io.File)

byte bytes[] = FileUtils.readFileToByteArray(photoFile)

The only drawback is to add this dependency in your build.gradle app :

implementation 'commons-io:commons-io:2.5'

+ 1562 Methods count

Kishan Donga
  • 2,851
  • 2
  • 23
  • 35
Renaud Boulard
  • 709
  • 6
  • 9
23

Since the accepted BufferedInputStream#read isn't guaranteed to read everything, rather than keeping track of the buffer sizes myself, I used this approach:

    byte bytes[] = new byte[(int) file.length()];
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    DataInputStream dis = new DataInputStream(bis);
    dis.readFully(bytes);

Blocks until a full read is complete, and doesn't require extra imports.

lase
  • 2,508
  • 2
  • 24
  • 35
22

Here is a solution that guarantees entire file will be read, that requires no libraries and is efficient:

byte[] fullyReadFileToBytes(File f) throws IOException {
    int size = (int) f.length();
    byte bytes[] = new byte[size];
    byte tmpBuff[] = new byte[size];
    FileInputStream fis= new FileInputStream(f);;
    try {

        int read = fis.read(bytes, 0, size);
        if (read < size) {
            int remain = size - read;
            while (remain > 0) {
                read = fis.read(tmpBuff, 0, remain);
                System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
                remain -= read;
            }
        }
    }  catch (IOException e){
        throw e;
    } finally {
        fis.close();
    }

    return bytes;
}

NOTE: it assumes file size is less than MAX_INT bytes, you can add handling for that if you want.

Siavash
  • 7,583
  • 13
  • 49
  • 69
  • 1
    Thanks. Substitute 'jsonFile' with 'f'. – CoolMind Apr 27 '16 at 15:29
  • You make it very confusing by calling the buffer size and the file size by the same name: "size". This way you will have a buffer size of the size of the file which means no buffer, your loop will never be executed. – FlorianB Nov 29 '16 at 00:17
  • @FlorianB The hope is that the loop never gets executed. in the best case scenario, the entire file will be read in the first call to `fis.read(bytes, 0, size);`... the loop is there just in case the file is too big and the system doesn't read the whole file, in which case we enter the loop and read the rest in consecutive calls to fis.read(). file.read() doesn't guarantee that all the bytes that were requested of it can be read in one call, and the return value is the number of bytes ACTUALLY read. – Siavash Mar 14 '17 at 07:20
4

If you want to use a the openFileInput method from a Context for this, you can use the following code.

This will create a BufferArrayOutputStream and append each byte as it's read from the file to it.

/**
 * <p>
 *     Creates a InputStream for a file using the specified Context
 *     and returns the Bytes read from the file.
 * </p>
 *
 * @param context The context to use.
 * @param file The file to read from.
 * @return The array of bytes read from the file, or null if no file was found.
 */
public static byte[] read(Context context, String file) throws IOException {
    byte[] ret = null;

    if (context != null) {
        try {
            InputStream inputStream = context.openFileInput(file);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            int nextByte = inputStream.read();
            while (nextByte != -1) {
                outputStream.write(nextByte);
                nextByte = inputStream.read();
            }

            ret = outputStream.toByteArray();

        } catch (FileNotFoundException ignored) { }
    }

    return ret;
}
Nathan F.
  • 3,250
  • 3
  • 35
  • 69
1

In Kotlin you can simply use:

File(path).readBytes()
Syscall
  • 19,327
  • 10
  • 37
  • 52
Unes
  • 312
  • 7
  • 12
0

You can also do it this way:

byte[] getBytes (File file)
{
    FileInputStream input = null;
    if (file.exists()) try
    {
        input = new FileInputStream (file);
        int len = (int) file.length();
        byte[] data = new byte[len];
        int count, total = 0;
        while ((count = input.read (data, total, len - total)) > 0) total += count;
        return data;
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
    finally
    {
        if (input != null) try
        {
            input.close();
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
    return null;
}
razz
  • 9,770
  • 7
  • 50
  • 68
0

A simple InputStream will do

byte[] fileToBytes(File file){
    byte[] bytes = new byte[0];
    try(FileInputStream inputStream = new FileInputStream(file)) {
        bytes = new byte[inputStream.available()];
        //noinspection ResultOfMethodCallIgnored
        inputStream.read(bytes);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bytes;
}
Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
0

Following is the working solution to read the entire file in chunks and its efficient solution to read the large files using a scanner class.

   try {
        FileInputStream fiStream = new FileInputStream(inputFile_name);
        Scanner sc = null;
        try {
            sc = new Scanner(fiStream);
            while (sc.hasNextLine()) {
                String line = sc.nextLine();
                byte[] buf = line.getBytes();
            }
        } finally {
            if (fiStream != null) {
                fiStream.close();
            }

            if (sc != null) {
                sc.close();
            }
        }
    }catch (Exception e){
        Log.e(TAG, "Exception: " + e.toString());
    }
0

To read a file in bytes, often used to read binary files, such as pictures, sounds, images, etc. Use the method below.

 public static byte[] readFileByBytes(File file) {

        byte[] tempBuf = new byte[100];
        int byteRead;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
            while ((byteRead = bufferedInputStream.read(tempBuf)) != -1) {
                byteArrayOutputStream.write(tempBuf, 0, byteRead);
            }
            bufferedInputStream.close();
            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
Richard Kamere
  • 749
  • 12
  • 10