Bir dosyanın içeriğinden nasıl Java dizesi oluşturabilirim?


1513

Bir süredir aşağıdaki deyimi kullanıyorum. Ve en azından ziyaret ettiğim sitelerde en geniş yayılmış gibi görünüyor.

Java'da bir dizeye dosya okumak için daha iyi / farklı bir yol var mı?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}

7
Biri bana NIO'da ne olduğunu çok basit bir şekilde açıklayabilir mi? Her okuduğumda kanalın
nihayetinde kayboluyorum

7
dosyadaki satır ayırıcısının, sistemin satır ayırıcısıyla aynı olması gerekmediğinin garanti edilmediğini unutmayın.
Henrik Paul

138
Sonunda, okuyucuyu kapatan uygun bir deneme ekler misiniz? Birisi bu örneği kullanabilir ve koduna bir hata verebilir.
Hans-Peter Störr

6
Yukarıdaki kod, son satıra yeni satır karakterleri ekleme hatası veriyor. Aşağıdaki gibi bir şey olmalıdır (line = reader.readLine ())! = Null) {stringBuilder.append (line); } while (line = reader.readLine ())! = null) {stringBuilder.append (ls); stringBuilder.append (satır); }
Derin

27
Java 7 byte[] Files.readAllBytes(file);, 'tek satırlı' Tarayıcı çözümünü önerenlere tanıtıyor : Kapatmanıza gerek yok mu?
Val

Yanıtlar:


1534

Bir dosyadaki tüm metni okuma

Java 11, küçük dosyaları satır sonlandırıcılarını koruyarak okumak için readString () yöntemini ekledi String:

String content = Files.readString(path, StandardCharsets.US_ASCII);

Java 7 ve 11 arasındaki sürümler için, bir yardımcı program yöntemiyle sarılmış kompakt, sağlam bir deyim:

static String readFile(String path, Charset encoding) 
  throws IOException 
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

Dosyadaki metin satırlarını okuma

Java 7 bir katma metin satırı gibi bir dosyayı okumak için kolaylık yöntemini bir olarak temsil List<String>. Bu yaklaşım "kayıplıdır" çünkü çizgi ayırıcılar her çizginin sonundan çıkarılır.

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java 8, Files.lines()a Stream<String>. Yine, bu yöntem kayıptır çünkü hat ayırıcılar soyulmuştur. Bir ederse IOExceptiondosya okunurken karşılaşıldığında, bir sarılır UncheckedIOExceptionberi, Streamkontrol istisnalar atmak lambdas kabul etmez.

try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

Bunun Streamiçin bir close()çağrı gerekir ; Bu API üzerinde kötü bir şekilde belgelenmiştir ve birçok insanın bile Streambir close()yöntemi olduğunu fark etmediğinden şüpheleniyorum . Gösterildiği gibi bir ARM bloğu kullandığınızdan emin olun.

Dosya dışında bir kaynakla çalışıyorsanız lines(), BufferedReaderbunun yerine yöntemi kullanabilirsiniz .

Bellek kullanımı

Satır sonlarını koruyan ilk yöntem, geçici olarak dosyanın boyutunun birkaç katı bellek gerektirebilir, çünkü kısa bir süre için ham dosya içeriği (bayt dizisi) ve kodu çözülmüş olsa bile her biri 16 bit olan kod çözme karakterleri dosyada 8 bit gibi) aynı anda bellekte bulunur. Kullanılabilir belleğe göre küçük olduğunu bildiğiniz dosyalara başvurmak en güvenli yöntemdir.

İkinci yöntem olan satırları okumak genellikle bellek açısından daha verimlidir, çünkü kod çözme için girdi bayt tamponunun tüm dosyayı içermesi gerekmez. Bununla birlikte, kullanılabilir belleğe göre çok büyük dosyalar için hala uygun değildir.

