Java'da bayt [] olarak dosya


757

Nasıl dönüştürebilirim java.io.Filea byte[]?


Aklıma gelen bir kullanım dosyadan serileştirilmiş nesneleri okumaktır.
Mahm00d

2
Bir diğeri, başlığı kullanarak dosya türünü bulmaktır.
James P.

Bu baytı deneyin [] bytes = null; BufferedInputStream fileInputStream = null; {Dosya dosyası = yeni Dosya'yı (dosyaYolu) deneyin; fileInputStream = yeni BufferedInputStream (yeni FileInputStream (dosya)); // fileInputStream = Thread.currentThread (). getContextClassLoader (). getResourceAsStream (this.filePath); bytes = yeni bayt [(int) file.length ()]; fileInputStream.read (bayt); } catch (FileNotFoundException ex) {atmak; }
Rohit Chaurasiya

Yanıtlar:


486

Sizin için en iyi ne anlama geldiğine bağlıdır. Verimlilik açısından, tekerleği yeniden icat etmeyin ve Apache Commons kullanın. Hangisi burada IOUtils.toByteArray(InputStream input).


29
@ymajoros: Çok doğru! Başka bir bağımlılık daha fazla kod satırları tercih ediyorum. Bağımlılıkların gizli maliyetleri vardır. Bu kütüphane ile güncel kalmak, yapı komut dosyası vb bağımlılığı dahil, kodunuzu vb kullanarak insanlarla iletişim gerekir. Zaten bunu kullanmak için kodu olan bir kütüphane kullanıyorsanız, otherwsie söyleyebilirim kendiniz yazın.
Stijn de Witt

11
Bu, bir dosyanın nasıl okunacağı sorusuna cevap verir, ancak java.IO.File türündeki bir nesnenin byte [] 'a nasıl dönüştürüleceği sorusuna cevap vermez.
Ingo

5
Bu nasıl bir okuma için kullanılır Fileiçin byte[]? Java6 kullanıyorum, bu yüzden NIO yöntemlerini kullanamıyorum :(
PASTRY

4
@ymajoros bizimle herhangi bir "standart 3-hat çözümünü" paylaşır mısın, bu yüzden tekerleğin yeniden keşfedilmesine bağımlı olmamız gerekmez mi?
matteo

3
@matteo: herhangi biri? Diğer yanıtlara bakın, örneğin Files.readAllBytes (). Basit, bağımlılık yok.
ymajoros

1292

Gönderen JDK 7 kullanabilirsinizFiles.readAllBytes(Path) .

Misal:

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

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

10
Bir Dosya nesnesi var, bir yol değil (http posta isteğinden)
aldo.roman.nurena

81
@ aldo.roman.nurena JDK7 size bir Yol Nesnesi verecek bir File.toPath () yöntemi sundu.
KevinL

6
Bir Dosyadan Yol alabilirsiniz. Deneyin: File file = new File ("/ yol"); Yol yolu = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (yol);
gfelisberto

2
Java.nio dosyasında dosya kapama nasıl ele alınır - başka bir deyişle, yukarıdaki kod bir şeyi kapatmalı mı?
akauppi

4
@akauppi Yanıttaki bağlantıya bakın: "Yöntem dosyanın kapatılmasını sağlar ..."
Bernhard Barker

226

JDK 7'den beri - bir astar:

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

Harici bağımlılık gerekmez.


13
Bu artık Apache Commons gerektiren kabul edilen cevaptan daha iyi bir seçim.
james.garriss

1
Teşekkürler :) Ben de buna ihtiyacım var: String text = new String (Files.readAllBytes (yeni Dosya ("/ path / to / file"). ToPath ())); orijinali stackoverflow.com/a/26888713/1257959
cgl

5
Android'de, minimum API seviyesinin 26 olması gerekir.
Ashutosh Chamoli

2
Eklemeniz gerekecek import java.nio.file.Files;ve import java.nio.file.Paths;henüz yapmadıysanız.
Sam

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

Java 8 belgeleri: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html


2
F.read () dönüş değerini kontrol etmelisiniz. Burada bazen tüm dosyayı okumazsınız olabilir.
bugs_

8
Bu durum yalnızca dosyayı okurken değişiyorsa oluşabilir. Diğer tüm durumlarda IOException atılır. Bu sorunu çözmek için dosyayı okuma-yazma modunda açmanızı öneririm: RandomAccessFile (fileName, "rw")
Dmitry Mitskevich

5
Dosyanın sadece bir kısmını okumak için diğer kaynakları hayal edebiliyordum (Dosya ağ paylaşımında ...) readFully () aradığınız sözleşmeye sahip.
DThought

3
RandomAccessFile öğesinin iş parçacığı için güvenli olmadığını unutmayın. Bu nedenle, bazı durumlarda senkronizasyon gerekebilir.
bancer

@DmitryMitskevich Dosya sistemlerinde, muhtemelen uyumsuz olan başka durumlar da vardır. örneğin / proc / linux'daki "dosyaları" okumak kısa okumalara neden olabilir (yani hepsini okumak için bir döngüye ihtiyacınız vardır)
nos

78

Temelde onu bellekte okumak zorundasınız. Dosyayı açın, diziyi ayırın ve içeriği dosyadan diziye okuyun.

En basit yol buna benzer bir şeydir:

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();
}

