txt - sobreescribir un archivo en java




¿Cómo creo una cadena Java a partir del contenido de un archivo? (20)

He estado usando el lenguaje de abajo desde hace algún tiempo. Y parece ser la más extendida, al menos en los sitios que he visitado.

¿Hay una forma mejor / diferente de leer un archivo en una cadena en Java?

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

Utilizando JDK 8 o superior:

no se utilizan bibliotecas externas

Puede crear un nuevo objeto String a partir del contenido del archivo (utilizando clases del paquete java.nio.file ):

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

Lee todo el texto de un archivo

Aquí hay un lenguaje compacto y robusto para Java 7, envuelto en un método de utilidad:

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

Leer líneas de texto de un archivo.

Java 7 agregó un método conveniente para leer un archivo como líneas de texto, representado como una List<String> . Este enfoque es "con pérdida" porque los separadores de línea se eliminan del final de cada línea.

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

En Java 8, BufferedReader agregó un nuevo método, lines() para producir un Stream<String> . Si se encuentra una IOException al leer el archivo, se envuelve en una excepción UncheckedIOException , ya que Stream no acepta lambdas que arrojan excepciones marcadas.

try (BufferedReader r = Files.newBufferedReader(path, encoding)) {
  r.lines().forEach(System.out::println);
}

También hay un método de Files.lines() que hace algo muy similar, devolviendo el Stream<String> directamente. Pero no me gusta. The Stream necesita una llamada close() ; esto está mal documentado en la API, y sospecho que muchas personas ni siquiera notan que Stream tiene un método close() . Entonces tu código se vería muy similar, así:

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

La diferencia es que tienes un Stream asignado a una variable, y trato de evitarlo como práctica para no intentar invocar el flujo accidentalmente dos veces.

Utilización de la memoria

El primer método, que conserva los saltos de línea, puede requerir temporalmente memoria varias veces el tamaño del archivo, ya que durante un breve período de tiempo el contenido sin procesar del archivo (una matriz de bytes) y los caracteres decodificados (cada uno de los cuales es de 16 bits, incluso si están codificados) como 8 bits en el archivo) residen en la memoria a la vez. Es más seguro aplicar a los archivos que sabe que son pequeños en relación con la memoria disponible.

El segundo método, la lectura de líneas, suele ser más eficiente en la memoria, ya que el buffer de bytes de entrada para la decodificación no necesita contener el archivo completo. Sin embargo, todavía no es adecuado para archivos que son muy grandes en relación con la memoria disponible.

Para leer archivos grandes, necesita un diseño diferente para su programa, uno que lea un fragmento de texto de una secuencia, lo procese y luego pase a la siguiente, reutilizando el mismo bloque de memoria de tamaño fijo. Aquí, "grande" depende de las especificaciones de la computadora. Hoy en día, este umbral puede ser de muchos gigabytes de RAM. El tercer método, usando un Stream<String> es una forma de hacer esto, si sus "registros" de entrada son líneas individuales. (El uso del método readLine() de BufferedReader es el equivalente de procedimiento de este enfoque).

Codificación de caracteres

Una cosa que falta en la muestra en la publicación original es la codificación de caracteres. Hay algunos casos especiales en los que el valor predeterminado de la plataforma es lo que desea, pero son raros, y debería poder justificar su elección.

La clase StandardCharsets define algunas constantes para las codificaciones requeridas de todos los tiempos de ejecución de Java:

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

La plataforma predeterminada está disponible desde la Charset clase Charset :

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

Nota: Esta respuesta reemplaza en gran medida mi versión de Java 6. La utilidad de Java 7 simplifica de forma segura el código, y la respuesta anterior, que utiliza un búfer de bytes asignado, impidió que el archivo que se leyó se eliminara hasta que el búfer asignado se recogiera como basura. Puede ver la versión anterior a través del enlace "editado" en esta respuesta.