Büyük dosyaları okumak için, programınız için bir akıştaki bir metni okuyan, işleyen ve daha sonra aynı sabit boyutlu bellek bloğunu yeniden kullanan farklı bir tasarıma ihtiyacınız vardır. Burada "büyük" bilgisayar özelliklerine bağlıdır. Günümüzde, bu eşik birçok gigabayt RAM olabilir. Üçüncü yöntem, a'yı kullanmak Stream<String>, girdilerinizin "kayıtlarının" tek tek satırlar olması durumunda bunu yapmanın bir yoludur. ( readLine()Yöntemini kullanmak BufferedReaderbu yaklaşımın prosedürel eşdeğeridir.)

Karakter kodlaması

Orijinal yazıdaki örnekte eksik olan bir şey karakter kodlamasıdır. Platform varsayılanının istediğiniz gibi olduğu bazı özel durumlar vardır, ancak bunlar nadirdir ve seçiminizi haklı çıkarmanız gerekir.

StandardCharsetsSınıf tüm Java çalıştırmalar gerekli kodlamaların bazı sabitleri tanımlar:

String content = readFile("test.txt", StandardCharsets.UTF_8);

Platform varsayılan edinilebilir sınıfın kendisi:Charset

String content = readFile("test.txt", Charset.defaultCharset());

Not: Bu yanıt büyük ölçüde Java 6 sürümümün yerini alıyor. Java 7'nin yardımcı programı kodu güvenli bir şekilde basitleştirir ve eşlenen bir bayt tamponu kullanan eski yanıt, eşlenen tampon çöp toplanana kadar okunan dosyanın silinmesini önledi. Eski sürümü bu yanıttaki "düzenlenmiş" bağlantı üzerinden görüntüleyebilirsiniz.


3
Teknik olarak, zaman ve mekanda O (n). Niteliksel olarak, Dizelerin değişmezlik gereksinimi nedeniyle, bellekte oldukça zordur; geçici olarak hafızadaki karakter verisinin iki kopyası ve kodlanmış baytlar için yer vardır. Bazı tek baytlık kodlama varsayarsak, dosyadaki her karakter için (geçici olarak) 5 bayt bellek gerektirir. Soru özellikle bir String istediğinden, bunu gösterdim, ancak "kod çözme" ile döndürülen CharBuffer ile çalışabiliyorsanız, bellek gereksinimi çok daha azdır. Zaman açısından, çekirdek Java kütüphanelerinde daha hızlı bir şey bulacağınızı sanmıyorum.
erickson

5
Olası yazım hatası mı? NIO, java.nio.charset.Charset adında bir Charset (CharSet değil) sınıfına sahiptir. CharSet böyle olmalı mıydı?
Jonathan Wright

31
Not: Bu kodu biraz kullandıktan sonra, dosyayı bu yöntemle okuduktan hemen sonra güvenilir bir şekilde silemeyeceğinizi öğrendim, bu bazı durumlarda sorun olmayabilir, ancak benimki değil. Bu sorunla ilgili olabilir: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 ? Sonunda bu hatadan muzdarip olmayan Jon Skeet'in önerisiyle gittim. Her neyse, sadece diğer insanlar için bilgi vermek istedim, ne olur ne olmaz ...
Sébastien Nussbaumer

5
@ Sébastien Nussbaumer: Ben de bu sorunla karşılaştım. Hatanın "Düzeltilmez" olarak işaretlenmiş olması şaşırtıcı. Bu aslında FileChannel#mapgenel olarak kullanılamaz olduğu anlamına gelir .
Joonas Pulakka

4
@ Sébastien Nussbaumer: Hata Oracle / Sun Bug Veritabanından silindi: "Bu hata mevcut değil." Google, siteyi webcache.googleusercontent.com/search?q=cache:bugs.sun.com/…
bobndrew

351

Harici bir kütüphane kullanmak istiyorsanız, Apache Commons IO'ya (200KB JAR) bakın. Bir içeren org.apache.commons.io.FileUtils.readFileToString()bütün bir okuma sağlayan yöntem Filebir içine Stringbir satır kod ile.

Misal:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}

Bu yöntemi sağladığınız URL'de bulamıyorum.
OscarRyz

2
Org.apache.commons.io.FileUtils
Cyrille Ka

2
Ben de FileUtils kullanıyorum, ama FileUtils veya kabul edilen nio cevap kullanarak daha iyi ne olduğunu merak ediyorum?
Guillaume