Bu dosya içeriğinin bazı gereksiz kopyalama (: dosyadan aslında veri üç kez kopyalanır vardır buffer, gelen bufferiçin ByteArrayOutputStreamgelen ByteArrayOutputStreamfiili çıkan dizi).

Ayrıca, bellekte yalnızca belirli bir boyuta kadar olan dosyaları okuduğunuzdan emin olmanız gerekir (bu genellikle uygulamaya bağlıdır) :-).

Ayrıca IOExceptiondış işlevi de tedavi etmeniz gerekir .

Başka bir yol şudur:

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;
}

Bunun gereksiz bir kopyalaması yoktur.

FileTooBigExceptionözel bir uygulama istisnasıdır. MAX_FILE_SIZESabiti bir uygulama parametreleri olduğunu.

Büyük dosyalar için muhtemelen bir akış işleme algoritması düşünmeli veya bellek eşleme kullanmalısınız (bkz. java.nio).


ios deneyin dışında ilan edilmesi gerekiyor
Daryl Spitzer

İkinci örnekteki "ios.read (buffer)" ifadesi, yalnızca dosyanın ilk 4096 baytında okunacaktır (ilk örnekte kullanılanla aynı 4k tamponu olduğu varsayılarak). İkinci örnek çalışması için, okuma -1 sonucunu (dosya sonuna ulaşıldı) kontrol eden bir while döngüsü içinde olması gerektiğini düşünüyorum.
Stijn de Witt

Maalesef yukarıdaki açıklamamı reddet, ifade ayar arabelleğini dosya uzunluğuna kaçırdı. Yine de ilk örneği daha çok seviyorum. Bir dosyanın tamamını tek seferde bir arabellekte okumak ölçeklenebilir değildir. Dosya büyük olduğunda hafızanın tükenme riskiyle karşılaşırsınız.
Stijn de Witt

"En basit" yöntem, kaynaklarla denemeden faydalanır.
Sina Madani

Havalı, ama biraz ayrıntılı.
Sapphire_Brick

77

Birinin söylediği gibi, Apache Commons File Utils aradığınızı alabilir

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

Örnek kullanım ( 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

Bunu yapmak için NIO API'sini de kullanabilirsiniz. Toplam dosya boyutu (bayt cinsinden) bir int sığacak sürece bu kodla bunu yapabilirdi.

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 kullanarak beri onun çok hızlı düşünüyorum.


2
dosyayı yalnızca bir kez okuyacaksanız bellek eşlemesini kullanmaya gerek yoktur ve normal bir FileInputStream kullanmaktan iki kat daha fazla bellek kullanır.
james

1
Maalesef MappedByteBuffer otomatik olarak yayınlanmaz.
Tom Hawtin - çakmak hattı

2
harika, yeni örnek printStackTrace, klasik kırık istisna işleme içerir.
james

Kabul ediyorum .. Tutulmanın koyduğu varsayılan şeyler. İstisnaları yeniden düşünmem gerektiğini düşünüyorum!
Amit

Bir Dosyadan bir bayt [] oluşturmak için nio'yu karşılaştırıyorum. Doğrudan bir arabellek kullanmaktan başka iki kat daha fazla bellek gerektirir. Çok büyük dosyalar için daha hızlı olmasına rağmen (200M için arabelleklenmiş bir IO'nun yaklaşık iki katı kadar hızlı), 5M civarındaki dosyalar için 5 kat kaybediyor gibi görünüyor.
Chaffers

22

Java 8'iniz yoksa ve bana birkaç satır kod yazmaktan kaçınmak için büyük bir kütüphane eklemenin kötü bir fikir olduğunu kabul ediyorsanız:

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();
}

Akışı kapatmak için Arayan sorumludur.


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;
    }

Ayrıca, döngü içine numRead koyun. Değişkenleri mümkün olan en küçük kapsamda bildirin. While döngüsünün dışına koymak, yalnızca bu karmaşık "while" testini etkinleştirmek için gereklidir; döngü içinde EOF testi yapmak daha iyi olur (ve eğer meydana gelirse bir EOFException özel durumu oluşturur).
erickson

throw new IOException("File is too large!");dosya çok büyük olduğunda ne yapmalıyız? Bununla ilgili herhangi bir örnek var mı?
Fer

21

Bunu yapmanın basit yolu:

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);

Daha önce bahsedilen tek gömlekler gibi daha basit yollar vardır.
Sapphire_Brick

@Sapphire_Brick Daha basit yollar evet - ancak tek astarlar her duruma uymuyor. Android gibi.
Behr

17

