BufferedWriter não está escrevendo tudo em seu arquivo de saída

Eu tenho um programa em Java que lê algum texto de um arquivo, linha por linha, e grava novo texto em um arquivo de saída. Mas nem todo o texto que escrevo para meu BufferedWriter aparece no arquivo de saída após o término do programa. Por que é que?

Os detalhes: o programa pega um documento de texto CSV e o converte em comandos SQL para inserir os dados em uma tabela. O arquivo de texto tem mais de 10000 linhas semelhantes às seguintes:

 2007,10,9,1,1,1006134,19423882 

O programa parece funcionar bem, exceto que ele pára no arquivo aleatoriamente na metade da criação de uma nova instrução SQL, tendo sido impressa no arquivo SQL. Parece algo como:

 insert into nyccrash values (2007, 1, 2, 1, 4, 1033092, 259916); insert into nyccrash values (2007, 1, 1, 1, 1, 1020246, 197687); insert into nyccrash values (2007, 10, 9, 1 

Isso acontece após cerca de 10.000 linhas, mas várias centenas de linhas antes do final do arquivo. Onde a quebra acontece é entre um 1 e um,. No entanto, os caracteres não parecem importantes porque se eu mudar o 1 para o 42 a última coisa escrita no novo arquivo é 4 , que está cortando o 2 daquele inteiro. Então parece que o leitor ou escritor deve estar morrendo depois de escrever / ler uma certa quantia.

Meu código Java é o seguinte:

 import java.io.*; public class InsertCrashData { public static void main (String args[]) { try { //Open the input file. FileReader istream = new FileReader("nyccrash.txt"); BufferedReader in = new BufferedReader(istream); //Open the output file. FileWriter ostream = new FileWriter("nyccrash.sql"); BufferedWriter out = new BufferedWriter(ostream); String line, sqlstr; sqlstr = "CREATE TABLE nyccrash (crash_year integer, accident_type integer, collision_type integer, weather_condition integer, light_condition integer, x_coordinate integer, y_coordinate integer);\n\n"; out.write(sqlstr); while((line = in.readLine())!= null) { String[] esa = line.split(","); sqlstr = "insert into nyccrash values ("+esa[0]+", "+esa[1]+", "+esa[2]+", "+esa[3]+", "+esa[4]+", "+esa[5]+", "+esa[6]+");\n"; out.write(sqlstr); } } catch(Exception e) { System.out.println(e); } } } 

Você precisa fechar seu OutputStream que irá liberar o restante de seus dados:

 out.close(); 

O tamanho do buffer padrão para BufferedWriter é 8192 caracteres , grande o suficiente para armazenar facilmente centenas de linhas de dados não gravados.

Você deve close() seu BufferedWriter . Você deve close() seu BufferedWriter porque é IS-A Writer e, portanto, implementa AutoCloseable , o que significa (ênfase adicionada) é

Um recurso que deve ser fechado quando não for mais necessário.

Algumas pessoas dizem que você deve primeiro chamar flush() para seu BufferedWriter antes de chamar close() . Eles estão errados. A documentação para BufferedWriter.close() observa que “Fecha o stream, liberando-o primeiro ” (ênfase adicionada).

A semântica documentada de flushing ( flush() ) é

Libera esse stream escrevendo qualquer saída em buffer no stream subjacente

Então, você deve close e close irá liberar qualquer saída em buffer.

Seu arquivo de saída não inclui todo o texto que você escreveu para o BufferedWriter porque ele armazenou parte desse texto em um buffer. O BufferedWriter nunca esvaziou esse buffer, passando-o para o arquivo, porque você nunca disse a ele para fazer isso.


Desde o Java 7, a melhor maneira de garantir um recurso AutoCloseable , como BufferedWriter , é fechado quando não é mais necessário usar o gerenciamento automático de resources (ARM), também conhecido como try-with-resources :

  try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) { // writes to out here } catch (IOException ex) { // handle ex } 

Você também deve close seu BufferedReader quando não precisar mais, portanto, você deve ter blocos nesteds try-with-resources:

  try (BufferedReader in = new BufferedReader(new FileReader("nyccrash.txt")) { try (BufferedWriter out = new BufferedWriter(new FileWriter("nyccrash.sql"))) { // your reading and writing code here } } catch (IOException ex) { // handle ex } 

Um recurso que deve ser fechado quando não for mais necessário.

 finally { out.close();//this would resolve the issue } 

Algumas coisas a considerar:

  • BufferedWriter.close() libera o buffer para o stream subjacente , portanto, se você esquecer de flush() e não fechar, o arquivo pode não ter todo o texto que você escreveu nele.
  • BufferedWriter.close() também fecha o Writer empacotado. Quando isso é um FileWriter, isso acabará por fechar um FileOutputStream e informar o sistema operacional que você acabou de gravar no arquivo.
  • O coletor de lixo chamará automaticamente close() , não no BufferedWriter ou no FileWriter, mas no FileOuputStream. Então, o sistema operacional será feliz, mas você tem que esperar pelo GC.
  • No entanto, você sempre deseja liberar resources do sistema operacional assim que não precisar mais deles. Isso vale para arquivos abertos, conexões de database, filas de impressão … qualquer coisa. Confie em mim.
  • BufferedWriter.close() limpa o buffer de caractere interno, de modo que a memory estará disponível para a garbage collection, mesmo enquanto o BufferedWriter permaneça no escopo.

Então, sempre feche seus resources (não apenas arquivos) quando terminar com eles.

Se você realmente quer dar uma olhada nas capas, a maior parte da fonte da API Java está disponível. O BufferedWriter está aqui .

Seu código não parece estar fechando o gravador depois que você terminar de escrever nele. Adicione um out.close() (de preferência em um bloco final) e ele deve funcionar corretamente.

você dint fecha seu BufferedWriter.close dentro de um bloco finalmente

  finally { out.close();//this would resolve the issue } 

você dint fecha seu BufferedWriter.close dentro de um bloco finalmente

 finally { out.close();//this would resolve the issue } 

Isso funciona. Eu enfrentei o mesmo problema e isso funcionou para mim .. Boa sorte 🙂

Sempre feche seus resources (não apenas arquivos) quando terminar com eles.

  finally { out.close();//this would resolve the issue } 

Pode haver situações em que você deseja liberar o buffer sem fechar o arquivo. Nestas situações, você pode usar o método flush.

Como você está usando o BufferedWriter, também pode liberar o buffer quando apropriado:

 out.flush() 

Isso gravará o restante do buffer no arquivo real. Close-method também libera o buffer e fecha o arquivo.

 out.close() 

Pode haver situações em que você deseja liberar o buffer sem fechar o arquivo. Nestas situações, você pode usar o método flush.

Você também pode usar o método newline do BuffredWriter em vez de adicionar \ n ao final da linha. O método newline usa um separador de linha específico do sistema para que seu código funcione em diferentes plataformas.

 out.newLine()