4
@Guillaume: En büyük soru, 3. taraf kütüphaneye bağımlı olmak konusunda rahat olup olmadığınızdır. Projenizde Commons IO veya Guava varsa, bunu kullanın (sadece kod basitliği için; aksi takdirde fark edilir bir fark olmayacaktır).
Jonik

183

Aşağıdakilere dayanan çok yalın bir çözüm Scanner:

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Veya karakter kümesini ayarlamak istiyorsanız:

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Veya sizi arayacak bir kaynak denemesi bloğuyla scanner.close():

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

ScannerYapıcı bir atabilir unutmayın IOException. Ve almayı unutmayın java.iove java.util.

Kaynak: Pat Niemeyer blogu


4
\\ A, "dosyanın başka bir başlangıcı" olmadığı için çalışır, bu yüzden aslında son belirteci okursunuz ... ki bu da birincisidir. Asla \\ Z ile denemedim. Ayrıca, Dosyalar, InputStreams, kanallar gibi Okunabilir bir şey okuyabilirsiniz unutmayın ... Bazen bir dosya ya da başka bir okudum emin değilim zaman, tutulma ekran penceresinden okumak için bu kodu kullanın .. .ev, sınıfyolu beni karıştırıyor.
Pablo Grisafi

1
Poster olarak, dosyanın düzgün bir şekilde kapatılıp kapatılmadığını gerçekten bilmiyorum diyebilirim ... Bunu üretim koduna asla yazmam, sadece testler veya hata ayıklama için kullanırım.
Pablo Grisafi

2
Sanırım 1024 karakter sınırı var
Whimusical

20
Tarayıcı Closeable uygular (kaynağa yaklaşır) - bu yüzden zarif olsa da tek astar olmamalıdır. Tamponun varsayılan boyutu 1024'tür, ancak Tarayıcı boyutu gerektiği gibi artıracaktır (bkz. Tarayıcı # makeSpace ())
earcam

8
Bu, a içeren boş dosyalar için başarısız olur java.util.NoSuchElementException.
SpaceTrucker

116
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

java 7'den beri bu şekilde yapabilirsiniz.


Bu cevap olarak kabul edilmelidir - tek satır, dış kütüphaneler yok.
Kiraz

Bu, dosyada olmasa bile sonuna yeni satır karakteri ekledi
Stefan Haberl

79

Üçüncü taraf kitaplığı içermeyen bir alternatif arıyorsanız (ör. Commons I / O ), Tarayıcı sınıfını kullanabilirsiniz :

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());        

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}


3
Bir Dizeyi kabul eden Tarayıcı yapıcısı, dizeyi okunacak dosyanın adı olarak değil, taranacak metin olarak kabul eder. Bu hatayı her zaman yaparım. : - /
Alan Moore

@Lan, iyi yakala. Bunu düzeltmek için Don'un cevabını hafifçe düzenledim (umarım).
Jonik

3
fileContents.append (scanner.nextLine ()) ekleme (lineSeparator.);
ban-jeomühendislik

1
Başlatma ifadesini olarak değiştirin Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));. Aksi takdirde dosyanın yalnızca bir kısmını yakalayabilirsiniz.
Wei Yang

71

Guava , Willi aus Rohr'ın bahsettiği Commons IOUtils'inkine benzer bir yönteme sahiptir:

import com.google.common.base.Charsets;
import com.google.common.io.Files;

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

PiggyPiglet tarafından EDIT
Files#toString kullanımdan kaldırıldı ve Octobor 2019'un kaldırılması gerekiyor. Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

Oscar Reyes tarafından EDIT

Atıfta bulunulan kitaplıktaki (basitleştirilmiş) kod:

InputStream in = new FileInputStream(file);
byte[] b  = new byte[file.length()];
int len = b.length;
int total = 0;

while (total < len) {
  int result = in.read(b, total, len - total);
  if (result == -1) {
    break;
  }
  total += result;
}

return new String( b , Charsets.UTF_8 );