Dosyadan bayt okumanın en kolay yolu

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
"En basit yol" olmayı savunuyorum :)
BlondCode

Burada açıklayabilir misiniz? Neden tartışıyorsun?
Muhammed Sadık

3
Özel bir şey yok, ama en basit olduğunu söylüyorsunuz ve daha basit çözümler görüyorum -> bence en basit değil. Belki birkaç yıl önceydi, ama dünya değişiyor. Kendi çözümlerimi böyle bir ifadeyle etiketlemem. ;) Eğer sadece "Bence en basit .." ya da "bulduğum en basit .." yazmış olsaydın Seni rahatsız etmek istemiyorum, sadece bunu iletmekten hoşlandım.
BlondCode

@MuhammadSadiq: hiçbir şey ithal etmeyin .*, kötü uygulama olarak kabul edilir.
Sapphire_Brick

13

Guava'da size sunmak için Files.toByteArray () vardır . Birkaç avantajı vardır:

  1. Dosyaların 0 uzunluğunu bildirdiği ancak yine de içeriğe sahip olduğu köşe durumunu kapsar
  2. Son derece optimize edilmiştir, dosyayı yüklemeye çalışmadan önce büyük bir dosyada okumaya çalışırsanız OutOfMemoryException alıyorsunuz. (File.length () işlevini akıllıca kullanarak)
  3. Tekerleği yeniden icat etmek zorunda değilsiniz.

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);

Bu hangi JDK seviyesi?
Jonathan S. Fisher

11

Topluluk wiki yanıtıyla aynı yaklaşımı kullanarak, ancak daha temiz ve kutudan derleme (Apache Commons kütüphanelerini, örneğin Android'de içe aktarmak istemiyorsanız tercih edilen yaklaşım):

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

Bunun en kolay yol olduğuna inanıyorum:

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

7
2009'da Tom'un bu öneriyle zaten bir cevap var
Knut Herrmann

7

ReadFully Geçerli dosya işaretçisinden başlayarak bu dosyadan b.length baytlarını bayt dizisine okur. Bu yöntem, istenen bayt sayısı okunana kadar dosyadan tekrar tekrar okur. Bu yöntem, istenen bayt sayısı okunana kadar, akışın sonu algılanıncaya veya bir istisna atılana kadar engellenir.

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

5

Baytları önceden ayrılmış bir bayt arabelleğine okumak istiyorsanız, bu cevap yardımcı olabilir.

İlk tahmininiz muhtemelen InputStream read(byte[]) . Bununla birlikte, bu yöntemin kullanımı mantıksız bir şekilde zorlaştıran bir kusuru vardır: EOF ile karşılaşılmasa bile dizinin tamamen doldurulacağına dair bir garanti yoktur.

Bunun yerine bir göz atın DataInputStream readFully(byte[]). Bu, giriş akışları için bir sarıcıdır ve yukarıda belirtilen sorunu içermez. Ayrıca, bu yöntem EOF ile karşılaşıldığında atar. Çok daha hoş.


4

Aşağıdaki yol sadece bir java.io.File dosyasını bir bayta [] dönüştürmekle kalmaz, aynı zamanda birçok farklı Java dosyası okuma yöntemini test ederken bir dosyada okumanın en hızlı yolu olduğunu buldum birbirine karşı :

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

Üçüncü taraf kitaplıkları kullanmadan başka bir çözüm ekleyeyim. Scott ( link ) tarafından önerilen bir istisna işleme modelini yeniden kullanır . Ve çirkin bölümünü ayrı bir mesaja taşıdım (bazı FileUtils sınıflarında saklıyorum;))

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

Dosyadan bayt okumanın başka bir yolu

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();
        }
    }

oyuk blokları kullanmayın. hata ayıklamayı zorlaştırır.
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
Bu kod soruya bir çözüm sunabilse de, neden / nasıl çalıştığına ilişkin bağlam eklemek daha iyidir. Bu, gelecekteki kullanıcıların bu bilgileri öğrenmelerine ve kendi kodlarına uygulamalarına yardımcı olabilir. Kod açıklandığında, kullanıcılardan upvotes şeklinde olumlu geri bildirimler almanız da olasıdır.
borchvm

Gelecek yazılarda akılda tutacağım önemli kısım bu. Yararlı bilgileriniz için teşekkürler.
Usama Mehmood

0

Bunu dene :

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);
}

Bu, başka bir JRE'de çalıştırılırsa uygulamayı kıracak belirli bir JRE uygulaması gerektirir.
rattaman

2
küçük hata: IOException değil, IOexception, ama teşekkürler :)
Matan Marciano

1
@MatanMarciano: benim kötü
Sapphire_Brick

-7

In JDK8

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

2
Fransızca konuşan arkadaşımın sorusunu okuyun, bir "byte []" biçimine dönüştürmeyi sorar ve cevabınız bunu sağlamaz.
Kaiser Keister

2
Bu, bayta [] dönüştürmek için yanıt vermek için bile uzak bir seçenek sağlamaz!
Anddo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.