Basado en la respuesta de @erickson`s, puedes usar:

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

Commons FileUtils.readFileToString :

public static String readFileToString(File file)
                       throws IOException

Lee el contenido de un archivo en una cadena usando la codificación predeterminada para la máquina virtual. El archivo siempre está cerrado.

Parámetros:

  • file - el archivo para leer, no debe ser nulo

Devoluciones: el contenido del archivo, nunca nulo.

Emite: - IOException - en caso de un error de E / S

Desde: Commons IO 1.3.1

El código utilizado (indirectamente) por esa clase es:

IOUtils.java bajo la Licencia Apache 2.0 .

public static long copyLarge(InputStream input, OutputStream output)
       throws IOException {
   byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
   long count = 0;
   int n = 0;
   while (-1 != (n = input.read(buffer))) {
       output.write(buffer, 0, n);
       count += n;
   }
   return count;
}

Es muy similar al usado por Ritche_W.


Desde esta página una solución muy magra:

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

o

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

Si quieres configurar el charset


Desde JDK 11:

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

En una línea (Java 8), suponiendo que tiene un Reader:

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

Ese código normalizará los saltos de línea, lo que puede o no ser lo que realmente desea hacer.

Aquí hay una alternativa que no lo hace, y que es (IMO) más fácil de entender que el código NIO (aunque todavía usa 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();
    }        
}

Existe una variación en el mismo tema que utiliza un bucle for, en lugar de un bucle while, para limitar el alcance de la variable de línea. Si es "mejor" es una cuestión de gusto personal.

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

Java intenta ser extremadamente general y flexible en todo lo que hace. Como resultado, algo que es relativamente simple en un lenguaje de scripting (su código sería reemplazado por " open(file).read() " en python) es mucho más complicado. No parece haber una forma más corta de hacerlo, excepto el uso de una biblioteca externa (como mencionó Willi aus Rohr ). Sus opciones:

  • Utilice una biblioteca externa.
  • Copia este código en todos tus proyectos.
  • Crea tu propia mini-biblioteca que contiene funciones que usas a menudo.

Su mejor apuesta es probablemente la segunda, ya que tiene las menores dependencias.


Puedes probar Scanner y File class, una solución de pocas líneas.

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

Reunió todas las formas posibles de leer el archivo como una cadena desde el disco o la red.

  • Guayaba: Google usando clases Resources , 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 - COMMONS IO usando las clases IOUtils, FileUtils

    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 usando Stream 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()));
    }
    
  • Clase de escáner con expresiones regulares \A que coincide con el inicio de entrada.

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

Ejemplo con método principal para acceder a los métodos anteriores.

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

@ver

  • Formas de convertir un InputStream en una cadena

Si está buscando una alternativa que no implique una biblioteca de terceros (por ejemplo, Commons I / O ), puede usar la clase Scanner :

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

Si necesita un procesamiento de cadenas (procesamiento paralelo), Java 8 tiene la gran API de Stream.

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

Más ejemplos están disponibles en ejemplos de JDK sample/lambda/BulkDataOperations que se pueden descargar desde la página de descarga de Oracle Java SE 8

Otro ejemplo de liner.

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

Tenga en cuenta que cuando use fileInputStream.available() el número entero devuelto no tiene que representar el tamaño real del archivo, sino la cantidad de bytes estimada que el sistema debería poder leer desde la secuencia sin bloquear IO. Una forma segura y simple podría verse así.

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

Se debe considerar que este enfoque no es adecuado para codificaciones de caracteres de múltiples bytes como UTF-8.


Una solución flexible que utiliza IOUtils de Apache commons-io en combinación con StringWriter :

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

Funciona con cualquier lector o flujo de entrada (no solo con archivos), por ejemplo, al leer desde una URL.


Usuario java.nio.Files para leer todas las líneas de archivo.

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

Guava tiene un método similar al de Commons IOUtils que Willi aus Rohr mencionó:

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

// ...

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

EDITADO por Oscar Reyes

Este es el código subyacente (simplificado) en la biblioteca citada:

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

Editar (por Jonik): Lo anterior no coincide con el código fuente de las versiones recientes de Guava. Para la fuente actual, vea las clases Files , CharStreams , ByteSource y CharSource en el paquete com.google.common.io .


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

Desde java 7 puedes hacerlo de esta manera.


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




io