Düzenle (Jonik tarafından): Yukarıdaki, son Guava sürümlerinin kaynak koduyla eşleşmiyor. Geçerli bir kaynak için, sınıflara bakınız Dosyalar , CharStreams , ByteSource ve CharSource içinde com.google.common.io paketin.


Bu kod, büyük dosyalarla bazı çılgın davranışlar ortaya çıkarabilecek uzuntan int'e döküm yapıyor. Fazladan boşluk var ve giriş akışını nerede kapatıyorsunuz?
Mohamed Taher Alrefaie

@MTA: akışı olan kapalı kullanımına dikkat Closeriçinde CharSource . Yanıttaki kod gerçek, geçerli Guava kaynağı değil.
Jonik

54
import java.nio.file.Files;

.......

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }

6
Veya daha da basit:new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));

12
or new String(Files.readAllBytes(Paths.get(filename)));:-)
assafmo

1
İyi oynandı ve bir sonraki adamı Googling'i kurtarmak için Pathsolduğu gibi 1.7+FileSystems . (Dang it!)
ruffin

4
Bu cevabın daha fazla oyu yok. Bir dize içine bir metin dosyası almak için en hızlı ve basit yolu arıyordu. Bu kadar ve aşağı ve aşağı ve aşağı kaydırmasaydım, kaçırırdım. OP bu cevabı en üste taşımak için kabul etmeyi düşünmelidir.
Thorn

@Thorn Bu yanıtın korkunç bir hata yönetimi var. Bu yöntemi üretim kodunda veya daha iyisi için kullanmayın: asla.
xehpuk

51

Bir dize işlemeye (paralel işleme) ihtiyacınız varsa, Java 8 mükemmel Stream API'sine sahiptir.

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines

Oracle Java SE 8 indirme sayfasındansample/lambda/BulkDataOperations indirebileceğiniz JDK örneklerinde daha fazla örnek bulunmaktadır

Başka bir liner örneği

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));

.Parallel (), satırları okuduktan sonra veya bundan önce mi gerçekleşir?
Istvan

Gerçek çalışma, terminal işlemi toplama (...) çağrıldığından başlar. Akış tembel olarak satır satır doldurulur. İşleme başlamadan önce bellekteki tüm dosyayı okumaya gerek yoktur (örn. Filtreleme ve haritalama).
Andrei N

boş olmayan satırları seçmeden önce kırp?
Thorbjørn Ravn Andersen

50

Bu kod, gerçekten yapmak istediğiniz şey olabilir veya olmayabilir satır sonlarını normalleştirecektir.

İşte bunu yapmayan ve anlaşılması kolay bir alternatif (IMO) NIO kodundan daha basit (yine de kullanılmasına rağmen java.nio.charset.Charset):

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}

1
Bu kadar eski bir yorumu canlandırdığım için beni affet, ama "dosya" adlı bir String nesnesini mi geçeceksin, yoksa bunun yerine bir File nesnesi mi olmalı?
Bryan Larson

28

Dosyayı Disk veya Ağdan Dize olarak okumak için tüm olası yolları topladı.

  • Guava: Google sınıfları kullanıyorResources ,Files

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }

  • APACHE - IOUtils, FileUtils sınıflarını kullanarak IO ORTAK

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }

  • Java 8 BufferReader kullanarakStream API

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }

  • Normal ifade ile Tarayıcı Sınıfı \A . girdinin başlangıcıyla eşleşir.

    static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
    public static String streamURL_Scanner( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    public static String streamFile_Scanner( File file ) throws IOException {
        Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }

  • Java 7 (java.nio.file.Files.readAllBytes )

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }

  • BufferedReaderkullanarak InputStreamReader.

    public static String getDiskFile_Lines( File file ) throws IOException {
        StringBuffer text = new StringBuffer();
        FileInputStream fileStream = new FileInputStream( file );
        BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }

Yukarıdaki yöntemlere erişmek için ana yöntemle örnek.

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@görmek


26

Bir metin dosyasıysa neden apache commons-io kullanmıyorsunuz? ?

Aşağıdaki yönteme sahiptir

public static String readFileToString(File file) throws IOException

Satırları liste olarak kullanmak istiyorsanız

public static List<String> readLines(File file) throws IOException

25

JDK 11'den beri:

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8

Neden, ah neden, 2018'de varsayılan karakter setine dayanan yeni yöntemler sunalım?
mryan

2
@mryan bu yöntem varsayılan sistem karakter kümesine bağlı değildir. Varsayılan olarak UTF-8'dir, bu iyidir.
leventov

@leventov haklısın! Files.readAllLines de öyle! dosyaları API eski yöntemlerle çok tutarlı kılan ama daha iyi için :)
mryan

17

Bir dosyayı ikili olarak okumak ve sonunda dönüştürmek için

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}

16

Java 7 ile, UTF-8 dosyasını okumak için tercih ettiğim seçenek:

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");

Java 7'den beri JDK, java.nio.filebirçok kısayol sağlayan yeni API'ye sahiptir, bu nedenle basit dosya işlemleri için 3. taraf kitaplıkları her zaman gerekli değildir.


15

Java, yaptığı her şeyde son derece genel ve esnek olmaya çalışır. Sonuç olarak, bir betik dilinde nispeten basit olan bir şey (kodunuz open(file).read()python'da " " ile değiştirilecek ) çok daha karmaşıktır. Harici bir kütüphane kullanmak dışında ( Willi aus Rohr gibi) bunu yapmanın daha kısa bir yolu yoktur . Seçenekleriniz:

  • Harici bir kütüphane kullanın.
  • Bu kodu tüm projelerinize kopyalayın.
  • Sık kullandığınız işlevleri içeren kendi mini kütüphanenizi oluşturun.

En az bağımlılığınız olduğu için en iyi bahis muhtemelen ikincisidir.


4
Yeap. "Yüksek" dilin farklı bir anlam kazanmasını sağlar. Java, C ile karşılaştırıldığında yüksek seviyededir ancak Python veya Ruby ile karşılaştırıldığında düşüktür
OscarRyz

3
Java'nın yüksek düzey soyutlamalarda uzun, ancak kolaylık yöntemlerinde kısa olduğunu kabul edin
Dónal

3
Doğru, Java'nın Dosyalar ile başa çıkmanın çılgınca bir yolu var ve bunların çoğu karmaşık görünüyor. Ancak bu, daha üst düzey dillerde olanlara oldukça yakın:byte[] bytes = Files.readAllBytes(someFile.toPath());
Thorn

11

JDK 8 veya üstünü kullanarak:

harici kütüphane kullanılmadı

Dosya içeriğinden yeni bir String nesnesi oluşturabilirsiniz ( java.nio.filePaketteki sınıfları kullanarak ):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}

Kim yazdı Moritz Petersen cevabının kopyası: String content = new String (Files.readAllBytes (Paths.get (dosya adı)), "UTF-8");
Jean-Christophe Blanchard

8

Aynı temada, satır değişkeninin kapsamını sınırlamak için while döngüsü yerine for döngüsü kullanan bir varyasyon vardır. "Daha iyi" olup olmadığı kişisel zevk meselesidir.

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}

3
Bu, yeni satırları varsayılan yeni satır seçeneğine değiştirecektir. Bu arzu edilebilir veya istenmeyebilir.
Peter Lawrey

Nokta linedeğişkenin kapsamını daraltmak olduğu için düzenlemeyi bu cevaba geri aldık . Düzenleme bunu iki kez açıkladı, bu da derleme hatası olurdu.
Dan Dyer

7

FilesSınıfa erişiminiz yoksa, yerel bir çözüm kullanabilirsiniz.

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}

çağırmak için örnek karakter kümesi?
Thufir

4

StringWriter ile birlikte Apache commons- io'dan IOUtils kullanan esnek bir çözüm :

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();

Örneğin bir URL'den okurken herhangi bir okuyucu veya giriş akışıyla (yalnızca dosyalarla değil) çalışır.


3

fileInputStream.available()Döndürülen tamsayıyı kullanırken gerçek dosya boyutunu temsil etmek zorunda değildir, aksine sistemin IO'yu engellemeden akıştan okuyabileceği tahmin edilen bayt miktarının farkında olun . Güvenli ve basit bir yol şöyle görünebilir

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}

Bu yaklaşımın UTF-8 gibi çok baytlı karakter kodlamaları için uygun olmadığı düşünülmelidir .


1
Bu kod öngörülemeyen sonuçlar verebilir. Göre belgelerin arasında available()yönteminin, dosyanın sonuna yöntemi tamamlanmamış bir dosya ile sonunda olabilir Bu durumda 0 döndürür durumunda ulaşılır hiçbir garantisi yoktur. Daha da kötüsü, gerçekten okunan bayt sayısı döndürülen değerden daha az olabilir available(), bu durumda bozuk çıktı alırsınız.
wau

3

Bu yöntemi kullanır, RandomAccessFile.readFullyJDK 1.0 kullanılabilir gibi görünüyor!

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}

3

Tarayıcı ve Dosya sınıfını deneyebilirsiniz, birkaç satırlık çözüm

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}

3

Kullanıcı java.nio.Filestüm dosya satırlarını okumak için.

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}

3
public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}

Bu platform varsayılan kodlama kullanarak rahatsızlık os olduğunu düşünüyorum. +1 neyse :)
OscarRyz

7
Bana öyle geliyor ki nihayet blok try bloğunda tanımlanan değişkenleri bilmiyor. javac 1.6.0_21 hata veriyor cannot find symbol.
ceving

Kendi kodunuzu bile denediniz mi? Reader'ı try / catch bloğunda tanımladınız, bu yüzden nihayet blokta erişilebilir olmayacak.
mauron85

2

Henüz diğer girişlere yorum yapamam, o yüzden burada bırakacağım.

Buradaki en iyi yanıtlardan biri ( https://stackoverflow.com/a/326448/1521167 ):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

hala bir kusuru var. Her zaman dizenin sonuna yeni satır karakterleri koyar, bu da bazı tuhaf hatalara neden olabilir. Benim önerim şu şekilde değiştirmektir:

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}

İlk durumda, sonuna ekstra bir satırsonu ekliyor olabilirsiniz. ikinci durumda bir tane atlıyor olabilirsiniz. Yani her ikisi de eşit derecede yanlış. Bkz Bu makaleyi
Patrick Parker

2

Tarayıcıdan sonra Ctrl + F'ing'den sonra, Tarayıcı çözümünün de listelenmesi gerektiğini düşünüyorum. Moda okumak en kolay olan şey şöyle:

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}

Java 7 veya daha yenisini kullanıyorsanız (ve gerçekten de) kodun daha kolay okunmasını sağlamak için kaynakları denemeyi deneyin. Artık her şeyi kirleten nokta yakın şeyler yok. Ama bu çoğunlukla stilistik bir seçim methinks.

Bunu çoğunlukla tamamlama için gönderiyorum, çünkü bunu çok yapmanız gerekiyorsa, java.nio.file.Files içinde bir şeyler olmalı işi daha iyi olmalı.

Benim önerim, tüm baytları almak ve yeni String'e (byte [] karakter kümesi) beslemek için Files # readAllBytes (Yol) kullanmak olacaktır. güvenebileceğiniz bir Dize almak . Karakter setleri yaşamınız boyunca sizin için anlamlı olacaktır, bu yüzden şimdi bu şeylere dikkat edin.

Diğerleri kod ve malzeme verdi ve onların ihtişamını çalmak istemiyorum. ;)


2

Bu kütüphaneyi kullanarak , bir satırdır:

String data = IO.from(new File("data.txt")).toString();

1
kitaplığın içindeki çizgiler sayılmazsa.
Ari

2

Ayrıca dosyanız bir kavanozun içindeyse, bunu da kullanabilirsiniz:

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\\A").next();
    }
}

Yol, / örneğin kavanozunuz

my.jar/com/some/thing/a.txt

O zaman şöyle çağırmak istersiniz:

String myTxt = fromFileInJar("/com/com/thing/a.txt");

2

Bir satırda (Java 8), bir Okuyucunuz olduğunu varsayarsak:

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));

2

@ Erickson'un cevabına dayanarak şunları kullanabilirsiniz:

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}
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.